我有一个带有一些抽象方法的类,但是我想要能够在设计器中编辑该类的子类。然而,设计器无法编辑子类,除非它可以创建父类的实例。所以我的计划是用桩代码替换抽象方法,并将其标记为虚拟的 - 但是如果我创建另一个子类,如果我忘记实现这些方法,我将不会得到编译时错误。
是否有一种方法可以标记这些方法必须由子类实现,而不将它们标记为抽象的?
我有一个带有一些抽象方法的类,但是我想要能够在设计器中编辑该类的子类。然而,设计器无法编辑子类,除非它可以创建父类的实例。所以我的计划是用桩代码替换抽象方法,并将其标记为虚拟的 - 但是如果我创建另一个子类,如果我忘记实现这些方法,我将不会得到编译时错误。
是否有一种方法可以标记这些方法必须由子类实现,而不将它们标记为抽象的?
你可以使用一些相当混乱的代码,涉及到#if
——即在DEBUG
中它是虚拟的(对于设计师来说),但在RELEASE
中它是抽象的。不过这样做会很难维护。
除此之外,基本上没有其他方法。如果你想要设计师支持,它就不能是抽象的,因此只能使用"virtual"(可能需要让基础方法抛出NotImplementedException
)。
当然,你的单元测试将检查这些方法是否已经被实现了,对吧? ;-p
实际上,通过泛型进行测试可能会很容易——即采用以下形式的通用测试方法:
[Test]
public void TestFoo() {
ActualTest<Foo>();
}
[Test]
public void TestBar() {
ActualTest<Bar>();
}
static void ActualTest<T>() where T : SomeBaseClass, new() {
T obj = new T();
Assert.blah something involving obj
}
public class DesignerHappy
{
private ADesignerHappyImp imp_;
public int MyMethod()
{
return imp_.MyMethod()
}
public int MyProperty
{
get { return imp_.MyProperty; }
set { imp_.MyProperty = value; }
}
}
public abstract class ADesignerHappyImp
{
public abstract int MyMethod();
public int MyProperty {get; set;}
}
DesignerHappy只是暴露你想要的接口,但将所有调用转发到实现对象。通过子类化ADesignerHappyImp来扩展行为,这会强制你实现所有抽象成员。
您可以提供ADesignerHappyImp的默认实现,该实现用于默认初始化DesignerHappy并公开一个属性,允许您更改实现。
我知道这并不是你想要的,但你可以在基类中创建所有stub并让它们抛出NotImplementedException。这样,如果任何子类没有重写这些方法,在基类中调用该方法时就会抛出运行时异常。
Component类包含一个名为“DesignMode”的布尔属性,当您希望在设计时与运行时中使代码的行为不同时,它非常方便。 在这种情况下可能会有所帮助。
通常情况下,如果一种语言无法做某件事情,那通常意味着有很好的概念性原因不去做它。
有时这可能是语言设计者的问题 - 但并不经常。通常我发现他们对语言设计的了解比我更多 ;-)
在这种情况下,您需要一个未被覆盖的虚拟方法来抛出编译时异常(而不是运行时异常)。基本上是一个抽象方法。
让虚拟方法像抽象方法一样行为只会在以后给您带来困惑。
另一方面,VS插件设计通常没有达到相同的水平(这有点不公平,但肯定比语言设计阶段应用的严格程度要低)。一些VS工具,如类设计器和当前的WPF编辑器,是不错的想法,但并不完整 - 至少目前还不完整。
在您所描述的情况下,我认为您有理由不使用类设计器,而不是亲自修改代码。
在某个时候(也许在下一个VS中),他们将整理类设计器如何处理抽象类,然后您将拥有一个没有任何理由编写的代码。
将代码修改以适应设计师应该始终是最后的选择,而且当你尝试这样做时,要尽量减少修改。我发现通常最好拥有简洁易读的代码,能够快速理解,而不是使用复杂难懂的代码来适应当前不完善的工具。
NotImplementedException
并对代码进行单元测试。 - Keith以微软公司为例...
在Silverlight中,微软公司使用用户控件模板。 #if是完全可以接受的,而且工具很可能不会很快适应它。 依我之见。