例として次のクラスを取ります。
class Sometype
{
int someValue;
public Sometype(int someValue)
{
this.someValue = someValue;
}
}
次に、リフレクションを使ってこのタイプのインスタンスを作成します。
Type t = typeof(Sometype);
object o = Activator.CreateInstance(t);
通常これはうまくいきますが、SomeType
パラメータのないコンストラクタを定義していません。Activator.CreateInstance
型の例外をスローしますMissingMethodException
メッセージ付き」このオブジェクトにはパラメータなしのコンストラクタが定義されていません。「このタイプのインスタンスを作成する別の方法はありますか?すべてのクラスにパラメータのないコンストラクタを追加するのはちょっと面倒です。
私はもともとこの答えを投稿しましたここにしかし、これはまったく同じ質問ではありませんが、同じ答えを持っているので、ここに転載します。
FormatterServices.GetUninitializedObject()
コンストラクタを呼び出さずにインスタンスを作成します。を使ってこのクラスを見つけましたリフレクターそしてコアの.NETシリアライゼーションクラスのいくつかを掘り下げる。
以下のサンプルコードを使用してテストしましたが、うまく機能しているように見えます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;
namespace NoConstructorThingy
{
class Program
{
static void Main(string[] args)
{
MyClass myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass)); //does not call ctor
myClass.One = 1;
Console.WriteLine(myClass.One); //write "1"
Console.ReadKey();
}
}
public class MyClass
{
public MyClass()
{
Console.WriteLine("MyClass ctor called.");
}
public int One
{
get;
set;
}
}
}
このCreateInstanceメソッドのオーバーロードを使用します。
public static Object CreateInstance(
Type type,
params Object[] args
)
指定されたのインスタンスを作成します 最良のコンストラクタを使ってタイプする 指定されたパラメーターと一致します。
見る:http://msdn.microsoft.com/en-us/library/wcxyzt4d.aspx
ときにベンチマークのパフォーマンス(T)FormatterServices.GetUninitializedObject(typeof(T))
遅くなりました。同時にコンパイルされた式は、デフォルトのコンストラクタを持つ型に対してのみ機能しますが、速度が大幅に向上します。私はハイブリッドアプローチを取りました:
public static class New<T>
{
public static readonly Func<T> Instance = Creator();
static Func<T> Creator()
{
Type t = typeof(T);
if (t == typeof(string))
return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();
if (t.HasDefaultConstructor())
return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();
return () => (T)FormatterServices.GetUninitializedObject(t);
}
}
public static bool HasDefaultConstructor(this Type t)
{
return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}
つまり、create式は事実上キャッシュされ、型が最初にロードされたときにのみペナルティが発生します。値型も効率的な方法で扱います。
あれを呼べ:
MyType me = New<MyType>.Instance();
ご了承ください(T)FormatterServices.GetUninitializedObject(t)
stringでは失敗します。したがって、空の文字列を返すために、stringに対する特別な処理が行われます。
良い答えだがドットネットのコンパクトフレームワークでは使えない。これはCF.Net上で動作するソリューションです...
class Test
{
int _myInt;
public Test(int myInt)
{
_myInt = myInt;
}
public override string ToString()
{
return "My int = " + _myInt.ToString();
}
}
class Program
{
static void Main(string[] args)
{
var ctor = typeof(Test).GetConstructor(new Type[] { typeof(int) });
var obj = ctor.Invoke(new object[] { 10 });
Console.WriteLine(obj);
}
}
FormatterServices.GetUninitializedObject
未初期化文字列を作成することはできません。あなたは例外が発生する可能性があります。System.ArgumentException: Uninitialized Strings cannot be created.
これを覚えておいてください。 - Bartosz Pierzchlewicz