c#中的虚拟关键字

时间:2012-12-13 09:34:03

标签: c# virtual

我对java有所了解,过去几天一直在学习c#。现在我遇到了“虚拟”关键字,正如this link所建议的那样,用于允许在子类中覆盖相应的方法,属性等。现在我认为即使不使用“virtual”关键字也可以覆盖方法。那为什么有必要呢?

5 个答案:

答案 0 :(得分:12)

如果您真的想要子类中的virtual方法,则需要override关键字。否则,新实现将隐藏基本实现,就像您使用new关键字声明它一样。

通过“覆盖”它们来隐藏方法而不声明基本方法virtual会使你没有多态性,这意味着:如果你将“专用版本”“转换”为“基础”版本并调用方法,将使用基类实现而不是重写版本 - 这不是您所期望的。

示例:

class A
{
    public void Show() { Console.WriteLine("A"); }
}

class B : A
{
    public void Show() { Console.WriteLine("B"); }
}

A a = new A();
B b = new B();

a.Show(); // "A"
b.Show(); // "B"

A a1 = b;
a1.Show(); // "A"!!!

答案 1 :(得分:7)

virtual是一种定义方法具有默认实现的方法,但该实现可以在子类中重写。除了使用虚拟之外,您无法在不使用new关键字的情况下直接覆盖方法(这通常是不好的做法)。

virtual方法的一个很好的示例是ToString()方法。 C#中的每个对象都保证能够调用ToString(),因为每个对象都继承自基类System.Object类,其中包含虚方法ToString()。派生类可以覆盖它,并提供它们自己的实现,这可能对对象的用户更有用。

更新:我最近写了一篇博文,深入探讨了这个主题。 Check it out here

答案 2 :(得分:2)

  

现在我认为即使不使用“virtual”关键字也可以覆盖方法。

不,你不能。与Java相反,C#成员默认密封除非您使用virtual关键字标记,否则无法覆盖它们。

答案 3 :(得分:1)

看一下这个例子:

    void Main()
    {
        var o1 = new S();
        Console.WriteLine(((B)o1).m1());    
    }

    public class B
    {
        public virtual string m1() {
            return "m1";
        }
    }

    public class S : B
    {
        override public string m1() {
            return "overridden m1";
        }
    }

在此示例中,子类S被实例化并分配给对象变量o1。 在Console.WriteLine语句的参数中,它被强制转换为基类B,然后调用方法m1。 因为我们在子类virtual中使用了B而在子类override中使用了S,所以我们得到了

  

重写了m1

作为输出。如果您删除了virtual中的m1B子类override的方法声明中的S,那么您将获得

  

M1

作为输出,这意味着强制转换还具有使用基类m1中方法B的原始声明的效果。

N.B。如果您在子类new中使用S关键字,例如

         new public string m1() {
            return "overridden m1";
        }

假设基类virtual中的B关键字不存在,那么您将获得输出

  

M1

也是。如果您不将其强制转换为B,则会使用新方法。这称为 shadowing (或隐藏)方法(基类的原始方法)。

摘要:

  • 要覆盖一个方法,该方法在强制转换为基类时也应该有效,请在基类中使用virtual关键字,在子类中使用override

  • 如果要覆盖仅在子类中处于活动状态的方法,请在子类方法声明中使用new关键字。正如你所看到的那样它也可以没有它,但如果它存在则更好,所以每个人都知道这是该方法的新版本。

答案 4 :(得分:0)

如果派生类被实例化为基类,virtual/override 将允许派生类覆盖基函数。 示例:

      class A
      {
         public virtual void Show() { Console.WriteLine("A"); }
      }

      class B : A
      {
         public override void Show() { Console.WriteLine("B"); }
      }


         A a = new A();
         B b = new B();

         a.Show(); 
         b.Show(); 

         A a1 = b;
         a1.Show();  // here is the test!!!

         B b1 = new B();
         b.Show();  

With virtual / override :
A
B
B
B

After removing virtual / override keywords (or simply removing override):
A
B
A
B