应该使用基本关键字吗?

时间:2009-10-06 17:11:15

标签: c# .net

从派生类调用基类的方法时,是否应该使用'base'关键字?似乎使用base关键字会增加代码的可读性,但对我来说,当我排除它时,对代码编译和执行没有任何影响。

8 个答案:

答案 0 :(得分:13)

重写方法时,base关键字很重要:

override void Foo()
{
  base.Foo();
  // other stuff
}

我从不将它用于其他任何事情。

答案 1 :(得分:9)

你不应该使用base,除非你具体指的是“即使这个类中有一个方法覆盖了基本实现,我想调用基类实现并忽略这个类上的那个”。

使用base通过导致发出call指令而不是callvirt来绕过在多态中非常重要的虚拟调度机制。

所以说base.Foo()语义与this.Foo()非常非常不同。你几乎总是想要后者。

答案 2 :(得分:1)

如果你有overridden方法,那就很重要了:

class Test { 
   public override string ToString() { return "Hello World"; }
   public string M1() { return ToString(); } // Test.ToString
   public string M2() { return base.ToString(); } // System.Object.ToString
   static void Main() { 
       var t = new Test();
       Console.WriteLine("M1: {0}", M1()); // Hello World
       Console.WriteLine("M2: {0}", M2()); // Test
   }
}

答案 3 :(得分:1)

有时候,你无法避免它。如果您的类重写了基类中函数的实现,那么在没有base关键字的情况下,可以将调用分派给您类中的实现。

在所有其他情况下,这是一个风格问题(很像“我应该使用this为所有呼叫/字段访问添加前缀。”我说“不”,因为它往往会增加代码混乱而不会显着提高可读性,但是“是”也是一个有效的答案 - 特别是如果你有一个包含许多重写方法的类,但在层次结构中会包含许多调用。

答案 4 :(得分:1)

我会说不。 base的主要目的是允许您在不进行虚拟分派的情况下调用虚方法的基类版本。就我个人而言,我认为base的任何其他用途都是滥用 - 它并不像往常一样(或使用this)而只是通过调用方法给你带来任何东西,并且如果你以后它会破坏它覆盖你班级中的被调用方法。

此外,如果该方法是虚拟的,则存在非常明显的差异,并且该线路上的某个人会覆盖它。举个例子,假设你写这个(在可重用的类中):

class Base {
   public virtual void Foo() {}
}

class Derived : Base {
   void Bar() { base.Foo(); }
}

后来在使用你班级的其他人写道:

class MoreDerived : Derived {
   public override void Foo() {}
}

现在,您的base.Foo()不会进行动态调度,因此不会在Foo()中调用被覆盖的MoreDerived。它可能是你真正想要的,但我发现这样的代码非常怀疑,如果这是意图。

答案 5 :(得分:0)

有些时候必须使用base关键字,例如当你想调用派生类中被覆盖的基类中的方法时。

答案 6 :(得分:0)

看看这个例子:

    class ParentClass {
        public virtual void A() {
            // Some operations
        }
    }

    class ChildClass : ParentClass {
        public override void A()
        {
            base.A();
        }
    }

如果我们执行ChildClass.A(),那么我们有一些操作,但在这种情况下:

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

    class ChildClass : ParentClass {
        public override void A()
        {
            A();
        }
    }

我们有StackOverflowException,因为ChildClass.A()执行ChildClass.A()

答案 7 :(得分:-1)

在大多数情况下,生成的IL没有差异。

但是,如果要覆盖基类中的虚方法,或者使用“new”关键字在基类中隐藏方法,那么这是必需的,并且会改变含义,因为它显式调用基类方法

然而,这通常是一个好主意,因为它提高了可读性,从而提高了可维护性。如果你明确想要在基类中调用一个方法,那么我觉得这是一个好主意,即使在技术上不需要。