我的一个应用程序中有几个控件,它们都显然扩展了Control类.
我需要其中几个来拥有一些共享接口,所以我创建了一个覆盖共享功能的接口.
有什么办法可以强制我的界面只能被赋予Control的子类吗?
即(伪)
interface IEmbed
class MyControl1 : Control, IEmbed
class MyControl2 : Control, IEmbed
class MyClass : IEmbed
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望编译器在这里失败,因为MyClass尝试实现IEmbed,即使它不是一个控件.
我是以错误的方式解决这个问题还是有办法强制执行此行为?
编辑
我被问到为什么我希望强制执行此行为.
我有一个方法,我想采取任何IEmbed实现,并将其作为子控件添加到另一个元素.
这一切都很好,但Controls.Add()拒绝接受一个IEmbed对象,这不会编译.
我想如果我告诉编译器实现IEmbed的任何东西必须是一个控件,它可能会工作吗?
不,没有办法在编译时强制执行此操作.
您可以在运行时通过obj is Control在obj用作IEmbed实例之前测试框架代码来强制执行它.
更新:根据评论的反馈,看起来好的解决方案是从中间人继承abstract class EmbedControl : Control并使你的方法接受EmbedControl而不是IEmbed(在这种情况下,实际上不需要保持接口,因为你可以简单使用abstract基类中的方法).
虽然上述方法可以很好地工作,但在某些情况下,强制"客户"类的实现者从您自己的中间类派生是不可取的,即使您需要它们同时从"基类"派生Control.在这种情况下,另一个好方法是使用泛型:
public void DoSomethingWithControl<T>(T control) where T : Control, IEmbed
Run Code Online (Sandbox Code Playgroud)
如果您需要执行此类检查,我建议您检查您的设计.界面只是一个契约,并没有对可以遵守它的内容施加限制.如果类型很重要,那么您应该尝试不同的方法,例如基类.如何使用需要继承者来实现接口方法的抽象类(您可以在其中指定类型约束)?
interface IInterface
{
void Method1();
int Property1 { get; }
}
abstract class BaseClass: Control, IInterface
{
public abstract void Method1();
public abstract int Property1 { get; }
}
Run Code Online (Sandbox Code Playgroud)
这只会确保从BaseClass派生的任何类都是Control和implements IInterface.