我试图建立一个验证属性,将验证集合的大小,我希望该方法能够处理引用类型,如字符串和非引用类型,如int。我试图使用IEnumerable<object>
,但在我通过IEnumerable<int>
的情况下保持为空。
这是我当前的代码-
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
public class EnumerableSizeAttribute : ValidationAttribute<IEnumerable<object>>
{
protected override ValidationResult? IsValid(IEnumerable<object>? enumerable, ValidationContext validationContext)
{
//check collection size
}
}
我应该使用什么作为参数来允许我将任何集合类型传递到方法中?谢谢你的帮助!
值和引用类型之间的一般方差规则是…复杂。
如果需要避免装箱,则考虑使方法本身具有泛型并采用IEnumerable<T>
,以便调用者指定它(通常是隐式的,因此无需更改代码)。
如果这不是一个选项:考虑使用非通用的IEnumerable
api。或者IList
或ICollection
,因为你在计数之后,你可以通过.Count
便宜地访问它们,而无需支付与IEnumerable
相关的任何装箱/迭代开销。
. NET 7及以后的版本可以使用泛型属性:
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
public class EnumerableSizeAttribute<T> : ValidationAttribute<IEnumerable<T>>
{
protected override ValidationResult? IsValid(IEnumerable<T>? enumerable, ValidationContext validationContext)
{
//check collection size
}
}
在IsValid
内部,您可以检查enumerable
是否为ICollection<T>
,从而使用便宜的Count
属性来检查大小:
if(enumerable is ICollection<T> col && col.Count <...)
{
}
您也可以使用属性模式匹配,尽管我对语法仍然不太熟悉。就像
if(enumerable is ICollection<T> {Count: < MaxLength} col)
{
}