空接口代码有异味吗?

Sed*_*glu 76 c# design-patterns

我有一个函数返回相同类型的对象(查询结果),但没有共同的属性或方法.为了有一个共同的类型,我使用空接口作为返回类型,并在两者上"实现".

这听起来不对.我只能通过坚持希望有一天这些类会有一些共同点来安慰自己,我会将这个共同的逻辑移到我的空接口上.然而,我并不满足于思考我是否应该采用两种不同的方法并有条件地呼叫下一步.这会是一个更好的方法吗?

我还被告知.NET Framework使用空接口进行标记.

我的问题是:空接口是设计问题的强烈标志还是被广泛使用?

编辑:对于那些感兴趣的人,我后来发现功能语言中的歧视联盟是我试图实现的完美解决方案.C#对这个概念似乎并不友好.

编辑:我写了一篇关于这个问题的文章,详细解释了问题和解决方案.

Urb*_*Esc 48

虽然看起来存在一种设计模式(很多人现在都提到了"标记界面"),但我相信这种实践的使用是代码气味的指示(至少大部分时间).

正如@ V4Vendetta发布的那样,有一个针对此的静态分析规则:http://msdn.microsoft.com/en-us/library/ms182128( v = VS.100) .aspx

如果您的设计包含期望实现类型的空接口,则可能使用接口作为标记或标识一组类型的方法.如果此标识将在运行时发生,则实现此目的的正确方法是使用自定义属性.使用属性的存在或不存在或属性的属性来标识目标类型.如果标识必须在编译时进行,则可以使用空接口.

这是引用的MSDN推荐:

删除界面或向其添加成员.如果使用空接口标记一组类型,请使用自定义属性替换该接口.

这也反映了已发布的维基百科链接的批判部分.

标记接口的一个主要问题是接口定义了实现类的契约,并且该契约由所有子类继承.这意味着您无法"实现"标记.在给出的示例中,如果您创建了一个不想序列化的子类(可能因为它依赖于瞬态),则必须使用显式抛出NotSerializableException(每个ObjectOutputStream文档).


Col*_*inE 9

你声明你的功能"根据某些情况返回完全不同的对象" - 但它们有多么不同?可以是流编写器,另一个是UI类,另一个是数据对象吗?不......我对此表示怀疑!

您的对象可能没有任何常用方法或属性,但是,它们的角色或用法可能相似.在这种情况下,标记界面似乎完全合适.


Ode*_*ded 8

如果没有用作标记界面,我会说是的,这是代码味道.

接口定义了实现者遵守的契约 - 如果您有空接口而不使用反射(与标记接口一样),那么您也可以使用Object(已经存在的)基类型.

  • `object`太通用了,并且不会提供返回"kind"的提示.界面帮助我缩小了解释函数返回值的选项范围.但我理解你的评论,因为我没有澄清我正在返回的对象的相似性. (2认同)

Luc*_*ore 6

你回答了自己的问题......"我有一个函数可以根据某些情况返回完全不同的对象."...为什么你想拥有返回完全不同对象的相同函数?我看不出这个有用的原因,也许你有一个好的,在这种情况下,请分享.

编辑:考虑到您的澄清,您应该确实使用标记界面."完全不同"与"同类型"完全不同.如果它们完全不同(不仅仅是它们没有共享成员),那将是代码味道.