Kann ein nicht nullbarer Referenztyp in C # 8 zur Laufzeit null sein?


10

Es scheint mir wirklich keine Garantie dafür zu geben, dass eine nicht nullfähige Variable niemals null haben wird. Stellen Sie sich vor, ich habe eine Klasse mit einer Eigenschaft, die nicht nullbar ist:

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

Das scheint jetzt nicht null zu sein. Wenn wir diese Klasse jedoch mit einer anderen Bibliothek referenzieren, die keinen nullbaren Kontext verwendet, hindert nichts sie daran, dort null zu senden.

Ist das richtig oder gibt es vielleicht auch einige Laufzeitprüfungen, die dies sicherstellen?


Ist es public void Foo(string test){...}oder public Foo(string test){...}?
HuMpty DuMpty

Danke, ich habe es behoben. Das passiert, wenn der Mensch sich zu sehr auf R # verlässt, um Konstruktoren zu generieren :)
Ilya Chernomordik

2
C # 9 wird (wahrscheinlich) eine vereinfachte Nullvalidierung hinzufügen .
Steven

Kurz gesagt, die Funktion "nullfähige Referenztypen" ist vollständig fehlerhaft.
Alejandro

Antworten:


9

Dies ist, was MS über sagt ( https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references#interfaces-with-external-code ):

Der Compiler kann nicht alle Aufrufe Ihrer öffentlichen APIs validieren, selbst wenn Ihr Code mit aktivierten annullierbaren Annotationskontexten kompiliert wird. Darüber hinaus werden Ihre Bibliotheken möglicherweise von Projekten verwendet, die sich noch nicht für die Verwendung nullbarer Referenztypen entschieden haben. Überprüfen Sie Eingaben in öffentliche APIs, obwohl Sie sie als nicht löschbare Typen deklariert haben.


2

jemand kann es immer tun

var myFoo = new Foo(null);

Möglicherweise können Sie Domain Driven Design verwenden

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

         Test = test;
    }
    public string Test {get;private set;}
}

Ja, du hast recht, es ist sowieso nur eine Warnung, denke ich. Ich hoffe, dass sie es in Zukunft wirklich irgendwie durchsetzen können, wie in zB Kotlin
Ilya Chernomordik

2

Sie haben Recht, anderer Code, der die neue Funktion nicht verwendet, könnte dieser Eigenschaft null zuweisen. Es gibt keine Laufzeitprüfungen. Es handelt sich lediglich um konformere Hinweise.

Sie können es jederzeit selbst tun, wenn Sie eine Laufzeitprüfung wünschen:

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

Beachten Sie, dass Sie garantieren können, dass der größte Teil Ihres Codes nicht null ist. Sie müssen lediglich Schutzmaßnahmen zu Ihrer öffentlichen API der obersten Ebene hinzufügen und sicherstellen, dass die Klassen ordnungsgemäß versiegelt sind.

Natürlich können die Leute immer noch Reflexion verwenden, um Ihren Code zu ficken, aber dann liegt es an ihnen


Das bedeutet also effektiv, dass ich immer noch eine Nullreferenzausnahme erhalten kann, obwohl ich einen nicht nullbaren Typ verwende, oder?
Ilya Chernomordik

Nun ... Sie können nicht in dem Code, den Sie kompilieren, weil Sie die Hinweise haben ... aber Code anderer Leute, die die Hinweise nicht haben, aber auf Ihren Code verweisen - ja, sie können eine Null-Ausnahme bekommen
Milney

Nun, wenn zB ein Automapper Ihren Konstruktor oder so etwas benutzt, sind es immer noch Sie, die die Ausnahme bekommen :)
Ilya Chernomordik

Of course people can still use reflection to f*** your code upwahr, wahr in der Tat. Sie können definitiv Reflexion verwenden, um dies zu tun, wird empfohlen , nein , tun die Leute es immer noch, ja.
Çöđěxěŕ

2

Selbst in Ihrem eigenen Code können Sie, wenn Sie dies möchten null, mit dem Operator nullverzeihend übergeben. null!wird in Bezug auf die Nullabilitätsanalyse des Compilers als nicht null betrachtet.


-1

Um mit Nullprüfungen umzugehen und Ihren Code auch lesbar zu machen, schlage ich das Null-Objekt-Entwurfsmuster vor.

Lesen Sie hier mehr:

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

Grundsätzlich wird ein neues Objekt erstellt, das von derselben Schnittstelle abgeleitet ist und eine Nullinstanz aufweist.

Beispiel:

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()  
    { }  
}  

Nullen können nicht vermieden werden, können jedoch sauber überprüft werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.