2009-05-21 9 views
4

J'essaie d'utiliser des opérations Set avec une classe que j'ai. Chaque instance de cette classe a un identifiant unique. Dois-je implémenter l'interface System.IComparable et si oui, comment le ferais-je?F # Définir à l'aide de la classe personnalisée

type SomeClass(id : int) = 
    member this.ID = id 

let someSet = Set.of_list [SomeClass(1); SomeClass(2)] 
let test = someSet.Contains(SomeClass(2))  

Répondre

4

est ici une implémentation qui devrait fonctionner:

type SomeClass(id : int) =  
    member this.ID = id 
    override this.Equals(o) = 
     match o with 
     | :? SomeClass as sc -> this.ID = sc.ID 
     | _ -> false 
    override this.GetHashCode() = 
     id.GetHashCode() 
    interface System.IComparable with 
     member this.CompareTo(o) = 
      match o with 
      | :? SomeClass as sc -> compare this.ID sc.ID 
      | _ -> -1 
+0

Un grand merci, y a-t-il quelque chose dans le bloc d'alimentation F # qui implémente le motif d'enregistrement actif? Serait cool si je pouvais juste en hériter. Hmm, peut-être que je vais ajouter plus à cette classe et l'utiliser comme tel. – bhd739ge

+0

Voir mon autre réponse. – Brian

+0

Avez-vous pensé à utiliser un dictionnaire au lieu d'un ensemble? – gradbot

1

Je crois que vous aurez besoin de mettre en œuvre IComparer<T> pour compréhensions ensemble (par exemple Set.of_list) au travail.

Cette blog post explique en général comment implémenter des interfaces en F # - (je peux être si mal pasIComparable<T>, qui a tendance à être moins largement utilisé.). Il inclut également un exemple spécifique d'un type implémentant le IComparer<T>, ce qui n'est pas simple comme vous pouvez l'espérer. Laissez-moi savoir si cela fonctionne pour vous. Je soupçonne que vous pourriez en fait avoir besoin d'implémenter le IEqualityComparer<T> à la place, puisque c'est ce que les méthodes d'extension définies par LINQ sont basées, pour autant que je sache. (Il devient vraiment déroutant avec toutes ces interfaces pour comparer la BCL!)

1

En ce qui concerne le commentaire sur mon autre réponse, vous pourriez tenir compte dans une base réutilisable classe, mais je ne suis pas sûr que ce soit vraiment une bonne idée:

type EqCompBase<'EqKey, 
     'DerivedType when 'DerivedType :> EqCompBase<'EqKey,'DerivedType> > 
     (id : 'EqKey) =  
    member this.ID = id 
    override this.Equals(o) = 
     match o with 
     | :? EqCompBase<'EqKey, 'DerivedType> as sc -> this.ID = sc.ID 
     | _ -> false 
    override this.GetHashCode() = 
     id.GetHashCode() 
    interface System.IComparable with 
     member this.CompareTo(o) = 
      match o with 
      | :? EqCompBase<'EqKey, 'DerivedType> as sc -> compare this.ID sc.ID 
      | _ -> -1 

type SomeClass(id : int, otherFieldThatDoesNotMatterForEquality : string) = 
    inherit EqCompBase<int, SomeClass>(id) 

let someSet = Set.of_list [SomeClass(1,"yadda"); SomeClass(2,"blah")] 
let test = someSet.Contains(SomeClass(2,"foo")) 
printfn "%A" test // true 
Questions connexes