这会导致编译时异常:
public sealed class ValidatesAttribute<T> : Attribute
{
}
[Validates<string>]
public static class StringValidation
{
}
我意识到c#不支持泛型属性。然而,在谷歌搜索了很多次之后,我似乎找不到原因。
有人知道为什么泛型类型不能从Attribute派生吗?什么理论吗?
这会导致编译时异常:
public sealed class ValidatesAttribute<T> : Attribute
{
}
[Validates<string>]
public static class StringValidation
{
}
我意识到c#不支持泛型属性。然而,在谷歌搜索了很多次之后,我似乎找不到原因。
有人知道为什么泛型类型不能从Attribute派生吗?什么理论吗?
当前回答
我的变通方法是这样的:
public class DistinctType1IdValidation : ValidationAttribute
{
private readonly DistinctValidator<Type1> validator;
public DistinctIdValidation()
{
validator = new DistinctValidator<Type1>(x=>x.Id);
}
public override bool IsValid(object value)
{
return validator.IsValid(value);
}
}
public class DistinctType2NameValidation : ValidationAttribute
{
private readonly DistinctValidator<Type2> validator;
public DistinctType2NameValidation()
{
validator = new DistinctValidator<Type2>(x=>x.Name);
}
public override bool IsValid(object value)
{
return validator.IsValid(value);
}
}
...
[DataMember, DistinctType1IdValidation ]
public Type1[] Items { get; set; }
[DataMember, DistinctType2NameValidation ]
public Type2[] Items { get; set; }
其他回答
泛型属性从。net 7和c# 11开始支持(在。net 6和c# 10的预览中)。
我不知道为什么不允许,但这是一个可行的解决办法
[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
{
....
}
泛型属性从c# 11开始可用。现在,这是可能的:
[GenericAttribute<int>()]
public int Method();
然而,这还不可能:
[GenericAttribute<T>()]
public int Method<T>(T param);
T在编译时是未知的。
同时,
The type arguments must satisfy the same restrictions as the typeof operator. Types that require metadata annotations aren't allowed. For example, the following types aren't allowed as the type parameter: dynamic string? (or any nullable reference type) (int X, int Y) (or any other tuple types using C# tuple syntax). These types aren't directly represented in metadata. They include annotations that describe the type. In all cases, you can use the underlying type instead: object for dynamic. string instead of string?. ValueTuple<int, int> instead of (int X, int Y).
来源:https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11 generic-attributes
好吧,我不能回答为什么它不可用,但我可以确认这不是CLI的问题。CLI规范没有提到它(据我所知),如果你直接使用IL,你可以创建一个通用属性。c# 3规范中禁止它的部分——10.1.4节“类基规范”并没有给出任何理由。
注释的ECMA c# 2规范也没有提供任何有用的信息,尽管它提供了一个不允许的示例。
我的带注释的c# 3规范应该明天就能到…我看看能不能提供更多信息。无论如何,这绝对是一个语言决定,而不是运行时决定。
编辑:Eric Lippert的回答(转述):没有特别的原因,只是为了避免语言和编译器的复杂性,这并没有增加多少价值。
我的变通方法是这样的:
public class DistinctType1IdValidation : ValidationAttribute
{
private readonly DistinctValidator<Type1> validator;
public DistinctIdValidation()
{
validator = new DistinctValidator<Type1>(x=>x.Id);
}
public override bool IsValid(object value)
{
return validator.IsValid(value);
}
}
public class DistinctType2NameValidation : ValidationAttribute
{
private readonly DistinctValidator<Type2> validator;
public DistinctType2NameValidation()
{
validator = new DistinctValidator<Type2>(x=>x.Name);
}
public override bool IsValid(object value)
{
return validator.IsValid(value);
}
}
...
[DataMember, DistinctType1IdValidation ]
public Type1[] Items { get; set; }
[DataMember, DistinctType2NameValidation ]
public Type2[] Items { get; set; }