52

C#では、コンパイラーがジェネリック型パラメーターを推測できる場合は、ジェネリック型パラメーターを指定する必要はありません。たとえば、次のようになります。

List<int> myInts = new List<int> {0,1,1,
    2,3,5,8,13,21,34,55,89,144,233,377,
    610,987,1597,2584,4181,6765};

//this statement is clunky
List<string> myStrings = myInts.
    Select<int,string>( i => i.ToString() ).
    ToList<string>();

//the type is inferred from the lambda expression
//the compiler knows that it's taking an int and 
//returning a string
List<string> myStrings = myInts.
    Select( i => i.ToString() ).
    ToList();

'aこれは、型パラメーターがコンパイラーによって追加されるため、型パラメーターが何であるかがわからない(インテリセンスではとして表示される)匿名型に必要です。

クラスレベルの型パラメータでは、これを行うことはできません。

//sample generic class
public class GenericDemo<T> 
{
    public GenericDemo ( T value ) 
    {
        GenericTypedProperty = value;
    }

    public T GenericTypedProperty {get; set;}
}

//why can't I do:
int anIntValue = 4181;
var item = new GenericDemo( anIntValue ); //type inference fails

//however I can create a wrapper like this:
public static GenericDemo<T> Create<T> ( T value )
{
    return new GenericDemo<T> ( value );
}

//then this works - type inference on the method compiles
var item = Create( anIntValue );

C#がこのクラスレベルのジェネリック型推論をサポートしないのはなぜですか?

4

3 に答える 3

31

実際、あなたの質問は悪くありません。私はここ数年、ジェネリック プログラミング言語をいじっていましたが、実際にそれを開発したことはありません (おそらくこれからも開発するつもりはありません) が、ジェネリック型の推論について多くのことを考えてきました。私の最優先事項の 1 つはジェネリック型を指定せずにクラスを構築できるように常にされてきました。

C# には、これを可能にする一連のルールが欠けています。開発者はこれを含める必要性を認識していなかったと思います。実際、次のコードはあなたの命題に非常に近く、問題を解決します。C# で必要なのは、追加の構文サポートだけです。

class Foo<T> {
    public Foo(T x) { … }
}

// Notice: non-generic class overload. Possible in C#!
class Foo {
    public static Foo<T> ctor<T>(T x) { return new Foo<T>(x); }
}

var x = Foo.ctor(42);

このコードは実際に機能するので、問題はセマンティクスの問題ではなく、単にサポートの欠如の問題であることを示しました。以前の投稿を取り戻さなければならないと思います。;-)

于 2008-09-05T12:58:05.767 に答える
10

C#がこのクラスレベルのジェネリック型推論をサポートしないのはなぜですか?

彼らは一般的に曖昧だからです。対照的に、型推論は関数呼び出しでは簡単です(すべての型が引数に表示される場合)。ただし、コンストラクター呼び出し(説明のために、栄光の関数)の場合、コンパイラーは同時に複数のレベルを解決する必要があります。1つのレベルはクラスレベルで、もう1つのレベルはコンストラクター引数レベルです。これを解決することは、アルゴリズム的に重要であると私は信じています。直感的には、NP完全でさえあると思います。

解決が不可能な極端なケースを説明するために、次のクラスを想像して、コンパイラが何をすべきかを教えてください。

class Foo<T> {
    public Foo<U>(U x) { }
}

var x = new Foo(1);
于 2008-09-05T12:05:24.643 に答える
2

Konrad に感謝します。これは良い反応 (+1) ですが、それを拡張するだけです。

C# に明示的なコンストラクター関数があるとしましょう。

//your example
var x = new Foo( 1 );

//becomes
var x = Foo.ctor( 1 );

//your problem is valid because this would be
var x = Foo<T>.ctor<int>( 1 );
//and T can't be inferred

最初のコンストラクターを推論できないというあなたの言う通りです。

それでは、クラスに戻りましょう

class Foo<T> 
{
    //<T> can't mean anything else in this context
    public Foo(T x) { }
}

//this would now throw an exception unless the
//typeparam matches the parameter
var x = Foo<int>.ctor( 1 );

//so why wouldn't this work?
var x = Foo.ctor( 1 );

もちろん、コンストラクターを (別の型で) 再度追加すると、あたかも通常のメソッドのオーバーロードが解決できないかのように、あいまいな呼び出しになります。

于 2008-09-05T12:48:42.480 に答える