Ich habe ildasm ausgeführt, um dies festzustellen:
using(Simple simp = new Simple())
{
Console.WriteLine("here");
}
erzeugt IL-Code, der dem hier entspricht:
Simple simp = new Simple();
try
{
Console.WriteLine("here");
}
finally
{
if(simp != null)
{
simp.Dispose();
}
}
und die Frage ist, warum zur Hölle prüft es null in der finally? Der finally-Block wird nur ausgeführt, wenn der try-Block ausgeführt wird, und der try-Block wird nur ausgeführt, wenn der Simple-Konstruktor erfolgreich ist (d.h. keine Exception auslöst), in diesem Fall wird simp nicht null sein. (Wenn zu befürchten ist, dass zwischen dem Simple-Konstruktor und dem Beginn des Try-Blocks einige Zwischenschritte liegen, dann wäre das wirklich ein Problem, denn dann könnte eine Ausnahme ausgelöst werden, die die Ausführung des Finally-Blocks überhaupt verhindert). Also, warum zum Teufel?
Abgesehen von der Frage, ob die using-Anweisung besser ist als try-finally, schreibe ich meine try-finally-Blöcke wie folgt:
Simple simp = new Simple();
try
{
Console.WriteLine("here");
}
finally
{
simp.Dispose();
simp = null; // sanity-check in case I touch simp again
// because I don't rely on all classes
// necessarily throwing
// ObjectDisposedException
}
0 Stimmen
Eine Sache hat mich neugierig gemacht: Wie "teuer" ist diese zusätzliche Unbedenklichkeitsprüfung (simp = null) im Vergleich zu der vom Compiler generierten Unbedenklichkeitsprüfung, was die Leistung angeht? Letztendlich scheint der Unterschied zwischen den beiden eher philosophischer als praktischer Natur zu sein, aber vielleicht irre ich mich ja. Interessant ist die Diskussion so oder so.
0 Stimmen
@Fredrik - Sie fragen also, ob "set to null" schneller/langsamer ist als "compare to null"? Ich bin mir nicht sicher. Abgesehen davon ist ein Vorteil der using-Anweisung, dass man sich keine Sorgen machen muss, dass auf das Objekt außerhalb des using-Bereichs zugegriffen wird. (Es sei denn, Sie halten einen anderen Verweis auf es.)
24 Stimmen
"Warum zum Teufel wird in der Endabfrage Null angezeigt?" Es gibt keinen guten Grund. Das Überspringen der Null-Prüfung ist eine Optimierung, die wir hätten durchführen können. Haben wir aber nicht. Keine wirklich große Sache; Nullprüfungen sind kurz und billig.
6 Stimmen
Übrigens gibt es eine Reihe von Stellen, an denen der C#-Compiler Mikrooptimierungen wie diese durchführt, wenn bekannt ist, dass ein Ausdruck nicht null ist, weil er das Ergebnis eines neuen Ausdrucks ist. Dies ist nur eine, die wir übersehen haben.
4 Stimmen
Auf diese Optimierung gehe ich hier kurz ein: blogs.msdn.com/ericlippert/archive/2009/06/11/