Null-Propagierungsoperator, out-Parameter und falsche Compilerfehler?

9

Nehmen wir an, ich habe eine Klasse mit einer Eigenschaft vom Typ Dictionary<string,string> , die null sein kann.

Dies kompiliert, aber der Aufruf von TryGetValue() könnte zur Laufzeit eine NullRef Ausnahme auslösen:

%Vor%

Also füge ich einen Null-propagierenden Operator hinzu, der gegen Nullen schützt, aber das kompiliert nicht:

%Vor%

Gibt es einen tatsächlichen Anwendungsfall, in dem val innerhalb des Blocks if nicht initialisiert ist, oder kann der Compiler dies (und warum) einfach nicht ableiten?

Update: Der sauberste (?) Weg zum Workaround ^ H ^ H ^ H ^ H ^ H Fix:

%Vor%     
Cristi Diaconescu 06.12.2017, 22:49
quelle

3 Antworten

3

Durch Initialisieren von val auf einen erhm-Wert (z. B. String.Empty ) kann der Compiler die Absicht für die Nulloperatoren ermitteln und verhält sich wie erwartet (über LINQPad, natch):

%Vor%

Ed: Mit 'grok the intent' meinte ich, dass der Compiler keine wichtigen Garantien über die Eigenschaften des Programms geben kann, wenn die Ausführung den aktuellen Bereich mit val uninitialized verlassen kann. Wenn die Nulloperatoren ausgewertet werden, wird der Methodenaufruf ausgeführt.

Der von Ihnen angeforderte Anwendungsfall lautet wie folgt: Sagen wir, dass wir anstelle von TryGetValue bool SomeMethod(string s, out v) haben. Nehmen wir an, dass SomeMethod , wenn sie aufgerufen wird, unartig ist und einfach einen Körper von return true; hat. Der Compiler behandelt Methodenaufrufe für Methodenaufrufe als undurchsichtig (da er nicht immer in einer für den Compiler verfügbaren / sichtbaren Assembly enthalten sein kann). Daher kann man nicht beweisen, dass val jemals initialisiert wurde.

ed: Als Reaktion auf einige Kommentare wollte ich meine Antwort aktualisieren, um darauf hinzuweisen, dass dieses Verhalten nicht spezifisch für die Sprachfunktionen ?? oder ?. C # ist. Sie können den gleichen Effekt einfach mit einem ternären Ausdruck reproduzieren:

%Vor%     
Josh E 06.12.2017, 23:15
quelle
4

Scheint so, als ob Sie eine Einschränkung des Verständnisses der Compiler von ?. und ?? erfahren haben, was nicht allzu überraschend ist, da sie nicht wirklich vollständig in die Sprache integriert sind.

Wenn Sie Ihren Test ohne die neueren Operatoren explizit machen, wird der Compiler mit Ihnen übereinstimmen:

%Vor%     
NetMage 06.12.2017 23:08
quelle
-3

Das liegt daran, dass, wenn c.PossiblyNullDictionary null ist, TryGetValue nicht ausgeführt wird und dieser Ausdruck nicht wahr oder falsch zurückgibt.

c.PossiblyNullDictionary?. TryGetValue ("someKey", out val) gibt Nullable zurück, Sie können Ihren Code durch etwas wie diesen ersetzen und kompilieren:

%Vor%     
olegk 06.12.2017 23:03
quelle

Tags und Links