2011-08-09 1 views
0

Quelle est la meilleure façon de créer une exception qui contient un type dans lequel il est lancé en F #? Ce qui suit ne fonctionne pas:Comment définir une relation récursive entre un type d'exception et un autre type?

// this fails since HeaderInfo is not yet defined. Can't seem use the and-keyword 
// on HeaderInfo 
exception MissingHeader of string*HeaderInfo 

type HeaderInfo = 
    { 
     DefaultHeaderIndices: Map<string, int>; 
     AdditionalStudyIndices: Map<string, int>; 
     VolumeIndex: int option; 
    } 
    with member this.GetCommonIndex(name) = 
      match this.DefaultHeaderIndices.TryFind(name) with 
      | Some(idx) -> idx 
      | None -> 
       match this.AdditionalStudyIndices.TryFind(name) with 
       | Some(idx) -> idx 
       | None -> 
        match this.VolumeIndex with 
        | Some(idx) when name = optionalHeader -> idx 
        | _ -> raise <| MissingHeader(name, this) 

Merci!

Répondre

6

Vous pouvez utiliser les extensions de type pour ajouter des membres à un type déclaré précédemment. Lorsque vous utilisez l'extension de type dans le même module, le membre est compilé en tant que membre ordinaire (instance) du type, ce qui signifie exactement la même chose qu'un membre ordinaire.

De cette façon, vous pouvez d'abord déclarer HeaderInfo, puis déclarer missingHeader puis ajouter le membre GetCommonIndex au type HeaderInfo.

EDIT: Je pense que vous pouvez rendre le code un peu plus agréable en utilisant des modèles actifs (bien qu'il soit une utilisation légèrement subtile)

type HeaderInfo = 
    { DefaultHeaderIndices: Map<string, int> 
     AdditionalStudyIndices: Map<string, int> 
     VolumeIndex: int option } 

exception MissingHeader of string*HeaderInfo 

let (|TryFind|_|) map key() = Map.tryFind key map 

type HeaderInfo with 
    member this.GetCommonIndex(name) = 
     match(), this.VolumeIndex with 
     | TryFind this.DefaultHeaderIndices name (idx), _ 
     | TryFind this.AdditionalStudyIndices name (idx), _ -> idx 
     | _, Some(idx) when name = optionalHeader -> idx 
     | _ -> raise <| MissingHeader(name, this) 
+0

Merci, fonctionne parfaitement – Rickard

5

réponse Tomas est très bien. Une autre option est de ne pas utiliser

exception Foo ... 

et au lieu d'utiliser

type Foo() = 
    inherit System.Exception() ... 

and OtherRecursiveType ... 

C'est, déclare l'exception en utilisant le formulaire de classe normale, puis utiliser type...and... pour récursion parmi les type s.

Questions connexes