1

私が質問に答えようとしたとき:

ServiceクラスのTClientジェネリック型を取り除くことは可能ですか?

この種のコンパイルできない構文を設計したことがないという奇妙な使用法を見つけました。以下は、私が遭遇したことを表しています。

interface IGeneric<T> {
}

partial class SomeClass {
    // won't compile
    public static void SomeMethod<U>(Action<T> d) where T: IGeneric<U> {
    }
}

そして、たとえ次のように宣言されたとしても:

class Concrete: IGeneric<object> {
}

partial class SomeClass {
    public static void SomeMethod<U>(Action<IGeneric<U>> d) { // compiles
    }
}

次のコードをコンパイル可能にしません。

var d=default(Action<Concrete>);
SomeClass.SomeMethod(d); // won't compile

両方の型パラメーターが関係していなくても機能する構文を認識していません。

だから私はこの種の逆型推論の構文があるのだろうか?または回避策?

4

2 に答える 2

4

簡単な答えはノーです。これは、最初は型推論に関するものではなく、型制約に関するものです。同じ宣言で導入されたtypeパラメーターのみをconstraintを追加できます。したがって、この:

public static void SomeMethod<U>(Action<T> d) where T: IGeneric<U>

メソッド宣言で実際に導入されたときに、のT観点から制約しようとしているため、は無効です。確かに、それ自体はどこにも型パラメーターではありません-しかし、これはでジェネリックであったとしても失敗します。UUTSomeClassT

これに似た多くの状況では、非ジェネリック型で追加の静的メソッドを使用して、型推論を介してジェネリック型のインスタンスを作成できますが、詳細は通常、2つの型パラメーターがあり、それらの1つを明示的に指定します。

注意すべき重要な点の1つは、Action<Concrete>単にはではないということAction<IGeneric<object>>です。たとえば、が依存Concreteする可能性のあるいくつかの追加のプロパティを公開する場合がありますが、与えられた場合、のの実装でそれを簡単に呼び出すことができます。あなたの既存の人は、それを回避するために、-ではなく特定の方法で回避しようとしますが、その時点では、アクションを使用するのは比較的困難です。型推論が機能する場合でも、これが(私の経験では)実用的なアプローチになることはめったにありません。Action<Concrete>Action<IGeneric<object>>IGeneric<object>SomeMethodAction<U>Action<IGeneric<T>>

真に共変のデリゲートに変更するとすぐに(そしてC#4を使用していると仮定して)、気にしない限り、U単に別の署名を使用できます。

using System;

interface IGeneric<T> {}

class SomeClass
{    
    public static void SomeMethod<T>(Func<IGeneric<T>> d) {}
}

class Concrete: IGeneric<object> {}

class Test
{
    static void Main()
    {
        var d = default(Func<Concrete>);
        // This compiles fine
        SomeClass.SomeMethod(d);
    }
}
于 2013-04-26T06:04:44.883 に答える
2

Action<T>問題は、をTで共変であるとして処理しようとしているのに、そうではないということです。実際、それは反変です。

たとえば、このような共変デリゲートがある場合です。

delegate T CovariantCall<out T>();

あなたはあなたが求めていることを簡単に行うことができます。

CovariantCall<IGeneric<object>> covariant = default(CovariantCall<Concrete>);

Tメソッドの宣言された型パラメーターリストでを省略したため、最初の例はコンパイルされません。ただし、これはより良いアイデアであり、制約は検証するだけでパラメーターの分散には影響しないため機能しますが、探しているパラメーターを明示的に指定する必要があり、それを推測することはできません。

public static void SomeMethod<T, U>(Action<T> d) where T: IGeneric<U>
{ 
    ...
}

SomeClass.SomeMethod<Concrete, object>(default(Action<Concrete>));

C#型推論で可能なことには制限があり、これはその1つです。タイプを明示的に指定せずに、求めていることを実行することはできません。

于 2013-03-25T19:53:21.717 に答える