This question already has an answer here:
Reading existing code at work, I wondered how come this could work. I have a class defined in an assembly :
[Serializable]
public class A
{
private readonly string _name;
private A(string name)
{
_name = name;
}
}
And in another assembly :
public void f(Type t) {
object o = Activator.CreateInstance(t);
}
and that simple call f(typeof(A))
I expected an exception about the lack of a parameterless constructor because AFAIK, if a ctor is declared, the compiler isn't supposed to generate the default public parameterless constructor.
This code runs under .NET 2.0.
[EDIT] I'm sorry but I misread the actual code... The sample I provided doesn't illustrate it. I accepted JonH answer because it provided a good piece of information.
See this: Creating instance of type without default constructor in C# using reflection
Here's to the future also, this is in regards to C# 4.0:
Posted by Microsoft on 1/4/2010 at 2:08 PM
We have reviewed your bug and have determined that the behavior that you described is by design. We are now archiving this issue. Thanks for using Visual Studio and the .Net Framework!There are many overloads of Activator.CreateInstance, the one that takes a single type parameter only invokes the default parameterless constructor. Constructors that take an optional parameter like the one in your example are not default constructors. To invoke them you need to:
- use an overload that takes an argument array
- Pass in Type.Missing as the argument
- Specify OptionalParamBinding in the BindingFlags
Here is an example:
Activator.CreateInstance(typeof(MyClassName), BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance | BindingFlags.OptionalParamBinding, null, new Object[] {Type.Missing}, null);
Thanks,
Weitao Su
Microsoft Corp.
A
elsewhere, or the assembly it is being loaded from is not being updated. It sounds like more of a project/solution problem rather than a code anomaly. - Codesleuth
An alternative is:
object obj = System.Runtime.Serialization.FormatterServices
.GetUninitializedObject(t);
which creates the object in memory but doesn't run any constructor. Scary.
This may not be feasible for you to do, but the simplest thing is to pass the argument list after the type like so:
Activator.CreateInstance(t, "name");
You'll want to think about what f() is really trying to do. Should it be instantiating an object of type A at all? What other classes will it instantiate?
One possibility is to have a switch statement within f() which passes the correct parameters to CreateInstance() for class A. This won't scale, but that may not be an issue for you.
There are two confusing flavors of CreateInstance
: one that takes an object of type System.Type
as a parameter, another that takes a type parameter T
.
First one:
object Activator.CreateInstance(type As Type) { }
Second one:
T Activator.CreateInstance<T>() { }
The second one is the one that doesn't work for a class without a public parameterless constructor.
Note that it almost never makes sense to even use the second one; in any case where it would be used, it would be better to have a where T : new()
constraint on your class and simply use T
's constructor.
The MSDN documentation agrees:
In general, there is no use for the
CreateInstance
in application code, because the type must be known at compile time. If the type is known at compile time, normal instantiation syntax can be used (new
operator in C#,New
in Visual Basic,gcnew
in C++).
EDIT: I may have spoken too soon; it appears the first version isn't supposed to work either.