5

谁能解释我这个问题?

使其正常工作的唯一方法是在 CorrectName 中使用 virtual,然后在 Derived 中覆盖,而不是 new 关键字,但是,为什么会发生这种情况?

为什么如果我通过泛型转换它会给我 Base 值,如果我直接转换它会给我 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传递给该方法的任何内容都必须是 type Base,因此 eachT被强制转换为Base.

现在发生的情况是,当您不使用 时virtual,您将失去多态性,这意味着,即使对象实际上是 type Derived,但是强制转换为Base,也会调用 的Base实现CorrectName,而不是 - 正如您所期望的那样 - 中的新实现Derived.

仅当您将对象显式转换为Derived.

这也已在此处讨论和描述:虚拟关键字 in c#

另一个可以帮助您了解虚拟和非虚拟方法之间区别的链接可能是:http ://en.wikipedia.org/wiki/Virtual_method_table

于 2012-12-21T10:58:54.070 回答
0

非虚拟方法在编译时绑定,而不是在运行时绑定。在编译时,所有可以保证的T是 a Base,因此编译器将属性访问器绑定到的Base版本,CorrectName这在运行时不会改变。您正在使用Derived作为类型参数调用该方法T,但其他人可以使用继承自的另一种类型Base,甚至是Base其自身来调用它。

然而,虚拟方法将检查实际的运行时类型并调用正确的覆盖方法。

您发布的“真相表”在这里无关紧要,因为所有这些都是在运行时评估的。要证明编译器的计算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 回答