Un type de référence non nullable en C # 8 peut-il être nul en runtime?

10

Il me semble qu'il n'y a vraiment aucune garantie qu'une variable non nullable n'aura jamais null. Imaginez que j'ai une classe qui a une propriété qui n'est pas nullable:

public class Foo
{
    public Foo(string test)
    {
        Test = test;
    }
    public string Test {get;set;}
}

Maintenant, cela pourrait sembler être désormais nul. Mais si nous référençons cette classe avec une autre bibliothèque qui n'utilise pas de contexte nullable, rien ne l'empêche d'envoyer null dedans.

Est-ce correct ou il y a peut-être des vérifications d'exécution qui assurent cela?

Ilya Chernomordik
la source
C'est public void Foo(string test){...}ou public Foo(string test){...}?
huMpty duMpty
Merci, je l'ai corrigé. C'est ce qui arrive lorsque l'homme s'appuie trop sur R # pour générer des constructeurs :)
Ilya Chernomordik
2
C # 9 ajoutera (probablement) une validation nulle simplifiée .
Steven
En bref, la fonctionnalité "types de référence nullable" est complètement rompue.
Alejandro

Réponses:

9

Voici ce que MS en dit ( https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references#interfaces-with-external-code ):

Le compilateur ne peut pas valider tous les appels à vos API publiques, même si votre code est compilé avec des contextes d'annotation nullables activés. De plus, vos bibliothèques peuvent être utilisées par des projets qui n'ont pas encore opté pour l'utilisation de types de référence nullables. Validez les entrées des API publiques même si vous les avez déclarées comme des types non nullables.

Dmitri Tsoy
la source
2

quelqu'un peut toujours faire

var myFoo = new Foo(null);

Peut-être que vous pouvez utiliser la conception pilotée par domaine

public class Foo
{
    public Foo(string test)
    {
         if (string.IsNullOrWhiteSpace(test))
             throw new ArgumentNullException(nameof(test));

         Test = test;
    }
    public string Test {get;private set;}
}
huMpty duMpty
la source
ouais, tu as raison, c'est juste un avertissement de toute façon je suppose. J'espère qu'à l'avenir, ils pourront vraiment l'appliquer d'une manière ou d'une autre, par exemple dans Kotlin
Ilya Chernomordik
2

Vous avez raison, un autre code qui n'utilise pas la nouvelle fonctionnalité pourrait affecter null à cette propriété, il n'y a pas de vérification au moment de l'exécution, il s'agit simplement d'indicateurs de conformité.

Vous pouvez toujours le faire vous-même si vous souhaitez une vérification de l'exécution:

public string Test { get; set{ if (value == null) throw new ArgumentNullException() } }

Notez que vous pouvez garantir que la plupart de votre code n'est pas nul , il vous suffit d'ajouter des gardes à votre API publique de niveau supérieur et de vous assurer que les classes sont correctement scellées, etc.

Bien sûr, les gens peuvent toujours utiliser la réflexion pour f *** votre code, mais alors c'est sur eux

Milney
la source
Donc, cela signifie effectivement que je peux toujours obtenir une exception de référence nulle même si j'utilise un type non nul, non?
Ilya Chernomordik
Eh bien ... vous ne pouvez pas dans le code que vous compilez, car vous avez les indices ... mais le code d'autres peuples qui n'en ont pas, mais référencez votre code - oui, ils peuvent obtenir une exception nulle
Milney
Eh bien, si par exemple un automappeur utilise votre constructeur, ou quelque chose comme ça, c'est toujours vous qui obtiendrez l'exception :)
Ilya Chernomordik
Of course people can still use reflection to f*** your code up, vrai, vrai en effet. Vous pouvez certainement utiliser la réflexion pour ce faire, est-ce recommandé , non , les gens le font-ils toujours, oui.
Çöđěxěŕ
2

Même dans votre propre code, si vous choisissez de le faire, vous pouvez passer null, en utilisant l'opérateur pardonnant les valeurs nulles. null!est considéré comme non nul en ce qui concerne l'analyse de nullité du compilateur.

Damien_The_Unbeliever
la source
-1

Pour gérer les vérifications nulles et rendre votre code lisible, je suggère le modèle Null Object Design.

Plus de lecture ici:

https://www.c-sharpcorner.com/article/null-object-design-pattern/

Fondamentalement, cela implique de créer un nouvel objet qui est dérivé de la même interface et a une instance nulle.

Exemple:

public class NullExample : IExample  
{  
    private static NullExample _instance;  
    private NullExample()  
    { }  

    public static NullExample Instance  
    {  
        get {  
            if (_instance == null)  
                return new NullExample();  
            return _instance;  
        }  
    }  

    //do nothing methods  
    public void MethodImplementedByInterface1()  
    { }  

    public void MethodImplementedByInterface1()  
    { }  
}  

Les valeurs nulles ne peuvent pas être évitées, mais elles peuvent être vérifiées proprement.

Gauravsa
la source