一个好的做法留下了一个空的界面?

时间:2012-01-27 20:41:42

标签: c# interface

这一次,我要创造一个数学问题。我计划有一个词典,其中键是Levels enum {Easy,Medium,Hard},值应该包含一些关于如何创建问题的配置。

例如:

BinaryProblemConfiguration
    + Bound1 : Bound<int>
    + Bound2 : Bound<int>

Bound有两个属性:min和max。

其他类型的问题不需要Bounds,但需要其他数据。

所以,我在想创建一个名为IConfiguration的接口。

public interface IConfiguration {}

具体的配置应该是:

public class BinaryProblemConfiguration : IConfiguration
{
    public Bound Bound1 {get;set;}
    public Bound Bound2 {get;set;}
}

public class AnotherProblemConfiguration : IConfiguration
{
    // other stuff
}

我们的想法是拥有一个名为ConfigurationLevels的字典。这是一个很好的做法让界面空了或者我的设计意味着错误吗?

3 个答案:

答案 0 :(得分:8)

.NET Framework设计指南将其称为“标记”界面,并且肯定地说这是一个坏主意。他们改为使用自定义属性进行推荐。

  

避免使用标记接口(没有成员的接口)。

     

自定义属性提供了一种标记类型的方法。欲获得更多信息   有关自定义属性,请参阅编写自定义属性。习惯   当您可以推迟检查属性时,首选属性   直到代码执行。如果您的方案需要编译时   检查,你不能遵守这个准则。

http://msdn.microsoft.com/en-us/library/ms229022.aspx

public sealed class ConfigurationAttribute : Attribute {

}


[ConfigurationAttribute]
public class AnotherProblemConfiguration : IConfiguration 
{ 
    // other stuff 
} 

答案 1 :(得分:2)

您将在哪里使用IConfiguration的实例?如果有这样的用例:

void Something(IConfiguration configuration) { ... }

然后是的,很好。但是使用空接口,这将是一个有趣的用例。另外,想到的是序列化对象,你知道通过该方法序列化的对象必须是IConfiguration,但你实际上并不关心IConfiguration的样子:

void SerializeConfiguration(IConfiguration configuration) { ... }

现在从纯粹的功能角度来看,这对Object也有效,但我认为这是提供编译时机制的一种合理方式,强烈建议除了使用此方法的配置之外,有人不会序列化任何内容

这些的另一个常见用法是标记接口,您可以使用反射来查找通过实现公共接口来“标记”的类型。

答案 2 :(得分:1)

拥有一个扩展另一个接口但不添加任何内容的接口绝对有用。例如,可以很容易地想象IImmutableEnumerable<T>的继承自IEnumerable<T>的用例,但承诺它返回的项目序列永远不会因任何原因而改变。需要包含不会更改的项列表的例程可能会导致IEnumerable<T>IImmutableEnumerable<T>重载。第一个重载可以检查提供的对象实例是否实现IImmutableEnumerable<T>,如果没有,则通过复制原始项中的项来生成新的不可变列表。第二个重载可以直接使用传入列表,因为知道实现IImmutableEnumerable<T>

有点难以想象一个没有任何成员的界面的用例。这样的接口可以在约束中使用,以允许例程接受没有其他公共基类型的各种类型,但不幸的是,类层次结构足够复杂以使这样的事物在概念上有用,这使得很难保持满足这些约束的对象。