这会导致编译时异常:
public sealed class ValidatesAttribute: Attribute { } [Validates ] public static class StringValidation { }
我意识到C#不支持通用属性.然而,经过大量的谷歌搜索,我似乎无法找到原因.
有谁知道为什么泛型类型无法衍生出来Attribute
?任何理论?
好吧,我无法回答为什么它不可用,但我可以确认它不是CLI问题.CLI规范没有提到它(据我所见),如果你直接使用IL,你可以创建一个通用属性.禁止它的C#3规范的一部分 - 第10.1.4节"类基本规范"没有给出任何理由.
带注释的ECMA C#2规范也没有给出任何有用的信息,尽管它确实提供了一个不允许的例子.
我的带注释的C#3规范的副本应该明天到达......我会看看是否会提供更多信息.无论如何,它绝对是一种语言决策,而不是运行时决定.
编辑:Eric Lippert的回答(释义):没有特别的原因,除了避免语言和编译器的复杂性,用于不增加太多价值的用例.
属性在编译时修饰一个类,但泛型类在运行时之前不会收到它的最终类型信息.由于该属性可能会影响编译,因此必须在编译时"完成".
有关更多信息,请参阅此MSDN文章.
我不知道为什么不允许,但这是一种可行的解决方法
[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 { .... }
这不是真正的通用,你仍然需要为每种类型编写特定的属性类,但是你可以使用通用的基本接口来编写一些防御性的代码,编写比其他要求更少的代码,获得多态性等的好处.
//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 { }
这个问题问得好.在我与属性的经验,我认为约束是在地方,因为一个属性反映时,将创建您必须检查所有可能的排列型的条件:typeof(Validates
,typeof(Validates
,等...
在我看来,如果根据类型需要自定义验证,属性可能不是最好的方法.
接受a SomeCustomValidationDelegate
或ISomeCustomValidator
作为参数的验证类可能是更好的方法.