web-dev-qa-db-ja.com

ジェネリック型パラメーターを使用してfuncを渡すにはどうすればよいですか?

ジェネリック型コンバーター関数をメソッドに送信するのが好きですが、その方法がわかりません。

ここに私が達成したいことを説明する無効な構文があります。問題は、私のfuncとともにジェネリック型を指定する方法がわからないことです:

public void SomeUtility(Func<T><object,T> converter)
{
    var myType = converter<MyType>("foo");
}

編集(ローレンスとのコメントでの私の議論も参照してください):「ジェネリック型コンバーター」とは、強い型<T>(オブジェクトではない)に変換できるコンバーターを渡すことを意味するため、次の行はメソッドは次のとおりです。

var myOtherType = converter<MyOtherType>("foo");

パラメーターとして渡すデリゲートは次のようになります。

private delegate TOutput myConverterDelegate<TOutput>(object objectToConvert);

これは構文/ C#の調査になりました。処理を完了するには、おそらく代わりにインターフェイスを使用しますが、これがfunc/delegateで実現できることを願っています。

31
joeriks

汎用の関数またはアクションのインスタンスを持つことはできません-すべての型パラメーターは事前に定義されており、呼び出し元によって再定義することはできません。

簡単な方法は、ダウンキャストに依存することにより、ポリモーフィズムを完全に回避することです。

public void SomeUtility(Func<Type, object, object> converter)
{
    var myType = (MyType)converter(typeof(MyType), "foo");
}

型の安全性が必要な場合は、型パラメーターの定義を呼び出し元に委ねる必要があります。これを行うには、インターフェイス内でジェネリックメソッドを作成します。

public void SomeUtility(IConverter converter)
{
    var myType = converter.Convert<MyType>("foo");
}

interface IConverter
{
   T Convert<T>(object obj);
}

編集:

呼び出しサイトで「コンバータータイプ」がわかっていて、ユーティリティメソッド内でこのタイプのみが使用される場合、他のポスターが示唆しているように、メソッドで汎用タイプを定義して使用できます。

23
public void SomeUtility<T>(Func<object, T> converter)
{
    var myType = converter("foo");
}

その後:

SomeUtility(arg => new MyType());

この場合、ジェネリック型推論が機能します。

16
Darin Dimitrov

SomeUtilityも汎用にする必要があります。これを実行して構文を修正すると、次のようになります。

public void SomeUtility<T>(Func<object,T> converter)
{
    var myType = converter("foo");
}
7
Jon

使用するには、コンパイル時にT型を知る必要があります。 Tは、クラスレベルまたはメソッドレベルで指定できます。

class SomeClass<T> {
    public void SomeUtility(Func<object, T> converter) {
        var myType = converter("foo"); // Already is the T-type that you specified.
    }
}

または

public void SomeUtility<T>(Func<object, T> converter) {
    var myType = converter("foo"); // Already is the T-type that you specified.
}
3
Maarten