为接口强制某个类类型
本文关键字:类型 接口 | 更新日期: 2023-09-27 18:28:56
我的一个应用程序中有几个控件,它们显然都扩展了Control类。
我需要其中的几个来拥有一些共享接口,所以我创建了一个涵盖共享功能的接口。
有没有什么方法可以强制我的接口只能给Control的子类?
即(伪)
interface IEmbed
class MyControl1 : Control, IEmbed
class MyControl2 : Control, IEmbed
class MyClass : IEmbed
理想情况下,我希望编译器在这里失败,因为MyClass试图实现IEmbed,即使它不是一个控件。
我是不是走错了路,还是有办法强制执行这种行为?
编辑
有人问我为什么要强制执行这种行为。
我有一个方法,我想采用任何IEmbed实现,并将其作为子控件添加到另一个元素中。
这一切都很好,但Controls.Add()拒绝接受IEmbed对象,并且这不会编译。
我想,如果我告诉编译器,任何实现IEmbed的东西都必须是一个控件,它可能会工作吗?
不,在编译时没有办法强制执行。
可以在运行时强制执行它,方法是在使用obj
作为IEmbed
实例之前,让框架代码测试是否为obj is Control
。
更新:根据评论的反馈,看起来一个好的解决方案是从中间abstract class EmbedControl : Control
继承,并使您的方法接受EmbedControl
而不是IEmbed
(在这种情况下,实际上不需要保留接口,因为您可以简单地在基类中使用abstract
方法)。
虽然上面的操作很好,但在某些情况下,强制"客户端"类的实现者从您自己的中间类派生是不可取的,即使您需要它们同时从"基本"类Control
派生也是如此。在这种情况下,另一个好的方法是使用泛型:
public void DoSomethingWithControl<T>(T control) where T : Control, IEmbed
如果你需要进行这样的检查,我建议你审查一下你的设计。一个接口只是一个契约,并没有限制什么可以坚持它。如果类型很重要,那么你应该尝试不同的方法,比如基类。使用一个抽象类(可以在其中指定类型约束),它需要继承者来实现接口的方法,怎么样?
interface IInterface
{
void Method1();
int Property1 { get; }
}
abstract class BaseClass: Control, IInterface
{
public abstract void Method1();
public abstract int Property1 { get; }
}
这只会确保从BaseClass派生的任何类都是Control并实现IInterface。
我认为没有办法强制执行这样的东西,但我认为你真的不需要,因为你只需要在运行时检查接口的实例是否是控件。
但是:alternativley只使用一个抽象类(派生自Control)而不是接口:
abstract class EmbedControl
: Control
{
// your abstract members
}
class MyControl1 : EmbedControl
什么不使用声明和检查T是控件?
另外,我同意上面写的内容,为什么接口应该是一种类型?这看起来像是一个糟糕的deszign,你知道你稍后会把你的界面重新投射到一个控件中。。。
实际上我无法想象你为什么需要它,但Control是IComponent的后代。也许你应该继承它?
好吧,我提供的解决方案非常难看,但在编译时失败了。
public interface IEmbed<T> where T: Control
{
}
public class A :Control, IEmbed<A>
{
}
//this fails at compile time as B does not inherit from Control class.
public class B : IEmbed<B>
{
}