74

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.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Chris Gillum
  • 14,526
  • 5
  • 48
  • 61
  • 3
    Related 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 Apr 19 '09 at 10:13
  • Why would you ever want this? If it is just curiosity, that's fine. – nawfal Jan 02 '14 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 Jan 09 '14 at 01:36

12 Answers12

97

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.

Simon
  • 33,714
  • 21
  • 133
  • 202
Hallgrim
  • 15,143
  • 10
  • 46
  • 54
  • In my case, it's only for prototyping. Not for real code that anyone would use for anything remotely important. – Chris Gillum Nov 18 '08 at 06:34
  • I'm planning on using it for deserializing a DataContract object from an unsuported serialized format. – Michael Shaw Nov 27 '11 at 00:01
  • Does GetUninitializedObject() still call static constructors? I've just tried `var ut = FormatterServices.GetUninitializedObject(typeof(UserType));` where `UaserType` is an Umbraco class and contains a static constructor. Each time I execute that line, I get a SQL error since the ctor is being executed. So I'm curious if static ctor's are a problem. – Jason Evans Aug 09 '12 at 08:58
  • 7
    I have tested this out and can confirm that FormatterServices.GetUninitializedObject() does not avoid static ctor's from being called. :( – Jason Evans Aug 09 '12 at 09:24
  • @ChrisGillum even for prototyping, what's wrong with reflection? Mind you `FormatterServices.GetUninitializedObject` would be much slower than `Activator.CreateInstance`. – nawfal Jan 02 '14 at 13:08
  • 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 it – Orion Edwards Jan 08 '14 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 Jan 09 '14 at 01:31
10

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.

Scott Dorman
  • 42,236
  • 12
  • 79
  • 110
Zachary Yates
  • 12,966
  • 7
  • 55
  • 87
6

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.

1

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;
   }
}
Warty
  • 7,237
  • 1
  • 31
  • 49
0

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.)

Community
  • 1
  • 1
Art Swri
  • 2,799
  • 3
  • 25
  • 36
0

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.

rslite
  • 81,705
  • 4
  • 44
  • 47
0

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.

FlySwat
  • 172,459
  • 74
  • 246
  • 311
  • Haven't you just called the constructor without creating an object instance? (eg: the exact opposite of what the question is asking?) – Orion Edwards Nov 17 '08 at 19:52
  • I created the object by calling the hidden constructor, which is what he wanted until he edited his post. – FlySwat Nov 17 '08 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 posted – Orion Edwards Nov 17 '08 at 20:53
  • http://stackoverflow.com/revisions/296584/list <-- I see him adding his note of clarification. – FlySwat Nov 17 '08 at 22:25
0

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.

Sam Corder
  • 5,374
  • 3
  • 25
  • 30
-1

See the System.Activator.CreateInstance function.

Cybis
  • 9,773
  • 2
  • 36
  • 37
-1

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.

Kennet Belenky
  • 2,755
  • 18
  • 20
-1

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.

  • 2
    That'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 Apr 19 '09 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 Sep 13 '11 at 07:33
-3

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)

James Curran
  • 101,701
  • 37
  • 181
  • 258