我有一个带有一些抽象方法的类,但我希望能够在设计器中编辑该类的子类。但是,设计者不能编辑子类,除非它可以创建父类的实例。所以我的计划是用存根替换抽象方法并将它们标记为虚拟 - 但是如果我创建另一个子类,如果我忘记实现它们,我将不会收到编译时错误。
有没有办法标记方法,以便它们必须由子类实现,而不将它们标记为抽象?
我有一个带有一些抽象方法的类,但我希望能够在设计器中编辑该类的子类。但是,设计者不能编辑子类,除非它可以创建父类的实例。所以我的计划是用存根替换抽象方法并将它们标记为虚拟 - 但是如果我创建另一个子类,如果我忘记实现它们,我将不会收到编译时错误。
有没有办法标记方法,以便它们必须由子类实现,而不将它们标记为抽象?
好吧,你可以做一些非常混乱的代码#if
——即DEBUG
它是虚拟的(对于设计师来说),但RELEASE
它是抽象的。不过,要维持真的很痛苦。
但除此之外:基本上,没有。如果你想要设计师支持,它不能是抽象的,所以你只剩下“虚拟”(大概是基础方法抛出 a 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 并公开一个允许您更改实现的属性。
请注意,构造函数中未设置“DesignMode”。它是在 VS 解析 InitializeComponents() 方法之后设置的。
我知道它并不完全是你所追求的,但你可以让基类中的所有存根都抛出 NotImplementedException。然后,如果您的任何子类没有覆盖它们,那么当基类中的方法被调用时,您将获得运行时异常。
Component 类包含一个名为“DesignMode”的布尔属性,当您希望代码在设计器中的行为与运行时不同时,该属性非常方便。在这种情况下可能会有一些用处。
作为一般规则,如果一种语言无法做某事,这通常意味着有一个很好的概念理由不去做。
有时这将是语言设计者的错——但并不常见。通常我发现他们比我更了解语言设计;-)
在这种情况下,您需要一个未覆盖的虚拟方法来引发编译时异常(而不是运行时异常)。基本上是一个抽象方法。
让虚拟方法表现得像抽象方法只会为你进一步创造一个混乱的世界。
另一方面,VS 插件设计通常并不完全处于同一水平(这有点不公平,但肯定比在语言设计阶段应用的严格性要低——这是正确的)。一些 VS 工具,如类设计器和当前的 WPF 编辑器,是不错的想法,但还不是很完整。
在您所描述的情况下,我认为您有一个不使用类设计器的论点,而不是破解您的代码的论点。
在某个时候(可能在下一个 VS 中),他们会整理类设计器如何处理抽象类,然后你就会有一个不知道为什么要这样编码的 hack。
它应该始终是破解代码以适应设计者的最后手段,并且当您尝试将破解保持在最低限度时。我发现拥有简洁易读的代码通常比在当前损坏的工具中工作的拜占庭代码更有意义。
以 ms 为例...
Microsoft 使用 silverlight 中的用户控件模板执行此操作。#if 是完全可以接受的,而且工具是否会很快解决它是值得怀疑的。恕我直言