85 votes

C # ok avec la comparaison des types de valeur à null

J'ai couru dans le présent d'aujourd'hui et n'ai aucune idée pourquoi le compilateur C# n'est pas de lancer une erreur.

Int32 x = 1;
if (x == null)
{
    Console.WriteLine("What the?");
}

Je suis confus quant à la façon dont x pouvaient être null. Surtout depuis que cette cession certainement renvoie une erreur de compilateur:

Int32 x = null;

Est-il possible que x pourrait devenir nulle, n'a Microsoft vient de décider de ne pas mettre cette case dans le compilateur, ou a été, il a complètement raté?

Mise à jour: Après avoir jouer avec le code à écrire cet article, tout à coup le compilateur est venu avec un message d'avertissement que l'expression ne sera jamais vrai. Maintenant, je suis vraiment perdu. J'ai mis l'objet dans une classe et maintenant l'avertissement a disparu, mais la gauche avec la question, un type de valeur à la fin null.

public class Test
{
    public DateTime ADate = DateTime.Now;

    public Test ()
    {
        Test test = new Test();
        if (test.ADate == null)
        {
            Console.WriteLine("What the?");
        }
    }
}

120voto

Eric Lippert Points 300275

C'est légal, parce que l'opérateur de résolution de surcharge a un unique opérateur à choisir. Il y a un opérateur == qui prend deux valeurs null ints. L'int local est convertible en un nullable int. Le littéral null est convertible en un nullable int. Donc c'est un juridiques de l'utilisation de l'opérateur==, et sera toujours faux.

De même, nous permet également de vous dire "if (x == 12.6)", qui va être toujours aussi faux. L'int local est convertible en un lit double, la traduction littérale est convertible en un lit double, et, évidemment, ils ne seront jamais égaux.

17voto

Marc Gravell Points 482669

Ce n'est pas une erreur, car il y a (int?) à la conversion; il génère un message d'avertissement dans l'exemple donné:

Le résultat de l'expression est toujours "false", puisqu'une valeur de type " int " n'est jamais égal à 'null', de type 'int?'

Si vous cochez l'IL, vous verrez que c' complètement supprime l'inaccessible direction générale - il n'existe pas dans une version release.

Notez cependant qu'il n'est pas de générer cet avertissement personnalisé pour les structures avec des opérateurs d'égalité. Il a utilisé à la 2.0, mais pas dans la version 3.0 du compilateur. Le code est encore retirée (de sorte qu'il sait que le code est inaccessible), mais pas d'avertissement est généré:

using System;

struct MyValue
{
    private readonly int value;
    public MyValue(int value) { this.value = value; }
    public static bool operator ==(MyValue x, MyValue y) {
        return x.value == y.value;
    }
    public static bool operator !=(MyValue x, MyValue y) {
        return x.value != y.value;
    }
}
class Program
{
    static void Main()
    {
        int i = 1;
        MyValue v = new MyValue(1);
        if (i == null) { Console.WriteLine("a"); } // warning
        if (v == null) { Console.WriteLine("a"); } // no warning
    }
}

Avec le IL ( Main) - note de tout, sauf de l' MyValue(1) (ce qui pourrait avoir des effets secondaires) a été supprimé:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 i,
        [1] valuetype MyValue v)
    L_0000: ldc.i4.1 
    L_0001: stloc.0 
    L_0002: ldloca.s v
    L_0004: ldc.i4.1 
    L_0005: call instance void MyValue::.ctor(int32)
    L_000a: ret 
}

c'est en gros:

private static void Main()
{
    MyValue v = new MyValue(1);
}

5voto

Adam Robinson Points 88472

Le fait qu'une comparaison ne puisse jamais être vraie ne signifie pas que c'est illégal. Néanmoins, non, un type de valeur ne peut jamais être null .

3voto

Li0liQ Points 8104

Non, Int32 x ne deviendra jamais null .

Si vous comparez un int à null, l'opérateur de comparaison prenant deux int? S est applicable.

"Pourquoi une comparaison d'un type de valeur avec null est un avertissement?" L'article vous aidera.

1voto

Greg Points 11248

Un type de valeur ne peut pas être null , bien qu'il puisse être égal à null (considérez Nullable<> ). Dans votre cas, les variables int et null sont implicitement converties en Nullable<Int32> et comparées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X