如果我知道该类型是可枚举类型,那么如何将其转换为IEnumerable<T>,以便在接收对象值的方法中使用Linq扩展方法(Count(),Distinct())?
对IEnumerable<object>的简单转换适用于引用类型,但它不适用于枚举之类的值类型,例如:
StringComparison[] myArray = new StringComparison[] {
StringComparison.OrdinalIgnoreCase,
StringComparison.Ordinal
};
void DoSomething(object value) {
IEnumerable<object> items = (IEnumerable<object>) value;
// use the enumerable with System.Linq.Enumerable extensions
// items.Count()
// items.Distinct()
}
DoSomething(myArray);使用一个枚举,演员们抛出System.InvalidCastException: 'Unable to cast object of type 'System.StringComparison[]' to type 'System.Collections.Generic.IEnumerable^1[System.Object]'.'
其他的答案(例如C# object to array)建议通过转换到非一般的IEnumerable来实现这一点。不幸的是,我想要的扩展方法(Count()和Distinct())不能用于非通用IEnumerable。
背景:简化了上述示例。我的实际用例是,我编写了一个自定义System.ComponentModel.DataAnnotations.ValidationAttribute,它对可枚举属性属性执行检查。ValidationAttribute有一个传递枚举值数组的方法IsValid(object value),我需要对该属性进行迭代,但由于这个原因,它失败了。
谢谢!
发布于 2021-02-11 10:46:56
数组StringComparison[]实现IEnumerable和IEnumerable<StringComparison>接口,但不实现IEnumerable<object>。
不幸的是,您不能使用泛型协方差将IEnumerable<StringComparison>类型的对象赋值给IEnumerable<object>类型的变量,因为StringComparison不是引用类型:您不能像访问对象一样访问StringComparison[]的任何旧元素,因为它没有普通的对象标头等等。
你能做的是:
IEnumerable<object> items = ((IEnumerable)value).Cast<object>();这是因为数组实现了IEnumerable,而Enumerable.Cast是IEnumerable上的扩展方法,而不是IEnumerable<T>。
每次从items中获取元素时,都会涉及到Cast<object>()方法,并将StringComparison值类型装箱到对象中。
这意味着多次迭代列表(正如调用大量linq方法所做的那样)可能很昂贵,因为每次都会分配新的对象。您可能希望将装箱对象缓存到列表中,以避免这种开销:
List<object> items = ((IEnumerable)value).Cast<object>().ToList();https://stackoverflow.com/questions/66153111
复制相似问题