2015-07-24 5 views
7

Wie Sie alle wissen, in C# könnten wir so etwas wie dies nicht tun:Habe ich ein Objekt von void instanziiert?

var voidObject = new void(); 

oder

var voidObject = new System.Void(); 

oder

var voidObject = Activator.CreateInstance(typeof(void)); 

Aber dieser Code erfolgreich und im Debug-Modus kompiliert I kann sehen, dass der Typ voidObjectSystem.Void ist:

var voidObject = FormatterServices.GetUninitializedObject(typeof(void)); 

Was ist das? Ist das eine echte Instanz von void?

+1

Wow ... völlig nutzlos, aber unglaublich :-) Sie zu schließen vergessen, dieser Weg :-) – xanatos

+0

bekam ich diese 'Ausdruck ausgewertet wurde, und hat keine value' –

+0

auf .NET https://dotnetfiddle.net/BUUdKU und auf Mono https://ideone.com/LegWvM – xanatos

Antwort

3

Von dem, was ich sehe, es ist ein vollkommen gut ist, absolut gültige boxedSystem.Void Werttyp :-)

Sie können

Console.WriteLine(voidObject.GetType()); 

und sehen, dass es ein System.Void ist.

System.Void ein Werttyp ist, so sollte es durch FormatterServices.GetUninitializedObject Schaffung gleich (object)default(void) zu tun (weil FormatterServices.GetUninitializedObject einen Werttyp mit all seinen Feldern auf ihren Standardwert zurück) (Anmerkung, die eindeutig (object)default(void) illegal ist).

Noch gibt es nicht viele Dinge, die Sie mit Ihrem boxedSystem.Void tun können ...

var voidObject = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(void)); 
var voidObject2 = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(void)); 

Console.WriteLine("Type: {0}", voidObject.GetType()); 
Console.WriteLine("IsValueType: {0}", voidObject.GetType().IsValueType); 

Console.WriteLine("Equals: {0}", voidObject.Equals(voidObject2)); 
Console.WriteLine("GetHashCode1: {0}", voidObject.GetHashCode()); 
Console.WriteLine("GetHashCode2: {0}", voidObject2.GetHashCode()); 
Console.WriteLine("ToString: {0}", voidObject.ToString()); 

Es scheint einige Unterschiede zwischen .NET und Mono Implementierungen ... On zu sein.NET alle Instanzen von System.Void die gleiche GetHashCode(), während auf Mono jeder von ihnen eine andere GetHashCode() hat. Die Equals ordnungsgemäß funktioniert (true) für beide.

(beachten Sie, dass der Unterschied in den GetHashCode() scheint mit struct s ohne Felder ein Fehler von Mono zu sein: https://ideone.com/t0t8I6 dass should be fixed in neueren Versionen)

0

Nun, Imstance ist das Whrong-Wort, denke ich. Wenn Sie ein Objekt erstellen, indem Sie GetUninitializedObject verwenden, erhalten Sie ein unitialisiertes Objekt wie erwähnt rom methods name. Nehmen wir an, Sie haben eine Klasse Foo mit einigen Mitgliedern, keines dieser Mitglieder würde irgendeinen Wert haben, da der Konstruktor nicht aufgerufen wird. Während Void nicht einmal einen Konstruktor hat, dürfen Sie nicht Activator.CreateInstance darauf aufrufen oder new void() verwenden. Bei dem erwähnten Ansatz, der keinen Konstruktor verwendet, erstellen Sie ein Objekt, aber lassen Sie es unitalisiert. Das ist also nur ein Sonderfall, bei dem ein neues Objekt unitizialisiert bleibt.

Wenn dies ein Fehler ist, ein Feature oder was ich nur erraten kann.

EDIT: obviosuly es ist ein Feature, das folgende von MSDN mich so lässt vermuten:

Die aktuelle Methode sollte nur für die Deserialisierung verwendet werden, wenn der Benutzer sofort beabsichtigt, alle Felder zu füllen. (https://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices.getuninitializedobject%28v=vs.110%29.aspx)

So, während Sie können eine Instanz mit dieser Methode erstellen Sie sollten es nur tun, wenn alle notwendigen Informationen sofort nach dem Anruf bereitstellt. Jedoch hat void keine Mitglieder, sein Zustand ist immer noch ungültig.