質問

これは、既に回答されている何かである場合、事前に謝罪ので、

-

この種のものが、まったく同じではないについて、既にスタックオーバーフローのいくつかの記事があります。

なぜこれが動作しません。

public class MyBase { }

public class MyUtils
{
    public bool Foo<T> (T myObject) { return true; }
    public bool Foo (MyBase myBaseObject) { return false; }

    public void Go<T> (IEnumerable<T> items)
    {
        foreach (var item in items)
        {
            // this test fails
            Assert.IsFalse (Foo (item));
        }
    }
}
Iは、上記移動()を呼び出すとMyBaseオブジェクトの負荷に渡す場合、

、fooへの各呼び出しがtrueを返すジェネリックはFoo()をコールします。

new MyUtils ().Go (new MyBase[] { new MyBase (), new MyBase () });      

なぜそれは代わりに、特殊なMyBaseバージョンを呼び出すことはありませんか?私は直接はFoo(新しいMyBaseを())を呼び出した場合は、それを正しく行うために呼んで推測します。これは、C#3内のコレクションのための共分散の欠如である、または私はちょうど愚かさと正確にこれをやっていないのですか?

ありがとうございます。

アイザック

役に立ちましたか?

解決

コンパイラは(この場合には、Go機能がある)プログラムがあるときに呼び出すためにどの方法chosesがあるため、

これは、「専門的な」ものを呼び出さないのコンパイルを、のありませんのそれは実行しています。

コンパイラはGo機能をコンパイルした場合、

、それが持っている唯一の情報は、型Tのいくつかのオブジェクトがあるということです。それはあなたが時間内にいくつかの後の時点で型MyBaseのオブジェクトでそれを供給することができる任意のアイデアを持っていません。それが持っている唯一のオプションはFoo<T>の過負荷を選択することであり、それはそれでコンパイルされたプログラムに焼くます。

あなたは実行時に過負荷を選択し、アプリケーションの実行中にオブジェクトを見て、最高の過負荷を選択するためのアプリケーションを使用する場合は、

、それは、「ダイナミックディスパッチ」と呼ばれています、とだけなRubyなどの動的言語で使用されていますなどのPython、PHP、

C#3が完全に静的であり、これをサポートしていません。あなたはこのように動作することを望んでいた場合は種類を確認するためにあなたのコードにif文を記述する必要があると思います。 一方、C#4は、いくつかの動的サポートを有しています。あなたはC#4でこのコードを書いていた場合は、次のように、あなたは「GO」関数を宣言できます:

 public void Go<T> (IEnumerable<dynamic> items)

そして、それが呼び出された過負荷を選択し、実行時に動的ディスパッチを使用して、

MyBaseを取るために専門のオーバーロードを呼び出します

他のヒント

C#の仕様(7.4.3.2)によれば、非ジェネリックメソッドは、一般的なものよりも優れているので、選択されるべきである。

それは、一般的な呼び出しコンテキスト(「foreachの」ループ)内で呼び出されるので、

しかし、私が思うに、一般的なものが、あなたのケースでピックアップされます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top