【问题标题】:Virtual and New in C# [duplicate]C# 中的虚拟和新功能 [重复]
【发布时间】:2016-03-01 00:32:23
【问题描述】:

我在 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();
    }
}

运行 Main 函数后,我得到了这个:

Derived Via Base Reference
Derived.DoSomethingVirtual
Base.DoSomethingNonVirtual

Derived Via Derived Reference
Derived.DoSomethingVirtual
Derived.DoSomethingNonVirtual

为什么baseRef.DoSoemthingNonVirtual 会调用base 函数?它与该函数的派生类中的“new”关键字有关吗? 我理解“虚拟”和“覆盖”的重要性。我的困惑是由以下声明引起的: BaseClass BaseRef = new DerivedClass();

【问题讨论】:

  • 这里new的唯一作用是抑制警告。

标签: c# .net virtual


【解决方案1】:

BaseRef.DoSoemthingNonVirtual 为什么调用基函数?

这是你的声明:

BaseClass BaseRef = new DerivedClass();

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

那么这里

BaseRef.DoSomethingNonVirtual

你调用方法DoSomethingNonVirtual

BaseRef的类型是什么?

它是BaseClass。所以调用的是这个类的方法而不是DerivedClass的方法。

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

BaseRef.DoSomethingNonVirtual

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

【讨论】:

    【解决方案2】:

    为什么baseRef.DoSomethingNonVirtual会调用base函数?

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

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

    【讨论】:

      【解决方案3】:

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

      使用new,您可以定义一个具有相同名称的方法 - 不多...

      基类不知道这个方法,所以不会被调用。

      【讨论】:

        猜你喜欢
        • 2014-05-12
        • 2019-02-21
        • 1970-01-01
        • 2019-01-01
        • 2019-07-28
        • 2011-08-21
        • 2022-10-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多