首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#将对象强制转换为IEnumerable<T>,并在可枚举类型为值类型(例如枚举)时使用Linq扩展

C#将对象强制转换为IEnumerable<T>,并在可枚举类型为值类型(例如枚举)时使用Linq扩展
EN

Stack Overflow用户
提问于 2021-02-11 10:40:17
回答 1查看 853关注 0票数 0

如果我知道该类型是可枚举类型,那么如何将其转换为IEnumerable<T>,以便在接收对象值的方法中使用Linq扩展方法(Count()Distinct())?

IEnumerable<object>的简单转换适用于引用类型,但它不适用于枚举之类的值类型,例如:

代码语言:javascript
复制
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),我需要对该属性进行迭代,但由于这个原因,它失败了。

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-11 10:46:56

数组StringComparison[]实现IEnumerableIEnumerable<StringComparison>接口,但不实现IEnumerable<object>

不幸的是,您不能使用泛型协方差将IEnumerable<StringComparison>类型的对象赋值给IEnumerable<object>类型的变量,因为StringComparison不是引用类型:您不能像访问对象一样访问StringComparison[]的任何旧元素,因为它没有普通的对象标头等等。

你能做的是:

代码语言:javascript
复制
IEnumerable<object> items = ((IEnumerable)value).Cast<object>();

这是因为数组实现了IEnumerable,而Enumerable.CastIEnumerable上的扩展方法,而不是IEnumerable<T>

每次从items中获取元素时,都会涉及到Cast<object>()方法,并将StringComparison值类型装箱到对象中。

这意味着多次迭代列表(正如调用大量linq方法所做的那样)可能很昂贵,因为每次都会分配新的对象。您可能希望将装箱对象缓存到列表中,以避免这种开销:

代码语言:javascript
复制
List<object> items = ((IEnumerable)value).Cast<object>().ToList();
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66153111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档