应该何时将类成员声明为虚拟(C#)/ Overridable(VB.NET)?

为什么我不选择抽象? 声明类成员虚拟有哪些限制? 只能将方法声明为虚拟?

抽象方法或属性(都可以是虚拟的或抽象的)只能在抽象类中声明,并且不能有正文,即您不能在抽象类中实现它。

虚方法或属性必须具有正文,即必须提供实现(即使正文为空)。

如果有人想要使用您的抽象类,他将必须实现一个inheritance自它的类并显式实现抽象方法和属性,但可以选择不覆盖虚拟方法和属性。

例子:

using System; using C=System.Console; namespace Foo { public class Bar { public static void Main(string[] args) { myImplementationOfTest miot = new myImplementationOfTest(); miot.myVirtualMethod(); miot.myOtherVirtualMethod(); miot.myProperty = 42; miot.myAbstractMethod(); } } public abstract class test { public abstract int myProperty { get; set; } public abstract void myAbstractMethod(); public virtual void myVirtualMethod() { C.WriteLine("foo"); } public virtual void myOtherVirtualMethod() { } } public class myImplementationOfTest : test { private int _foo; public override int myProperty { get { return _foo; } set { _foo = value; } } public override void myAbstractMethod() { C.WriteLine(myProperty); } public override void myOtherVirtualMethod() { C.WriteLine("bar"); } } } 

如果您不想在基类中定义任何实现并希望强制在任何派生类中定义它,则可以使用abstract。 如果要提供可由派生类覆盖的默认实现,请将其定义为虚拟实现。

是的,只有方法可以是虚拟的。

如果存在基本实现,则应该将成员声明为虚拟成员,但是有可能在子类中覆盖该function。 也可以使用Virtual而不是abstract来允许方法实现是可选的(即,基本实现是一个空方法)

将成员设置为虚拟时没有限制,但虚拟成员比非虚拟方法慢。

方法和属性都可以标记为虚拟。

Windows Forms需要注意这里的问题。

如果你想要一个可以inheritance的Control / UserControl,即使你没有基类中的逻辑,你也不希望它是抽象的,因为否则你将无法在派生类中使用Designer: http ://www.urbanpotato.net/default.aspx/document/2001

如果你想在你的基类中给它一个实现,你就把它变成虚拟的,如果不这样做你就把它变成抽象的。

是的,只有方法可以声明为虚拟。

抽象意味着您无法提供默认实现。 这反过来意味着所有子类必须提供抽象方法的实现才能实现(具体)。

我不确定你的’限制’是什么意思,所以无法回答这一点。

可以将属性声明为虚拟属性,但您也可以在概念上将它们视为方法。

你的问题与风格有关,而不是技术问题。 我认为这本书http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756围绕你的问题和很多其他人进行了很好的讨论。

首先,我将回答你的第二个问题。 只有方法可以声明为虚拟。 当您需要基类中的某些默认function时,可以选择虚拟而不是抽象,但是您希望保留通过从基类inheritance的类来覆盖此function的选项。 举些例子:

如果你正在实现Shape类,你可能会有一个名为getArea()的方法返回你的形状区域。 在这种情况下,Shape类中的getArea()方法没有默认行为,因此您可以将其实现为抽象 。 将方法实现为抽象将阻止您实例化Shape对象。

另一方面,如果你实现类Dog ,你可能想要在这种情况下实现方法Bark() ,你可能想要实现一个默认的吠叫声并把它放在Dog类中,而一些inheritance类,比如Chiwawa类可能希望覆盖此方法并实现特定的吠叫声。 在这种情况下,方法bark将实现为虚拟 ,您将能够实例化Dogs和Chiwawas。

我个人将大多数方法和属性标记为虚拟。 我使用代理和延迟加载很多,所以我不想担心以后更改的东西。