Dies wird nicht verpackt (was mich überrascht). Ich denke, dass die Erklärung von bnkdev es abdeckt. Hier ist, wie ich es überprüft:
Ich habe die folgende schnelle Konsolenanwendung geschrieben (beachten Sie, dass ich BoxTest() eingeschlossen habe, das ich wissen will box, damit ich etwas zum Vergleichen habe).
Dann habe ich Reflector verwendet, um die kompilierte Ausgabe in IL zu disassemblieren (Sie können ILDASM verwenden).
namespace StructInterfaceBoxingTest
{
public struct TestStruct : IDisposable
{
#region IDisposable Members
public void Dispose()
{
System.Console.WriteLine("Boo!");
}
#endregion
}
class Program
{
static void Main(string[] args)
{
using (TestStruct str = new TestStruct())
{
}
}
static void BoxTest()
{
TestStruct str = new TestStruct();
ThisWillBox(str);
}
static void ThisWillBox(object item) {}
}
}
Ok, also zuerst, hier ist die IL für BoxTest - beachten Sie die Box-Anweisung in Zeile L_000a (Sternchen Hervorhebung mein)
.method private hidebysig static void BoxTest() cil managed
{
.maxstack 1
.locals init (
[0] valuetype StructInterfaceBoxingTest.TestStruct str)
L_0000: nop
L_0001: ldloca.s str
L_0003: initobj StructInterfaceBoxingTest.TestStruct
L_0009: ldloc.0
L_000a: **box** StructInterfaceBoxingTest.TestStruct
L_000f: call void StructInterfaceBoxingTest.Program::ThisWillBox(object)
L_0014: nop
L_0015: ret
}
Schauen Sie sich nun Main an (wo wir eine using-Anweisung mit unserer IDisposable-Struktur verwenden):
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] valuetype StructInterfaceBoxingTest.TestStruct str)
L_0000: nop
L_0001: ldloca.s str
L_0003: initobj StructInterfaceBoxingTest.TestStruct
L_0009: nop
L_000a: nop
L_000b: leave.s L_001c
L_000d: ldloca.s str
L_000f: constrained StructInterfaceBoxingTest.TestStruct
L_0015: callvirt instance void [mscorlib]System.IDisposable::Dispose()
L_001a: nop
L_001b: endfinally
L_001c: nop
L_001d: ret
.try L_0009 to L_000d finally handler L_000d to L_001c
}
Beachten Sie das Schlüsselwort "constrained" in Zeile L_000f. Ich kann keinen Hinweis darauf finden, was dieses Schlüsselwort genau bedeutet, aber wenn Sie den Beitrag von bnkdev lesen, denke ich, dass dies der eingeschränkte viruelle Aufruf ist, den er beschreibt.
7 Stimmen
Warum haben Sie eine Struktur, die IDisposable implementiert?
5 Stimmen
Das klingt furchtbar gefährlich. Mit seiner Kopie auf Zuweisung Semantik, ist es sehr, sehr schwer zu sagen, wie viele Kopien einer Struktur Sie haben.
2 Stimmen
@Jonathan Allen - Die Anzahl der Kopien der Struktur ist jedoch im Kontext einer using-Anweisung nicht wirklich wichtig. Wichtig ist, dass die nicht verwaltete Ressource, auf die die Struktur verweist, ordnungsgemäß entsorgt wird. Diese Referenz sollte in der Copy-on-Assignment-Semantik nicht schwer zu verfolgen sein.
1 Stimmen
Ich befürchte, dass jemand Ihre Struktur missbrauchen und die Ressource doppelt freigeben wird. Je nachdem, um welche Ressource es sich handelt, kann es zu einer Ausnahme bis hin zur völligen Beschädigung des Speichers kommen.
1 Stimmen
Ich kann mir keinen guten Grund vorstellen, IDisposable in einer Struktur zu implementieren. Was hindert Sie daran, eine Klasse zu verwenden?