2012-03-26 44 views
1

我在我的一个应用程序中有几个控件,它们都显然扩展了Control类。为界面强制执行某种类别类型?

我需要其中几个具有一些共享接口,所以我创建了一个涵盖共享功能的接口。

有什么办法可以强制我的接口只能被赋予Control的子类吗?

即(伪)

interface IEmbed 

class MyControl1 : Control, IEmbed 

class MyControl2 : Control, IEmbed 

class MyClass : IEmbed 

我非常希望编译器在这里失败,因为MyClass的努力来实现IEmbed即使它不是控制。

我是否有过这种错误的方式,或者有没有办法强制这种行为?

编辑

我一直在问我为什么要实施这种行为。

我有一个方法,我想采取任何IEmbed实现并将其作为子控件添加到另一个元素。

这一切都很好,但Controls.Add()拒绝带一个IEmbed对象,并且这不能编译。

我想如果我告诉编译器,任何实现IEmbed的东西都必须是一个控件,它可能工作?

+0

为什么要将接口只给予Control的子类?也许你需要将它转换回Control?如果是这样,只需在调用实例'Control GetControl()'的接口中添加一个方法即使它不是Control的子类,它也必须提供关联的Control,并且可以避免转换... – digEmAll 2012-03-26 08:22:52

+0

请参阅编辑。 – KingCronus 2012-03-26 09:00:05

+0

@digEmAll如果OP意图将所有实现都作为Controls,那么他确实需要子类化Control(请参阅Strillo的答案)。我认为一个接口更好,因为它没有将任何东西绑定到一个特定的GUI框架,但是其中的一个“Control GetControl()”方法打破了这一切。 – 2012-03-26 09:06:58

回答

6

不,在编译时无法强制执行此操作。

可以通过如果obj is Control使用obj作为IEmbed实例之前,有你的框架代码测试在运行时执行它。

更新:基于从意见反馈,它看起来像一个很好的解决办法是从中间abstract class EmbedControl : Control继承,使您的方法接受一个EmbedControl而不是IEmbed(在这种情况下,不会真的是需要保持界面,因为你可以简单地在基类中使用abstract方法)。

尽管上述方法可以很好地工作,但在某些情况下,强迫“客户”类的实现者从您自己的中间类派生出来是不可取的,即使您需要它们从“基”类Control派生同时。在这种情况下,另一个好办法是使用泛型:

public void DoSomethingWithControl<T>(T control) where T : Control, IEmbed 
+0

我同意,问题是,我们不知道为什么OP需要强制执行此行为,并且可能还有另一种方法来实现这一点... – digEmAll 2012-03-26 08:28:56

+0

我想我会重新考虑我的设计... – KingCronus 2012-03-26 08:52:52

+0

我有一个方法,我想要采取任何IEmbed实现并将其作为子控件添加到另一个元素。 这一切都很好,但Controls.Add()拒绝采用IEmbed对象,并且这不会编译。 我想如果我告诉编译器,实现IEmbed的东西必须是一个控件,它可能会工作? – KingCronus 2012-03-26 09:00:12

2

我不认为有一种方法来执行这样的事情 - 但我不认为你真的需要,你才可以检查在运行时如果你的接口的实例是一个Control。

但是:alternativley只使用一个抽象类(从Control派生的),而不是接口:

abstract class EmbedControl 
    : Control 
{ 
    // your abstract members 
} 

class MyControl1 : EmbedControl 
5

如果你需要做的进行这样的检查,那么我建议你检查你的设计。一个接口只是一个契约,并不会限制遵守它的东西。如果类型很重要,那么你应该尝试一种不同的方法,比如基类。 如何使用抽象类(可以指定类型约束)需要继承者来实现接口的方法?

interface IInterface 
{ 
    void Method1(); 
    int Property1 { get; } 
} 

abstract class BaseClass: Control, IInterface 
{ 
    public abstract void Method1(); 
    public abstract int Property1 { get; } 
} 

这只会确保从BaseClass派生的任何类都是一个Control并实现IInterface。

0

什么不使用声明和检查T是一个控制?

此外,我同意什么是写的abaove,为什么要一个接口是一种类型?它似乎是一个糟糕的deszign,你知道你将把你的接口重新投入到控件后...

0

其实我无法想象为什么你需要那个,但控制是IComponent的后代。 也许你应该从那里继承?

0

那么,我提供的解决方案是一个非常丑陋的,但它在编译时失败。

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> 
{ 
} 
+0

我的意思是它失败,因为B没有实现控制。这是所问的行为。 – daryal 2012-03-26 08:48:48

+0

thx这是星期一,错过了代码中的评论。我认为代码一般不会编译。 – RvdK 2012-03-26 08:55:35

+2

这不是一个好的解决方案。开发人员可能很容易打破这个不知道“T”的目的,并声明“C类:IEmbed ”。 – 2012-03-26 09:11:10

相关问题