In C#, is there a way to instantiate an instance of a class without invoking its constructor?
Assume the class is public and is defined in a 3rd party library and the constructor is internal. The reasons I want to do this are complicated but it would be helpful to know if it's possible using some kind of C# hackery.
NOTE: I specifically do not want to call any constructor so using reflection to access the internal constructor is not an option.
-
3Related note to this and some people tend not to realize is that if you throw an exception during construction, your object still exists.. if it has a finalizer- that will still run, you need to be careful about making no assumptions about what happened in the constructor.meandmycode– meandmycode2009年04月19日 10:13:01 +00:00Commented Apr 19, 2009 at 10:13
-
Why would you ever want this? If it is just curiosity, that's fine.nawfal– nawfal2014年01月02日 13:07:11 +00:00Commented Jan 2, 2014 at 13:07
-
@nawfal WCF uses this for its serialization engine, which is one reason it is useful in general. My specific case was actually playing around with an existing object model (the SharePoint OM) to see if it were possible to work around some bugs/limitations for experimental purposes. Very hacky for sure, but again, experimental.Chris Gillum– Chris Gillum2014年01月09日 01:36:27 +00:00Commented Jan 9, 2014 at 1:36
12 Answers 12
I have not tried this, but there is a method called FormatterServices.GetUninitializedObject that is used during deserialization.
Remarks from MSDN says:
Because the new instance of the object is initialized to zero and no constructors are run, the object might not represent a state that is regarded as valid by that object.
-
In my case, it's only for prototyping. Not for real code that anyone would use for anything remotely important.Chris Gillum– Chris Gillum2008年11月18日 06:34:59 +00:00Commented Nov 18, 2008 at 6:34
-
I'm planning on using it for deserializing a DataContract object from an unsuported serialized format.Michael Shaw– Michael Shaw2011年11月27日 00:01:24 +00:00Commented Nov 27, 2011 at 0:01
-
7I have tested this out and can confirm that FormatterServices.GetUninitializedObject() does not avoid static ctor's from being called. :(Jason Evans– Jason Evans2012年08月09日 09:24:37 +00:00Commented Aug 9, 2012 at 9:24
-
4@JasonEvans I don't think you can ever stop static ctors from being run, as the CLR loads them when the type is loaded. You can't actually refer to a class at all without loading it's type, so I'm not sure quite how you'd get around itOrion Edwards– Orion Edwards2014年01月08日 19:29:31 +00:00Commented Jan 8, 2014 at 19:29
-
1@nawfal Reflection isn't practical in all cases. The whole reason I asked this question is because I was dealing with a type which had an internal constructor requiring parameters which themselves were complex internal types. Using reflection turned out to be too difficult to generate these other related types without falling down a slippery slope of endless reflection.Chris Gillum– Chris Gillum2014年01月09日 01:31:27 +00:00Commented Jan 9, 2014 at 1:31
Actually it sounds like they made the constructor internal just so you can't instantiate it. It may have a builder or factory method.
Check out these articles:
Preventing Third Party Derivation: Part 1
Preventing Third Party Derivation: Part 2
they kind of explain the reasoning.
Contrary to what many believe, a constructor hasn't much to do with the instantiation of an object at all (pretty misleading term). A constructor is a special method that can be called after the instantiation of an object to allow that object to properly initialize itself. In C++ object instantiation allocates memory for the object, in .NET and Java it is both allocated and pre-initialized to default values depending on the type of fields (0, null, false etc.). Then the run-time calls the constructor. The new operator encapsulates these two separate actions into what appears to be a single operation. Deserialization could never had worked in .NET if it wasn't possible to create an instance without using a constructor. That said, the so called ConstructorInfo type acts as both a new operator and constructor when calling its Invoke(...) method.
See RuntimeHelpers.GetUninitializedObject(Type)
, available in .NET Core 2.0 / .NET Standard 2.1 and above.
Another answer suggests
FormatterServices.GetUninitializedObject(Type)
, which directly proxies to RuntimeHelpers.
For completeness, if you want to create an uninitialized object of the same type as another instance, in .NET Core 7 there is also an undocumented AllocateUninitializedClone
, with sample code below. I wouldn't recommend this over simply passing instance.GetType()
to the documented API.
Likewise, here are notes for if you actually want to hit an internal constructor:
Given a Type
and some arguments.
Use Activator.CreateInstance(Type type, object[] args)
.
Alternatively via Reflection APIs
Use type.GetConstructor
. The returned ConstructorInfo
has an Invoke
method. If you pass an instance, you will effectively reinitialize an object. If you pass no instance, the invocation will instantiate a new object.
Some sample code:
using System.Reflection;
using System.Runtime.CompilerServices;
public static class Program {
public static void Main() {
//
// create uninitialized object instance, then run ctor on it
//
var inst1 = (C)RuntimeHelpers.GetUninitializedObject(typeof(C));
Console.WriteLine(inst1.X); // 0
var ctor = typeof(C).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Array.Empty<Type>());
ctor.Invoke(inst1, null); // Prints "Ran C's Ctor. X is -123"
Console.WriteLine(inst1.X); // 2
//
// create new object with ctor (via reflection)
//
var inst2 = (C)ctor.Invoke(null); // Prints "Ran C's Ctor. X is -123"
Console.WriteLine(inst2.X); // 2
//
// create new object with ctor (via activator)
//
var inst3 = (C)Activator.CreateInstance(typeof(C), BindingFlags.Instance | BindingFlags.NonPublic, null, null, null); // Prints "Ran C's Ctor. X is -123"
Console.WriteLine(inst3.X); // 2
//
// create new uninitialized object of type matching a given instance via undocumented AllocateUninitializedClone
//
var allocateUninitializedClone = typeof(RuntimeHelpers).GetMethod("AllocateUninitializedClone", BindingFlags.Static | BindingFlags.NonPublic, new[] { typeof(object) });
var inst4 = (C)allocateUninitializedClone.Invoke(null, new []{inst2});
Console.WriteLine(inst4.X); // 0
}
public class C {
private C() {
Console.WriteLine($"Ran C's Ctor. X is {X}");
X = 2;
}
public int X { get; } = -123;
}
}
It might be possible to access the constructor via reflection and invoke it like that (but I'm not sure that it will work since the constructor is internal - you'll have to test it). Otherwise from my knowledge you can't create an object without calling the constructor.
EDIT: You updated your question, you want to construct a class without a constructor. Or call a default "Empty Constructor".
This cannot be done, as the compiler will not generate a default constructor if there is already one specified. However, for the benefit of the readers, here is how to get at a internal, protected, or private constructor:
Assuming your class is called Foo:
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);
Ugly, but works.
Of course, there may be a perfectly legitimate reason to mark a constructor as internal, so you should really consider the logistics of what you want before you abuse that class by getting at it with reflection.
-
Haven't you just called the constructor without creating an object instance? (eg: the exact opposite of what the question is asking?)Orion Edwards– Orion Edwards2008年11月17日 19:52:01 +00:00Commented Nov 17, 2008 at 19:52
-
I created the object by calling the hidden constructor, which is what he wanted until he edited his post.FlySwat– FlySwat2008年11月17日 19:55:33 +00:00Commented Nov 17, 2008 at 19:55
-
The question's revision history disagrees with you. Perhaps this is dirty ol atwood trying to optimize things too much. I remember on a podcast he mentioned simply throwing away any record of changes that happened within a few minutes of the question being postedOrion Edwards– Orion Edwards2008年11月17日 20:53:47 +00:00Commented Nov 17, 2008 at 20:53
-
stackoverflow.com/revisions/296584/list <-- I see him adding his note of clarification.FlySwat– FlySwat2008年11月17日 22:25:41 +00:00Commented Nov 17, 2008 at 22:25
You have to call a constructor to create an object. If there are none available to your liking perhaps you could use a byte code rewriting library like the Mono project's Cecil. It works on Windows as well as Linux. From some of the demos I saw, it looked pretty cool. You can change the protection levels of methods and all sorts of crazy stuff.
If the class (and the classes of objects that it references) is Serializable, you can create a deep copy by serializing using a BinaryFormatter that outputs to a MemoryStream (creating a byte array byte[]), then deserializing. See the answers to this question on converting an object to a byte array. (But note - saving the byte array to use later/elsewhere is likely not to work. IOW don't save the byte array to a file or other persistent form.)
See the System.Activator.CreateInstance function.
-
Sadly, this is a proper answer. The question was edited after this post.nawfal– nawfal2014年01月02日 13:04:03 +00:00Commented Jan 2, 2014 at 13:04
-
No, Activator.CreateInstance does invoke the constructor, as stated in the documentation.Macmade– Macmade2023年02月09日 14:14:05 +00:00Commented Feb 9, 2023 at 14:14
What you are asking to do is a violation of the philosophy upon which managed programming was developed. The .Net Framework and C# are built with the principle that, whenever possible, objects should be abstracted away from their underlying memory. Objects are objects, not a structured array of bytes. This is why you can't cast objects to void pointers willy-nilly. When objects are abstracted away from their underlying memory, it is fundamentally invalid to suggest that an object instance can exist without the constructor being invoked.
That said,the .Net framework has made concessions to the fact that in reality, objects are actually represented in memory. With some creativity, it is possible to instantiate value types without invoking their initializers. However, if you feel you need to do it, you're probably doing things wrong.
I noticed the "deadness" of the subject but just for clarification on further readers and to put a final answer that maybe wasn't possible when the question was posted. Here it goes.
It seems that you can instantiate a class without using it's constructors by assigning values to its properties. Here is the address where is the how-to in MSDN for this type of instantiation http://msdn.microsoft.com/en-us/library/bb397680.aspx.
It seems like this is a technique that's not well known because I encountered it in a article in CodeProject and then googled it and didn't find anything about it and later on visited the MSDN Homepage and there was a post that linked me to that exact subject. So it seems that it's an unknown subject rather than a new one because the date on the CodeProject post dates May 2008.
Hope this helps someone else that google's this and comes across with this question.
-
2That's wrong. A parameter-less constructor will still be called. If there only are constructors with parameters, this cannot and will not compile. MSDN is missleading: it's not "without calling" just because you don't type it.Jabe– Jabe2009年04月19日 10:42:47 +00:00Commented Apr 19, 2009 at 10:42
-
The linked MSDN article is very clear about this: "The compiler processes object initializers by first accessing the default instance constructor, and then by processing the member initializations. Therefore, if the default constructor is declared as private in the class, object initializers that require public access will fail."Tim Coulter– Tim Coulter2011年09月13日 07:33:46 +00:00Commented Sep 13, 2011 at 7:33
No one here has quite clarified what is meant by "It can't be done."
The constructor is what creates the object. Your question is akin to "How can I build a sand castle without shaping it like a castle?" You can't -- All you will have is a pile of sand.
The closest thing you could possible do is to allocate a block of memory the same size as your object:
byte[] fakeObject = new byte[sizeof(myStruct)];
(NOTE: even that will only work in MyStruct is a value type)