C# 中的虚拟和新功能

Virtual and New in C#

我在 C# 中有以下 类:

public class BaseClass
{
    public virtual void DoSomethingVirtual()
    {
        Console.WriteLine("Base.DoSomethingVirtual");
    }

    public new void DoSomethingNonVirtual()
    {
        Console.WriteLine("Base.DoSomethingNonVirtual");
    }
}

public class DerivedClass : BaseClass
{
    public override void DoSomethingVirtual()
    {
        Console.WriteLine("Derived.DoSomethingVirtual");
    }

    public new void DoSomethingNonVirtual()
    {
        Console.WriteLine("Derived.DoSomethingNonVirtual");
    }
}

class ConsoleInheritanceTrial
{
    static void Main(string[] args)
    {
        Console.WriteLine("Derived via Base Reference.");

        BaseClass BaseRef = new DerivedClass();
        BaseRef.DoSomethingVirtual();
        BaseRef.DoSomethingNonVirtual();

        Console.WriteLine();
        Console.WriteLine("Derived via Dereived Reference.");

        DerivedClass DerivedRef = new DerivedClass();
        DerivedRef.DoSomethingVirtual();
        DerivedRef.DoSomethingNonVirtual();

        Console.Read();
    }
}

在 运行 主函数之后,我得到了这个:

Derived Via Base Reference
Derived.DoSomethingVirtual
Base.DoSomethingNonVirtual

Derived Via Derived Reference
Derived.DoSomethingVirtual
Derived.DoSomethingNonVirtual

为什么 baseRef.DoSoemthingNonVirtual 调用了基函数?它与该函数的 Derived Class 中的 "new" 关键字有关吗? 我了解 "virtual" 和 "overrides" 的重要性。我的困惑是由以下声明引起的: BaseClass BaseRef = new DerivedClass();

如果您定义了一个 virtual 方法,并且在派生的 class 中 override 它,该方法将在所有级别具有覆盖行为。基 class 将使用派生方法。这就是为什么大多数时候被覆盖的方法在内部调用它们的基本实现的原因。

使用 new 您可以定义一个同名方法 - 不多...

基础class不知道这个方法,所以不会调用。

Why did the BaseRef.DoSoemthingNonVirtual call the base function?

这是您的声明:

BaseClass BaseRef = new DerivedClass();

这里您创建了一个 DerivedClass 类型的对象,并将其引用分配给一个 BaseClass 类型的变量。这是可以做到的,因为 DerivedClass 的基本类型是 BaseClass.

然后这里

BaseRef.DoSomethingNonVirtual

您调用方法 DoSomethingNonVirtual

What is the type of BaseRef?

BaseClass。所以这个 class 的方法被调用而不是 DerivedClass 的方法。

所以这里的问题是你已经创建了一个DerivedClass类型的对象,并且你将这个对象的引用分配给了一个BaseClass类型的变量。 所以CLR,第一次看到这个调用的时候

BaseRef.DoSomethingNonVirtual

必须解析BaseRef的类型,然后查看对象的方法table,选择相应的IL,最后生成相应的本地代码。 CLR 将如何解决这个问题?作为 BaseClass 而不是 DerivedClass.

类型的对象

Why did the baseRef.DoSomethingNonVirtual call the base function?

因为 baseRef 的编译时类型是 BaseClass,方法调用被解析为 BaseClass.DoSomethingNonVirtual()baseRef引用的对象的实际类型是DerivedClass,但编译器不知道。

此方法不是虚拟的,因此在 运行 时调用它时,CLR 将简单地调用 BaseClass 实现。