为接口强制某个类类型

本文关键字:类型 接口 | 更新日期: 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>
{
}