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:
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% 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):
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:
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%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%Tags und Links c# null-propagation-operator