C#Create New T()


158

次のコードで、私が何をしようとしているのか(ただし失敗しているのか)を確認できます。

protected T GetObject()
{
    return new T();
}

どんな助けでも大歓迎です。

編集:

コンテキストは次のとおりです。私は、標準化されたメソッドを使用して、すべてのコントローラーから派生するカスタムコントローラークラスをいじっていました。したがって、コンテキストでは、コントローラータイプのオブジェクトの新しいインスタンスを作成する必要がありました。したがって、執筆時点では、次のようなものでした。

public class GenericController<T> : Controller
{
    ...

    protected T GetObject()
    {
        return (T)Activator.CreateInstance(ObjectType);
    }        

    public ActionResult Create()
    {
        var obj = GetObject()

        return View(obj);
    }

そして、私はここでの反射が最も簡単だと判断しました。私は確かに、質問の最初のステートメントを考えると、正しいとマークするための最も適切な答えはnew()制約を使用するものであったことに同意します。私はそれを修正しました。


27
いいえ、あなたが何をしようとして失敗したのかわかりません。作業プログラムの一部である可能性のあるコードがあり、コンテキストもエラーメッセージも説明もありません。
Ben Voigt、2011年

17
ええと、間違った答えが選択されたときは嫌です!
David Heffernan

回答:


409

新しい制約を見てください

public class MyClass<T> where T : new()
{
    protected T GetObject()
    {
        return new T();
    }
}

Tデフォルトのコンストラクタを持たないクラスである可能性があります。この場合new T()、ステートメントは無効になります。new()制約は、それが言うTになり、デフォルトコンストラクタ、持っている必要がありますnew T()法的に。

同じ制約をジェネリックメソッドに適用できます。

public static T GetObject<T>() where T : new()
{
    return new T();
}

パラメータを渡す必要がある場合:

protected T GetObject(params object[] args)
{
    return (T)Activator.CreateInstance(typeof(T), args);
}

2
ありがとう、仲間-今日、これを学んでよかったです。私の方法のコンテキストを考えると、私は反射ソリューションに行ってきました。乾杯!
ハンシャン2011年

8
@nulliusinverba-うーん...質問でメソッドのコンテキストを示してくれるといいですね。
Alex Aza 2011年

1
@nulliusinverba-パラメータが必要であることを質問に示さなかった。
Alex Aza

1
@アレックス-私が彼の質問を読んだとき、私は彼がパラメータを望んでいないと思っていました:Sしかしあなたのために賛成票を投じます:)
Phill

new(parameters)制約のようなものを使用することは可能ですか?
Louis Rhys、2011年


29

別の方法はリフレクションを使用することです:

protected T GetObject<T>(Type[] signature, object[] args)
{
    return (T)typeof(T).GetConstructor(signature).Invoke(args);
}

おかげで、仲間-メソッドのコンテキストを考えると、私はこの解決策を使いました。
ハンシャン2011年

22
参考までに、これは別の方法としてActivator.CreateInstance(typeof(T)、signature、args);と書くこともできます。詳細については、msdn.microsoft.com / en- us / library / 4b0ww1we.aspxを参照してください
クリスバクスター2011年

@Calgary Coder:type []シグネチャの用途は何ですか。シグネチャを明示的に指定せずに、パラメータを指定してCreateInstanceを直接呼び出すだけです。どちらの場合も、一致するコンストラクターが存在しない場合、MissingMethodExceptionが発生します。
ボリスB.

4
これがあなたにとって最も効果的な答えであるとしても、それは明らかにコミュニティにとって最良のものではありません。この質問を探している人は、本当に下からの答えを探しています。
トラップ

そして、その文脈は正確には何ですか?元の質問に追加してください。
ジェームズ

18

完了のためだけに、ここでの最善の解決策は、多くの場合、ファクトリー関数の引数を要求することです。

T GetObject<T>(Func<T> factory)
{  return factory(); }

それを次のように呼びます:

string s = GetObject(() => "result");

必要に応じて、それを使用して、使用可能なパラメーターを要求または利用できます。


16

新しい制約は罰金ですが、Tがあまりにも値型であることが必要な場合は、これを使用します:

protected T GetObject() {
    if (typeof(T).IsValueType || typeof(T) == typeof(string)) {
        return default(T);
    } else {
       return (T)Activator.CreateInstance(typeof(T));
    }
}

7

これはC#4でタグ付けされているため、オープンソースフレームワークのImpromptuInterefaceを使用すると、dlrを使用してコンストラクターが呼び出されます。ただし、主な利点は、C#4.0オプションパラメータを使用してコンストラクタを正しく処理することです。これは、Activatorでは行われません。

protected T GetObject(params object[] args)
{
    return (T)Impromptu.InvokeConstructor(typeof(T), args);
}

4

これを取得するには、次のコードを試してみました:

  protected T GetObject<T>()
    {
        T obj = default(T);
        obj =Activator.CreateInstance<T>();
        return obj ;
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.