2010-10-05 15 views
10

Je souhaite une classe générique unique pouvant accepter des types de référence ou de valeur, et effectuer uniquement une action basée sur un test d'égalité. considérer les points suivants:Contraintes génériques: Puis-je tester Equality of generic qui peut être un type de référence ou de valeur?

public class Property<TProp> 
    where TProp : struct, IEquatable<TProp> 
{ 
    public TProp Value; 

    public void SetValue(ObservableObject owner, TProp value) 
    { 
     if (!Value.Equals(value))  // cannot use != on struct constrained TProp 
     { 
      // ... set the property 
     } 
    } 
} 

public class ByRefProperty<TProp> 
    where TProp : class // Dont want to require IEquatable<> on reference type TProp 
{ 
    public TProp Value; 

    public void SetValue(ObservableObject owner, TProp value) 
    { 
     if (Value != value)   
     { 
      // ... set the property 
     } 
    } 
} 

Je vais avoir à utiliser des contraintes génériques et deux classes pour être en mesure de tester la valeur d'égalité de type vs égalité type de référence. Y at-il un moyen de contourner cela pour que je me retrouve avec un seul cours?

Je ne veux pas particulièrement une solution qui implique des types de valeurs de boxe, utilisant la réflexion, ou la génération d'IL à l'exécution. Y a-t-il une solution simple que j'ai manquée ici?

Répondre

15

La meilleure façon de faire cela est généralement EqualityComparer<T>.Default:

public void SetValue(ObservableObject owner, TProp value) 
{ 
    if (!EqualityComparer<TProp>.Default.Equals(Value, value)) 
    { 
     // ... set the property 
    } 
} 

Notez que cette même gère des valeurs nulles pour vous de la manière logique (nul est égal à null mais rien d'autre).

+0

Cela utilisera-t-il une logique Equals personnalisée définie dans l'implémentation de 'IEquatable '? –

+1

@Justin, oui, si le type l'implémente. –

+0

@Jon - Apprenez quelque chose de nouveau tous les jours ... encore une fois. –