2009-08-18 32 views
3

Quand je dois mettre en œuvre l'égalité pour les comparateursComment traiter les valeurs NULL dans les comparaisons d'égalité?

public class SampleClass 
{ 
    public int Prop { get; set; } 
} 

Dois-je faire

null == new SampleClass() 

et

new SampleClass() == null 

et

new SampleClass().Equals(null) 

faux?

Qu'en est-

new SampleClass() != null 

Faut-il aussi faux?

MISE À JOUR Les gens remettent en question le raisonnement derrière cette question. Il est supposé que ! = Et == soit toujours opposé. Mais si j'implémente les méthodes, toutes les comparaisons ci-dessus aboutissent à false, il y aura un cas où les opérateurs == et! = Aboutiront au même résultat. Donc, c'est un dilemme si! = Devrait retourner vrai ou faux.

Répondre

4

Toutes les comparaisons d'égalité avec null de votre exemple devraient certainement être fausses. Le dernier est également très important cependant:

new SampleClass() != null 

Cela doit certainement évaluer à true, parce que c'est une façon courante de vérifier si une variable de référence a été initialisé. S'il devait évaluer à false, il pourrait involontairement réaffecter la variable partout, car les développeurs C# attendent un certain type de comportement de la part des opérateurs. Un autre exemple:

SampleClass myVar = new SampleClass(); 

// Various stuff happening here, possibly setting myVar to null 

if (myVar != null) 
{ 
    // Programmer go "WTFBBQ?" when he finds this doesn't get executed 
    myVar.DoStuff(); 
} 

Confus, le programmeur change cela:

if (myVar == null) 
{ 
    myVar = new SampleClass(); 
} 

myVar.DoStuff(); // null reference exception, huh? 
7

Est-ce encore une question? Non, null ne devrait jamais être égal à un objet.

Modifier: Et donc par extension, new SampleClass() != null devrait être true. null n'est pas comme NaN; c'est assez bien défini.

1

Je ne suis pas sûr de bien comprendre votre question, mais null n'est (par définition) pas une valeur. En tant que tel,

null == new SampleClass() 

n'a pas vraiment de sens (et, vraiment, aucune des autres comparaisons faire).

Pouvez-vous reformuler votre question?

1

Comme d'autres l'ont dit, nul ne peut jamais être égale à toute autre chose dont nul. C'est parce que null n'est pas une valeur, c'est plutôt un manque de valeur.

Pour votre question spécifique, il semble que vous essayez d'instancier un objet qui n'a pas encore été initialisé et que vous voulez déterminer si cet objet a été initialisé ou non. Ma suggestion serait d'inclure une propriété qui indique si l'objet a été initialisé ou non.

+2

' null' devrait être égal à 'null': P – Thorarin

+0

" null ne peut jamais être égal à quoi que ce soit d'autre, y compris null "vs" null devrait être égal à null "quelqu'un peut-il décider? –

+3

'null' n'étant pas égal à' null' peut être commun dans les bases de données relationnelles, mais en C# cela n'a aucun sens. 'if (myVar == null) myVar = nouveau SampleClass();'. Cela ne * initialise * pas la variable si null n'est pas égal à null. – Thorarin

0

Si vous avez une instance d'un objet, vous n'avez pas de valeur NULL et tous les comparateurs d'égalité doivent la respecter.

1

Nul ne devrait jamais être égal à une référence non nulle. Par extension, votre! = Devrait retourner vrai car c'est le contraire de l'égalité.

2

En plus de ce qui a été dit, notez que:

Les opérateurs d'égalité de type de référence prédéfinies sont:

bool operator ==(object x, object y); 
bool operator !=(object x, object y); 

Alors ....

SampleClass a = null; 
SampleClass b = null; 
  • a = = b est vrai
  • a! = b est faux

Lisez ce que les concepteurs .NET Framework dit sur la question:

Why don't nullable relational operators return “bool?” instead of “bool“?

Pour plus d'information, lisez:

0

Je pense que c'est une question particulièrement intéressante. J'ai un point de vue qui n'est pas exactement le même que n'importe laquelle des réponses, alors supportez-moi si j'arrive si tard.

La première chose à noter, c'est que null dans .NET n'est pas tout à fait la même chose que null dans d'autres contextes, bien qu'il puisse être utilisé pour les modéliser.

Dans SQL par exemple, nous pourrions avoir 1 = null et 1 <> null à la fois revenir null, car il est concept de null est plus proche de la mathématique, où nul ne correspond pas à quoi que ce soit, y compris nulle, mais il n'est pas précisément inégal à quoi que ce soit . Nous pouvons utiliser C# null pour cela si nous voulons, mais ce n'est pas tout à fait comment fonctionne la signification par défaut de null dans .NET fonctionne.

Pour tout type de référence, null a une signification définie spécifique, et éventuellement des significations supplémentaires fournies par le contexte.

La signification spécifique est "il n'y a pas d'exemple de ceci un objet de ce type".Des significations supplémentaires dans un contexte donné pourraient être "la valeur entière est en fait nulle, plutôt que de correspondre à un nombre entier", ou "il n'y a pas une telle collection d'éléments, même vide", ou "c'est la premier tel élément, donc il n'y en a pas plus tôt "et ainsi de suite selon la façon dont nous l'utilisons. (En outre, cela pourrait signifier "oh mon dieu, ce n'était vraiment pas censé être nul, mieux jeter une exception").

Maintenant, nous pourrions vouloir utiliser ces significations additionnelles, à tel point que nous définissons des cas dans lesquels il est significatif qu'un objet soit nul, ou à tout le moins non nul à nul. Cependant, nous avons les limites suivantes:

  1. La définition précise que nulle pour une valeur d'un type de référence signifie qu'il n'y a pas d'exemple de ce type de référence ne va pas disparaître.

  2. La sémantique que x == y donnera toujours le résultat opposé à x != y pour un x et y donnés, ne disparaîtra pas.

Par conséquent:

  1. Si nous voulons un type où une instance peut être égal à zéro, il doit être un type de valeur.

  2. Nous devons encore avoir x != null retourner l'opposé de x == null.

Maintenant, depuis .NET 2.0, nous avons eu un intégré qui fait précisément que: Nullable<T> (ou T? en C# syntaxe). Il a aussi un peu plus de soutien pour l'aider à bien se comporter face à la boxe (ce qui le fait se comporter comme un type de référence, donc sans ce support supplémentaire nous aurions des complications x == null reviendraient vrai mais (object)x == null reviendraient

C'est aussi le cas, que Nullable<T> peut traiter à peu près n'importe quel cas dans lequel nous aimerions faire usage de ce genre de sémantique légèrement différente pour null, ce qui signifie qu'il n'y a pas vraiment de cas si nous 'Equals() est susceptible de vouloir définir une méthode qui retourne true quand elle est passée à 0.