是一个很好的做法留下一个空接口

本文关键字:下一个 接口 很好 一个 | 更新日期: 2023-09-27 18:21:45

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

例如:

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

绑定有两个属性:最小和最大

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

所以,我想创建一个名为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的字典。这是一个很好的做法,让界面空着还是意味着我的设计有问题?

是一个很好的做法留下一个空接口

.NET Framework设计指南称之为"标记"接口,并明确表示这是个坏主意。他们建议改为使用自定义属性。

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

自定义属性提供了一种标记类型的方法。有关详细信息关于自定义属性,请参见编写自定义属性。风俗当您可以推迟检查属性时,首选属性直到代码正在执行。如果您的场景需要编译时间检查,您不能遵守此准则。

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

public sealed class ConfigurationAttribute : Attribute {
}

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

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

void Something(IConfiguration configuration) { ... }

是的,很好。但是对于一个空接口,这将是一个有趣的用例。顺便说一下,脑海中浮现的是序列化对象,您知道要通过该方法序列化的对象必须是IConfiguration,但实际上并不关心IConfiguration:

void SerializeConfiguration(IConfiguration configuration) { ... }

现在,从纯函数的角度来看,这与Object同样适用,但我认为这是一种合理的方式,可以提供一种编译时机制,强烈建议某人使用此方法只序列化配置。

它们的另一个常见用法是标记接口,在标记接口中,您可以使用反射来查找通过实现公共接口"标记"的类型。

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

对于一个根本没有任何成员的接口来说,很难想象用例。这样的接口可以在约束中使用,以允许例程接受没有其他公共基类型的各种类型,但不幸的是,类层次结构足够复杂,使这种东西在概念上有用,这使得很难持久化满足这种约束的对象。