4

重複の可能性:
ジェネリックメソッドとメソッドのオーバーロード

わかりました、私は偶然これを打ちました...この状況を与える:

class Program {
    static void Main( string[ ] args ) {

        var obj = new gen<int>( );
        Console.Write( obj[ 1 ] );
        Console.ReadKey( );

    }
}

class gen<T> {

    public int this[ T i ] { get { return 2; } }

    public int this[ int i ] { get { return 1; } }

}

常に1を出力します。コンパイラが文句を言うか、ランタイムがクラッシュしてCPUを焼き付けて溶かすと予想していましたが、いいえ、「1」を出力できます。

もちろん、汎用パラメーターに他のタイプを使用する場合は、どちらかを返すことを選択できます。笑い声の場合、ジェネリック型パラメーターとしてUIntを使用してみます。呼び出しを区別できるため、質問は次のとおりです。

  1. なぜC#はおかしくなりませんか?アンダース・ヘルスバーグは部隊の混乱を感じるべきではありませんか?

  2. ジェネリックパラメーターを特定のタイプから制限するにはどうすればよいですか?このように、Tはint以外の何でもかまいません(ただし、長い場合は問題ありません)

4

4 に答える 4

9

これは、C#4仕様(Better Function Member)のセクション7.5.3.2で指定されていると思います。

  • それ以外の場合、 MPにMQよりも具体的なパラメーターの種類がある場合、 MPはMQよりも優れています[...]
    • タイプパラメータは、非タイプパラメータよりも具体的ではありません
    • [...]

したがって、ここでは、パラメーターを持つメンバーは、Tパラメーターを持つメンバーよりも具体的ではありませんint

このように過負荷にならないようにするだけで、これから抜け出す方法を設計してみてください。もちろん、インデクサーにとっては難しいことですが、代わりに(またはフォールバックとして)メソッドを提供することもできます。

編集:両方が型パラメーターであるオーバーロードされたメソッドがある場合、コンパイラー次のように文句を言うことに注意してください:

public class Foo<T1, T2>
{
    public void Bar(T1 t1) {}
    public void Bar(T2 t2) {}
}

...

Foo<int, int> foo = new Foo<int, int>();
foo.Bar(10); // Error

ここでは、どちらの方法もより具体的ではありません。

ジェネリックパラメーターを特定のタイプから制限するにはどうすればよいですか?このように、Tはint以外の何でもかまいません(ただし、長い場合は問題ありません)

これは実際には完全に別の質問ですが、基本的にはできません。型パラメータはさまざまな方法で制約できますが、型を明示的に含めたり除外したりすることはできません。詳細については、制約に関するMSDNページを参照してください。

于 2012-10-23T14:31:11.297 に答える
8

エリックリッパートが言うように:

C#仕様では、ReallyDoIt(string)とReallyDoIt(string)のどちらを呼び出すかを選択できる場合、つまり、同じ署名を持つ2つのメソッドのどちらかを選択したが、1つは一般的な置換によってその署名を取得する場合、 「置換された」署名よりも「自然な」署名。

また、このプロセスはC#仕様7.5.3.2(より優れた関数メンバー)で説明されています。

パラメータタイプシーケンス{P1、P2、…、PN}と{Q1、Q2、…、QN}が同等である場合(つまり、各Piが対応するQiへのID変換を持っている場合)、次のタイブレークルールが適用されます。より良い関数メンバーを決定するために。

  • MPが非ジェネリックメソッドであり、MQがジェネリックメソッドである場合、MPはMQよりも優れています(ジョンが指摘したように、これはジェネリック型ではなくジェネリックメソッドがある場合に当てはまります)
  • ..。
  • それ以外の場合、MPにMQよりも具体的なパラメーターの種類がある場合は、MPの方がMQよりも優れています。{R1、R2、…、RN}および{S1、S2、…、SN}が、MPおよびMQのインスタンス化されていないおよび拡張されていないパラメータータイプを表すとします。MPのパラメータータイプは、各パラメーターについてRXがSXよりも具体的であり、少なくとも1つのパラメーターについて、RXがSXよりも具体的である場合、MQよりも具体的です。

    • 型パラメーターは非型パラメーターよりも具体的ではありません(これはあなたの場合です-したがって、メソッドはジェネリックではなく、推測されるパラメータータイプは非ジェネリックパラメータータイプと同じです)
于 2012-10-23T14:30:55.230 に答える
0

C#コンパイラは、呼び出しが両方に適合する可能性がある場合、常により具体的な方法とより一般的な方法を選択します=)。そういうわけでそれはびっくりしません、彼はただ彼の規則に従います。

于 2012-10-23T14:33:25.460 に答える
-2

両方のメソッドが有効であり、両方を呼び出すことができるため、C#コンパイラは異常になりません。

「2」を返す例を次に示します。

Gen<Form> gen = new Gen<Form>();
textBox1.Text = gen[this].ToString();

「これ」はフォームです。もちろん、数値の代わりにインデックスアクセサーをオブジェクトとして使用します...まあ、それは何でも機能します。

しかし、他のみんなが言ったように、コンパイラは暗黙的よりも明示的を好むでしょう。

于 2012-10-23T14:36:23.353 に答える