TLDR: Dies ist ein bekannter Fehler von langer Dauer. Ich habe 2010 zum ersten Mal darüber geschrieben:
https://blogs.msdn.microsoft.com/ericlippert/2010/01/18/a-definite-assignment-anomaly/
Es ist harmlos und Sie können es ignorieren und sich selbst gratulieren, dass Sie einen etwas obskuren Fehler gefunden haben.
Warum erzwingt der Compiler nicht, dass Emaildies definitiv zugewiesen werden muss?
Oh, in gewisser Weise. Es hat nur eine falsche Vorstellung davon, welche Bedingung impliziert, dass die Variable definitiv zugewiesen ist, wie wir sehen werden.
Warum wird dieser Code kompiliert, wenn die Struktur in einer separaten Assembly erstellt wird, aber nicht kompiliert, wenn die Struktur in der vorhandenen Assembly definiert ist?
Das ist der Kern des Fehlers. Der Fehler ist eine Folge der Überschneidung, wie der C # -Compiler bestimmte Zuweisungsprüfungen für Strukturen durchführt und wie der Compiler Metadaten aus Bibliotheken lädt.
Bedenken Sie:
struct Foo
{
public int x;
public int y;
}
// Yes, public fields are bad, but this is just
// to illustrate the situation.
void M(out Foo f)
{
OK, an diesem Punkt, was wissen wir? fist ein Alias für eine Variable vom Typ Foo, daher wurde der Speicher bereits zugewiesen und befindet sich definitiv zumindest in dem Zustand, in dem er aus dem Speicherzuweiser stammt. Wenn der Aufrufer einen Wert in die Variable eingefügt hat, ist dieser Wert vorhanden.
Was brauchen wir? Wir fordern, dass fdiese definitiv an jedem Punkt zugewiesen wird, an dem die Kontrolle Mnormal abläuft. Sie würden also etwas erwarten wie:
void M(out Foo f)
{
f = new Foo();
}
welche setzt f.xund f.yauf ihre Standardwerte. Aber was ist damit?
void M(out Foo f)
{
f = new Foo();
f.x = 123;
f.y = 456;
}
Das sollte auch gut gehen. Aber, und hier ist der Kicker, warum müssen wir die Standardwerte nur zuweisen, um sie einen Moment später wegzublasen? Der definitive Zuweisungsprüfer von C # prüft, ob jedes Feld zugewiesen ist! Das ist legal:
void M(out Foo f)
{
f.x = 123;
f.y = 456;
}
Und warum sollte das nicht legal sein? Es ist ein Werttyp. fist eine Variable und enthält bereits einen gültigen Wert vom Typ. FooSetzen wir also einfach die Felder, und wir sind fertig, oder?
Recht. Also, was ist der Fehler?
Der Fehler, den Sie entdeckt haben, ist: Aus Kostengründen lädt der C # -Compiler die Metadaten für private Felder von Strukturen, die sich in referenzierten Bibliotheken befinden, nicht . Diese Metadaten können sehr groß sein und den Compiler für sehr wenig Gewinn verlangsamen, um jedes Mal alles in den Speicher zu laden.
Und jetzt sollten Sie in der Lage sein, die Ursache des gefundenen Fehlers abzuleiten. Wenn der Compiler prüft, ob der out-Parameter definitiv zugewiesen ist, vergleicht er die Anzahl der bekannten Felder mit der Anzahl der Felder, die definitiv initialisiert wurden, und in Ihrem Fall kennt er nur die null öffentlichen Felder, da die Metadaten der privaten Felder nicht geladen wurden . Der Compiler kommt zu dem Schluss: "Null Felder erforderlich, Null Felder initialisiert, wir sind gut."
Wie ich bereits sagte, gibt es diesen Fehler seit mehr als einem Jahrzehnt und Leute wie Sie entdecken ihn gelegentlich wieder und melden ihn. Es ist harmlos und es ist unwahrscheinlich, dass es repariert wird, da das Reparieren fast keinen Nutzen bringt, aber hohe Leistungskosten verursacht.
Und natürlich wird der Fehler nicht für private Felder von Strukturen angezeigt, die sich in Ihrem Projekt im Quellcode befinden, da der Compiler offensichtlich bereits Informationen über die privaten Felder zur Hand hat.