【发布时间】:2011-03-15 23:52:56
【问题描述】:
为什么要在 C# 中显式重写虚方法?
【问题讨论】:
标签: c# .net inheritance virtual
为什么要在 C# 中显式重写虚方法?
【问题讨论】:
标签: c# .net inheritance virtual
通过将方法声明为virtual,您表明您的意图该方法可以在派生类中被覆盖。
通过将您的实现方法声明为override,您表明您的意图您正在覆盖virtual 方法。
通过要求使用 override 关键字来覆盖虚拟方法,语言的设计者通过要求您陈述自己的意图来鼓励清晰。
【讨论】:
override 关键字不是必需的 - 请参阅我的答案。
如果您不添加 override 关键字,该方法将被隐藏(就像它具有 new 关键字一样),不会被覆盖。
例如:
class Base {
public virtual void T() { Console.WriteLine("Base"); }
}
class Derived : Base {
public void T() { Console.WriteLine("Derived"); }
}
Base d = new Derived();
d.T();
此代码打印Base。
如果将override 添加到Derived 实现中,代码将打印Derived。
您不能在 C++ 中使用虚方法执行此操作。 (There is no way to hide a C++ virtual method without overriding it)
【讨论】:
这是因为 C# 团队成员都是熟练的 C++ 程序员。并且知道这个特定的错误有多早:
class Base {
protected:
virtual void Mumble(int arg) {}
};
class Derived : public Base {
protected:
// Override base class method
void Mumble(long arg) {}
};
它比您想象的要普遍得多。派生类总是在另一个源代码文件中声明。您通常不会立即出错,它会在您重构时发生。编译器没有窥探,代码运行非常正常,只是没有按照您的预期执行。你可以看一个小时或一天而看不到错误。
这在 C# 程序中永远不会发生。甚至托管 C++ 也采用了这种语法,故意打破了原生 C++ 语法。永远是勇敢的选择。 IntelliSense 消除了多余的冗词。
在 C# 中有很多类似于这种避免错误的语法的语法调整。
编辑:C++ 社区的其他成员同意并将 override 关键字纳入新的 C++11 语言规范。
【讨论】:
因为它使代码更具可读性:
class Derived : Base
{
void Foo();
}
在 C++ 中,Foo 可能是也可能不是虚拟方法,我们无法通过查看定义来判断。在 C# 中,我们知道一个方法是虚拟的(或不是),因为有一个 virtual 或 override 关键字。
Jason 下面的评论是一个更好的答案。
(为清楚起见进行了编辑)
【讨论】:
override 会使代码的行为完全不同。
不是所有的虚方法都应该被覆盖,尽管所有的抽象方法都应该(并且必须)被覆盖。至于为什么“覆盖”关键字是显式的,那是因为覆盖和隐藏的行为不同。隐藏方法不是通过对基类的引用来调用的,而重写方法是。这就是为什么编译器会特别警告您在隐藏而不是覆盖的情况下应如何使用“new”关键字。
【讨论】: