空接口与属性,通用约束怎么样?

Jer*_*984 13 c# oop generics interface

我有一个类,它使用一个空接口作为"标记接口",如下所示:

namespace MyNameSpace
{
    public interface IMessage
    {
        //nothing in common here...
    }
    public class MyMessage : IMessage
    { 
        public void SendMyMessage()
        {
           //Do something here
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在其他一些帖子中读到了,但在MSDN(http://msdn.microsoft.com/en-us/library/ms182128.aspx)上也应该避免这种情况,你应该使用自定义属性而不是这个空接口.所以,我可以像这样重构我的代码:

namespace MyNameSpace
{
    public class MessageAttribute : Attribute
    {
         //nothing in common here...
    }
    [MessageAttribute]
    public class MyMessage
    { 
        public void SendMyMessage()
        {
           //Do something here
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一切正常,但主要问题是:

当我在程序的其他地方有一个通用方法时,例如:

public IEnumerable<T> GetAll<T>() where T : IMessage
{
    //Return all IMessage things here
}
Run Code Online (Sandbox Code Playgroud)

在上面的函数中,我确实需要添加一些泛型类型约束T,因此只IMessages允许.如何在使用自定义属性而不是空接口时完成此操作?

这是否证明使用空接口是正确的?或者我应该使用一个空的抽象类Message(而不是接口IMessage,因为MyMessage实际上是一个Message).

对你对此的看法非常好奇.

Mar*_*ell 8

使用自定义属性而不是空接口时,我怎么能做到这一点??? 这是否证明使用空接口是正确的?

你不能 - 至少,不能在编译时.您当然可以在运行时检查属性.

或者我应该使用一个空的抽象类Message

基类比接口更具限制性; 我个人会施加最少的开销.但我想知道即使是人工界面(它什么都不给你)本身就是开销,另一种选择就是:不要提出任何这样的要求.让人们添加一个接口只是为了一个方法编译并不会给你带来太多的东西,而不仅仅是一个没有约束的泛型方法.

  • 拥有或没有该界面的@ Jeroen1984并不是让它"有意义"的东西; 具有该界面的东西同样没有意义,没有它的东西可能是完全合理的.我不知道规则*是什么*是什么"有意义",但它与此界面没有任何关系. (4认同)
  • @SriramSakthivel:获取编译器错误总是优先于运行时错误,不是吗?否则,您可以只输入"System.Object"的所有内容,并在发现对象的类型错误时抛出"InvalidOperationException"或"NotSupportedException". (3认同)
  • @ORMapper这里的编译器错误代表_nothing_.使用空接口使错误消失,它仍然可以全部弹出. (2认同)
  • @Gusdor:正如我所说 - 然后我们也可以将每个参数输入到System.Object`并完全没有任何编译时类型检查.在运行时仍然可能发生某些异常的事实并不是试图在编译时尽可能多地捕获错误. (2认同)
  • @ORMapper你之所以选择传递一个字符串而不是一个`Object`的原因是因为该方法的逻辑依赖于字符串特定的逻辑(例如,字符串连接,StartsWith等).在这种情况下,他的方法确实_not_依赖于任何IMessage-specfic逻辑 - 因为有_none_. (2认同)
  • @Gusdor:意图并不总是通过标识符来表达吗?语言确实可以提供一些有限的支持来检查开发人员的意图是否得到遵守,从而避免错误。例如,具有相同成员的两个接口仍然不兼容分配,因为它们是两种不同的类型。它们在纯粹基于语言的层面上可能看起来相同,但它们是出于不同的意图而编写的,它们是出于不同的意图而被使用的,并且它们将被列为具有不同意图的类的实现接口。 (2认同)

O. *_*per 5

由于C# 当前不提供任何基于属性的通用约束,因此除了使用标记接口之外,您别无选择。

有趣的是,CA1040 上文档页面声明了以下规则的例外情况:

当接口用于在编译时识别一组类型时,可以安全地禁止来自此规则的警告。

确定“编译时的一组类型”似乎正是评估泛型约束时所需要的,我现在想知道该文档页面的作者是否考虑到了这一点。