当前位置:  开发笔记 > 编程语言 > 正文

为什么C#禁止通用属性类型?

如何解决《为什么C#禁止通用属性类型?》经验,为你挑选了5个好方法。

这会导致编译时异常:

public sealed class ValidatesAttribute : Attribute
{

}

[Validates]
public static class StringValidation
{

}

我意识到C#不支持通用属性.然而,经过大量的谷歌搜索,我似乎无法找到原因.

有谁知道为什么泛型类型无法衍生出来Attribute?任何理论?



1> Jon Skeet..:

好吧,我无法回答为什么它不可用,但我可以确认它不是CLI问题.CLI规范没有提到它(据我所见),如果你直接使用IL,你可以创建一个通用属性.禁止它的C#3规范的一部分 - 第10.1.4节"类基本规范"没有给出任何理由.

带注释的ECMA C#2规范也没有给出任何有用的信息,尽管它确实提供了一个不允许的例子.

我的带注释的C#3规范的副本应该明天到达......我会看看是否会提供更多信息.无论如何,它绝对是一种语言决策,而不是运行时决定.

编辑:Eric Lippert的回答(释义):没有特别的原因,除了避免语言和编译器的复杂性,用于不增加太多价值的用例.


"没有增加太多价值的用例"?这是一个主观意见,它可以为我提供很多价值!
"除了避免语言和编译器的复杂性"......以及来自给予我们合作和逆转的人们......
最让我困扰的是没有这个功能的东西,不能做[PropertyReference(x => x.SomeProperty)]之类的东西.相反,你需要魔术字符串和typeof(),我认为这很糟糕.
我只想添加@Timwi的辩护,这不是唯一的地方[他们正在讨论](https://www.google.co.uk/search?q="generic + attributes"+ c%23 ),对这个问题的13K意见意味着健康的兴趣水平.另外:感谢获得权威答案,Jon.
@John:我认为你大大低估了设计,指定,实施和测试新语言功能的成本.
@asbjornu:是的,虽然有一个`infoof`运算符比使用lambda表达式更好...
我很高兴听到通用属性是合法的IL.如果你能问团队,我将非常感激!我有机会在PDC问安德斯并完全忘了:-)
它对我也很有价值,因为我发现没有办法绕过这个限制.
在你想要像我现在这样的功能之前,避免语言和编译器中不必要的复杂性是可以理解的.:)在这一点上,我认为语言已经有了泛型和属性,所以为什么不把它们放在一起 - 也许夏天的实习生需要微软做点什么.
我问过......我们会看看他们是否回复.
只是想问一些关于属性的问题.太悲伤的通用属性不可用.更糟糕的是,没有特别的理由.:/
@乔恩,的确,这有点嘲讽。我忽略了最后包含标准表情符号。
@Jon:在某些情况下,语言禁止构造(例如使用`System.Enum`作为通用约束),在没有规则禁止它的情况下 - 默认情况下只需"工作".虽然设计师可以自由地做任何他们想做的事情,但只有在产生效益的情况下投入努力的理念才会表明设计师不应该花费精力去禁止这样的结构,除非这样做会带来一些好处.简单地让通用属性类型的行为会产生什么影响,但是如果C#没有打扰禁止它们,它们会"自然"出现?
@ygormutti:C#6将具有`nameof` ...不像`infoof`那么强大,但是要简单得多.

2> GalacticCowb..:

属性在编译时修饰一个类,但泛型类在运行时之前不会收到它的最终类型信息.由于该属性可能会影响编译,因此必须在编译时"完成".

有关更多信息,请参阅此MSDN文章.


这似乎与另一个答案相矛盾,该答案表明IL将允许它.(/sf/ask/17360801/)
文章重申,它们是不可能的,但没有理由.我从概念上理解你的答案.你知道关于这个问题的更多官方文件吗?
本文确实涵盖了IL仍然包含在运行时用实际类型替换的通用占位符这一事实.其余的由我推断...... :)

3> GeekyMonkey..:

我不知道为什么不允许,但这是一种可行的解决方法

[AttributeUsage(AttributeTargets.Class)]
public class ClassDescriptionAttribute : Attribute
{
    public ClassDescriptionAttribute(Type KeyDataType)
    {
        _KeyDataType = KeyDataType;
    }

    public Type KeyDataType
    {
        get { return _KeyDataType; }
    }
    private Type _KeyDataType;
}


[ClassDescriptionAttribute(typeof(string))]
class Program
{
    ....
}


可悲的是,我不想这样做,这就是我发现这个问题的原因.我想我只需坚持处理typeof.现在仿制药存在了这么久之后,它真的感觉像是一个肮脏的关键词.
不幸的是,在使用属性时会丢失编译时输入.想象一下,该属性创建了泛型类型的东西.你可以解决它,但它会很好; 这是你不能做的那些直观的事情之一,比如方差(目前).

4> nawfal..:

这不是真正的通用,你仍然需要为每种类型编写特定的属性类,但是你可以使用通用的基本接口来编写一些防御性的代码,编写比其他要求更少的代码,获得多态性等的好处.

//an interface which means it can't have its own implementation. 
//You might need to use extension methods on this interface for that.
public interface ValidatesAttribute
{
    T Value { get; } //or whatever that is
    bool IsValid { get; } //etc
}

public class ValidatesStringAttribute : Attribute, ValidatesAttribute
{
    //...
}
public class ValidatesIntAttribute : Attribute, ValidatesAttribute
{
    //...
}

[ValidatesString]
public static class StringValidation
{

}
[ValidatesInt]
public static class IntValidation
{

}



5> ichiban..:

这个问题问得好.在我与属性的经验,我认为约束是在地方,因为一个属性反映时,将创建您必须检查所有可能的排列型的条件:typeof(Validates),typeof(Validates),等...

在我看来,如果根据类型需要自定义验证,属性可能不是最好的方法.

接受a SomeCustomValidationDelegateISomeCustomValidator作为参数的验证类可能是更好的方法.


你可以检查泛型类型定义(即typeof(Validates <>))...
推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有