1

私は C++ テンプレートに慣れており、C# では動作が少し異なることに気付きました。ここに私が欲しいものがあります:

    T CreateButton<T>() {
       T test = T.create(...some vars...);
       return test;
    }

「作成」メソッドが定義されている基本クラスで派生制約を使用するとうまくいくと思いましたが、それでもコンパイルされません。

次のコンパイル エラーが発生します。**error CS0119: Expression denotes a 'type parameter', where a 'variable', 'value' or 'type' was expected**

C# でやろうとしていることを達成する方法はありますか?

4

5 に答える 5

4

あなたの問題は、ジェネリック T の静的メソッドであるかのように T.Create を呼び出していることです。これには 2 つの問題があります。まず、静的を継承できません (T の型をT.Create がコンパイルされるように「static Create」を定義した基本クラス)。第二に、静的を継承できたとしても、どういうわけか基本クラス .Create() は T を返すことを「知っている」必要があります。

ここで求めているのは Factory です。T のファクトリとして機能するクラスを定義します. すると次のように書けます.

T test = Factory < T >.Create(...いくつかの変数...);

これは、ある種の巨大な switch ステートメントになるように感じます - T の実際の型に基づいて、正しいことを行います。しかし、これは、制御の反転と依存性注入が役立つ場所です。必要な T のタイプごとに「プラグイン」を含む Factory を定義します。IoC を使用してプラグインをファクトリに挿入します。

ここで議論をチェックしてください

于 2012-08-01T16:07:20.997 に答える
2

これはあなたが求めているものです:

class MyFactory<T> where T : new()
{
    public T CreateMyStuff()
    {
        return new T();
    }
}
于 2012-08-01T16:06:37.890 に答える
0

インターフェイス (または基本クラス) を定義して実装する必要があります。に対しても制約する必要がありますnew()。次に、一般的な制約を使用できます。

ジェネリック パラメーターに対して静的メソッドを呼び出すことはできません。IE: で静的メソッドを呼び出すことはできませんT

于 2012-08-01T16:01:47.240 に答える
0

問題は特定の行にありますT.Create(...)

T は変数ではなく型であるため、Create() メソッドがその型の静的メソッドでない限りコンパイルされず、T は create が実際に何であるかを知らないため、コンパイルすることはできません。まずは関数呼び出し。Create() 関数が存在することをコードが認識できるように、何らかの方法で T を制約すると、これを行うことができます。

T が常に何らかの基本クラスのメンバーまたは継承されたメンバーであると仮定すると、関数は次のように宣言されます。

T CreateButton<T>() where T : BusinessObjectBase
{
   T test = (T)BusinessObjectBase.create(...some vars...);
   return test;
}

この場合、静的関数 Create() は BusinessObjectBase 内で宣言され、T として渡される型はそのクラスである、またはそのクラスから拡張されるように制約され、T が Create() を呼び出すことができるコードを保証します。関数。

もちろん、他の人が述べたように、 new() 制約を使用する方がはるかに簡単です。これにより、単純に new T(); を返すことができます。はるかに複雑ではありませんが、作成関数からのこれらのパラメーターはすべて失われます。

于 2012-08-01T16:08:02.297 に答える
0

制約を満たす型を除いて、new型だけが与えられた場合、ジェネリック型の新しいオブジェクトを作成する方法はありません。代わりに、おそらく最善の策は、タスクに適したデリゲートを受け入れるものを作成する必要があるメソッドを持つことです。

// コンストラクターが取るものを作成できるようにする必要があるとします
// Int32. 次に、次のようにします。

void MakeLotsOfTs<T>(Func<Int32, T> CreationProc) // その他必要なもの
{
  ... 指定された整数 N に対して新しい T が必要なときはいつでも、CreationProc(N) を呼び出します
}

Fooコンストラクターが を受け取るクラスがありInt32、それを上記のメソッドに渡したい場合は、

  MakeLotsOfTs<Foo>( (Int32 param) => new Foo(param) );

このアプローチは、コンストラクターが何か他のものを必要とするクラスで使用したい場合でも機能することに注意してください (たとえば、次のようなことができます:

MakeLotsOfTs<Bar>( (Int32 パラメータ) => new Bar(String.Format("Bar #{0}", param)) );

このアプローチは、「パラメータ化された」new制約を指定できる場合よりも、呼び出し元に少し多くの作業を必要としますが、はるかに強力です。

于 2012-08-01T16:53:08.630 に答える