【发布时间】:2019-04-19 12:12:24
【问题描述】:
我正在使用的代码有一个空界面:
public interface ICube {}
它没有方法或属性。
一些类实现ICube,而其他接口继承自ICube。
请有人告诉我 ICube 界面有什么好处?
【问题讨论】:
-
您能分享一些代码吗?它是作业的一部分吗?练习?任务是什么?想法?
我正在使用的代码有一个空界面:
public interface ICube {}
它没有方法或属性。
一些类实现ICube,而其他接口继承自ICube。
请有人告诉我 ICube 界面有什么好处?
【问题讨论】:
您应该从 MSDN 阅读有关 Interface Design 的信息
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/interface
✓ 如果您需要一些通用 API 被包括值类型的一组类型支持,请定义一个接口。
✓ 如果您需要在已经从其他类型继承的类型上支持其功能,请考虑定义接口。
X 避免使用标记接口(没有成员的接口)。
如果您需要将一个类标记为具有特定特征(标记),通常使用自定义属性而不是接口。
✓ 务必提供至少一种接口实现类型。
这样做有助于验证界面的设计。例如,List 是 IList 接口的实现。
✓ 务必提供至少一个 API 来使用您定义的每个接口(将接口作为参数的方法或类型化为接口的属性)。
这样做有助于验证界面设计。例如,List.Sort 使用 System.Collections.Generic.IComparer 接口。
X 不要将成员添加到以前发布的接口。
更多参考: 空界面Are empty interfaces code smell?
【讨论】:
这称为“标记界面”。有时它们被用来表示一个类是为了某种目的。这不是一种可取的做法。
虽然我使用了标记接口,但这里是它们产生的问题的说明。假设我有一个List<ICube>。也许我将它作为方法参数接收。
public interface ICube {} // It's empty!
public void DoSomethingWithTheseCubes(List<ICube> cubes)
{
foreach(var cube in cubes)
{
// what do I do with this cube?
}
}
你可以看到我卡在哪里了。 ICube 只是一个标记接口,所以它没有自己的方法或属性。我不能用它做任何事情。这可能会导致我将每个立方体转换为其他类型,以便我可以用它做一些事情。
public void DoSomethingWithTheseCubes(List<ICube> cubes)
{
foreach(var cube in cubes)
{
(SomeOtherType)cube.DoSomething();
}
}
但如果我强制转换它,我会引发运行时错误,因为我可能不确定每个对象的实际运行时类型是什么。如果我知道运行时类型是什么,那么我应该这样做:
public void DoSomethingWithTheseCubes(List<SomeOtherType> things)
{
foreach(var thing in things)
{
thing.DoSomething();
}
}
我们不能绝对肯定会遇到这个问题,但使用标记界面会引发问题。它使用接口用于其预期目的以外的目的。它更像是一个属性,甚至是一个评论。
接口有两个共同作用的用途:首先,它描述了一个类实现的成员。其次,它允许我们强制转换一个实现接口的类as 该接口。标记接口两者都不做。它们允许我们将对象转换为没有成员的类型。这充其量是无用的,最坏的情况是有害的,因为它会导致更可疑的选角。
【讨论】: