5

誰でもこの問題を説明できますか?

これを機能させる唯一の方法は、新しいキーワードの代わりに、CorrectName で virtual を使用してから Derived でオーバーライドすることですが、なぜこれが起こっているのでしょうか?

ジェネリックでキャストするとベース値が返され、直接キャストすると派生値が返されるのはなぜですか? ((出力は以下))

ありがとう、私が言ったように、私はすでに「解決策」を手に入れましたが、理解したいです

    class Base
    {
        public string Name { get; set; }
        public string CorrectName { get { return Name; } }
    }
    class Derived : Base
    {
        public new string CorrectName { get { return "NEW" + Name; } }
    }
    static void Main(string[] args)
    {
        List<Derived> container = new List<Derived>();

        var d = new Derived() { Name = "NameDerived2" };

        container.Add(d);

        Search<Derived>(container);
        Console.ReadLine();
    }

    static void Search<T>(List<T> list) where T : Base
    {
        foreach (var el in list)
        {
            Console.WriteLine("No Cast -->" + el.CorrectName);
            Console.WriteLine("Generic Cast -->" + (el as T).CorrectName);
            Console.WriteLine("Direct Cast -->" + (el as Derived).CorrectName);
        }
    }

出力:

No Cast -->NameDerived2

Generic Cast -->NameDerived2

Direct Cast -->NEWNameDerived2

真実の表:

el is Derived == true
el.GetType().Equals(typeof(Derived)) == true
el.GetType().Equals(typeof(T)) == true
el.GetType().Equals(typeof(Base)) == false
typeof(T).Equals(typeof(Base)) == false
typeof(T).Equals(typeof(Derived)) == true
4

2 に答える 2

4

キーワードがないvirtualと、基本クラスのメソッドはオーバーライドされませんが、新しい実装によって「隠され」ます。newまた、キーワード inを使用してこれを強制していますDerived。ジェネリック メソッドの宣言で述べたようTに、メソッドに渡されるものはすべて型Baseでなければならないため、すべてTが にキャストされBaseます。

を使用しないvirtualと、ポリモーフィズムが失われます。つまり、実際にはオブジェクトの型が であるにもかかわらず、 にDerivedキャストするBaseと、 のBase実装CorrectNameが呼び出されます。ご想像のとおり、 の新しい実装ではありません。Derived.

これは、オブジェクトを明示的に にキャストした場合にのみ呼び出されますDerived

これについては、ここでも議論および説明されています: c# の virtual キーワード

仮想メソッドと非仮想メソッドの違いを理解するのに役立つ別のリンクは次のとおりです: http://en.wikipedia.org/wiki/Virtual_method_table

于 2012-12-21T10:58:54.070 に答える
0

非仮想メソッドは、実行時ではなくコンパイル時にバインドされます。コンパイル時に保証できるのは であることだけであるTためBase、コンパイラはプロパティ アクセサーを のBaseバージョンにバインドしCorrectName、これは実行時に変更されません。Derived型パラメーターとしてメソッドを呼び出していますが、他の人は、またはそれ自体Tから継承する別の型で呼び出すことができます。BaseBase

ただし、仮想メソッドは実際のランタイム タイプを検査し、オーバーライドされた正しいメソッドを呼び出します。

あなたが投稿した「真実の表」は、実行時にすべて評価されるため、ここでは関係ありません。Tコンパイラが であるかのように評価することを証明するにはBase、次のことを試してください。

T t = default(T);
object o = t; // works
Base b = t; // works
Derived d = t; // doesn't work
于 2012-12-24T00:38:30.273 に答える