Objectinstantie maken zonder constructor aan te roepen?

Is er in C# een manier om een ​​instantie van een klasse te instantiëren zonder de constructor ervan aan te roepen?

Veronderstel dat de klasse openbaar is en is gedefinieerd in een bibliotheek van derden en dat de constructor intern is. De redenen waarom ik dit wil doen zijn ingewikkeld, maar het zou handig zijn om te weten of het mogelijk is om een ​​soort van C#-hackery te gebruiken.

OPMERKING: ik wil specifiek geen enkele constructor aanroepen, dus reflectie gebruiken om toegang te krijgen tot de interne constructor is geen optie.


Antwoord 1, autoriteit 100%

Ik heb dit niet geprobeerd, maar er is een methode genaamd FormatterServices.GetUninitializedObjectdat wordt gebruikt tijdens deserialisatie.

Opmerkingen van MSDN zegt:

Omdat de nieuwe instantie van het object
wordt geïnitialiseerd op nul en nee
constructors worden uitgevoerd, kan het object
niet vertegenwoordigen een staat die wordt beschouwd
als geldig door dat object.


Antwoord 2, autoriteit 11%

Eigenlijk klinkt het alsof ze de constructor intern hebben gemaakt, zodat je het niet kunt instantiëren. Het kan een builder- of fabrieksmethode hebben.

Bekijk deze artikelen:

Derde voorkomen Feestafleiding: deel 1

Derde voorkomen Partijafleiding: deel 2

ze leggen een beetje de redenering uit.


Antwoord 3, autoriteit 6%

In tegenstelling tot wat velen denken, heeft een constructeur niet veel te maken met het maken van een object (behoorlijk misleidende term). Een constructor is een speciale methode die kan worden aangeroepen nadat een object is gemaakt, zodat dat object zichzelf correct kan initialiseren. In C++ wijst objectinstantiatie geheugen toe aan het object, in .NET en Java wordt het zowel toegewezen als vooraf geïnitialiseerd op standaardwaarden, afhankelijk van het type velden (0, null, false enz.). Vervolgens roept de runtime de constructor aan. De nieuwe operator vat deze twee afzonderlijke acties samen in wat lijkt op één enkele bewerking.
Deserialisatie zou nooit hebben gewerkt in .NET als het niet mogelijk was om een ​​instantie te maken zonder een constructor te gebruiken. Dat gezegd hebbende, het zogenaamde ConstructorInfo-type fungeert als zowel een nieuwe operator als een constructor bij het aanroepen van de Invoke(…)-methode.


Antwoord 4

Het is misschien mogelijk om via reflectie toegang te krijgen tot de constructor en deze zo aan te roepen (maar ik weet niet zeker of het zal werken aangezien de constructor intern is – je zult hem moeten testen).
Anders kun je voor zover ik weet geen object maken zonder de constructor aan te roepen.


Antwoord 5

Zie de functie System.Activator.CreateInstance.


Antwoord 6

EDIT: je hebt je vraag bijgewerkt, je wilt een klasse maken zonder een constructor. Of bel een standaard “Empty Constructor”.

Dit kan niet worden gedaan, omdat de compiler geen standaardconstructor zal genereren als er al een is opgegeven. In het voordeel van de lezers is hier echter hoe u bij een interne, beschermde of privéconstructeur kunt komen:

Ervan uitgaande dat je klas Foo heet:

using System.Reflection;
// If the constructor takes arguments, otherwise pass these as null
Type[] pTypes = new Type[1];
pTypes[0] = typeof(object);    
object[] argList = new object[1];
argList[0] = constructorArgs;
ConstructorInfo c = typeof(Foo).GetConstructor
    (BindingFlags.NonPublic |
     BindingFlags.Instance,
     null,
     pTypes,
     null);
Foo foo = 
    (Foo) c.Invoke(BindingFlags.NonPublic,
                   null, 
                   argList, 
                   Application.CurrentCulture);

Lelijk, maar werkt.

Natuurlijk kan er een volkomen legitieme reden zijn om een ​​constructor als intern te markeren, dus je moet echt nadenken over de logistiek van wat je wilt voordat je die klasse misbruikt door er met reflectie over te gaan.


Antwoord 7

Je moet een constructor aanroepen om een ​​object te maken. Als er geen beschikbaar is naar uw wens, kunt u misschien een bibliotheek voor het herschrijven van bytecode gebruiken, zoals Cecil van het Mono-project. Het werkt op zowel Windows als Linux. Van sommige van de demo’s die ik zag, zag het er best cool uit. Je kunt de beschermingsniveaus van methoden en allerlei gekke dingen veranderen.


Antwoord 8

Als de klasse (en de klassen van objecten waarnaar deze verwijst) Serializable is, kunt u een diepe kopie maken door te serialiseren met behulp van een BinaryFormatter die wordt uitgevoerd naar een MemoryStream (waardoor een byte-arraybyte[] wordt gemaakt), en vervolgens deserialiseren. Bekijk de antwoorden op deze vraag over het converteren van een object naar een bytearray. (Maar let op: het opslaan van de bytearray om later/elders te gebruiken zal waarschijnlijk niet werken. IOW slaat de bytearray niet op in een bestand of een andere permanente vorm.)


Antwoord 9

Wat u vraagt, is een schending van de filosofie waarop beheerde programmering is ontwikkeld. Het .Net Framework en C# zijn gebouwd met het principe dat, waar mogelijk, objecten moeten worden geabstraheerd uit hun onderliggende geheugen. Objecten zijn objecten, geen gestructureerde array van bytes. Dit is de reden waarom je geen objecten kunt casten om pointers te ongeldig te maken. Wanneer objecten uit hun onderliggende geheugen worden geabstraheerd, is het fundamenteel ongeldig om te suggereren dat een objectinstantie kan bestaan ​​zonder dat de constructor wordt aangeroepen.

Dat gezegd hebbende, heeft het .Net-framework concessies gedaan aan het feit dat objecten in werkelijkheid in het geheugen worden weergegeven. Met enige creativiteit is het mogelijk om waardetypes te instantiëren zonder hun initializers aan te roepen. Als je echter het gevoel hebt dat je het moet doen, doe je waarschijnlijk dingen verkeerd.


Antwoord 10

Ik merkte de “doodsheid” van het onderwerp op, maar alleen ter verduidelijking voor verdere lezers en om een ​​definitief antwoord te geven dat misschien niet mogelijk was toen de vraag werd gepost. Hier gaat het.

Het lijkt erop dat je een klasse kunt instantiëren zonder zijn constructors te gebruiken door waarden toe te kennen aan zijn eigenschappen. Hier is het adres waar is de how-to in MSDN voor dit type instantiatie http ://msdn.microsoft.com/en-us/library/bb397680.aspx.

Het lijkt erop dat dit een techniek is die niet goed bekend is, omdat ik het in een artikel in CodeProject tegenkwam en het vervolgens googelde en er niets over vond en later de MSDN-startpagina bezocht en er een bericht was dat mij linkte naar dat exacte onderwerp. Het lijkt er dus op dat het een onbekend onderwerp is in plaats van een nieuw onderwerp, omdat de datum op de CodeProject-post mei 2008 dateert.

Ik hoop dat dit iemand anders helpt die dit googlet en deze vraag tegenkomt.


Antwoord 11

Niemand hier heeft helemaal duidelijk gemaakt wat wordt bedoeld met “Het kan niet.”

De constructor iswat het object maakt. Uw vraag is verwant aan “Hoe kan ik een zandkasteel bouwen zonder het vorm te geven als een kasteel?” Dat kan niet — je hebt alleen een hoop zand.

Het beste wat u kunt doen, is een geheugenblok van dezelfde grootte als uw object toewijzen:

byte[] fakeObject = new byte[sizeof(myStruct)];

(LET OP: zelfs dat werkt alleen in MyStruct is een waardetype)

Other episodes