简体   繁体   English

我该如何投射IEnumerable <?> 到IEnumerable <string> ?

[英]How can I cast IEnumerable<?> to IEnumerable<string>?

This question was completely edited. 这个问题已完全编辑。 To see the original one, see the edit history 要查看原始版本,请参阅编辑历史记录


I think I should explain a little bit of my situation and context of the problem. 我想我应该解释一下我的情况和问题的背景。

I'm inspecting a type for a property annotated with a custom attribute. 我正在检查使用自定义属性注释的属性的类型。 I then get the value of that property, but as an object : 然后我获取该属性的值,但作为一个object

IEnumerable<object> propertiesValues = myType.GetProperties().Where(p => p.GetCustomAttributes(typeof(MyCustomAttribute)) != null);

Once I have these values I want to call my method Map on them, which converts them to a different object depending on their type. 一旦我有这些值,我想在它们上面调用我的方法Map ,它根据它们的类型将它们转换为不同的对象。 This is because my database API requires so. 这是因为我的数据库API需要这样做。

foreach(object value in propertiesValues)
{
     object mapped = Map(value);
     // ...
}

I need all IEnumerable<NumberType> values, to be converted to IEnumerable<string> . 我需要所有IEnumerable<NumberType>值,才能转换为IEnumerable<string> So my first approach was: 所以我的第一个方法是:

public static object Map(object value)
{
    if(value is IEnumerable<short> || value is IEnumerable<int> || ....)
         return ((IEnumerable<object>) value).Cast<string>();
}

However, this is throwing a runtime exception, as I cannot cast IEnumerable<int> to IEnumerable<object> for example. 但是,这会引发运行时异常,因为我无法将IEnumerable<int> IEnumerable<object>IEnumerable<object>

The feature you want is called covariance , and C# supports it on IEnumerable<T> only when the type arguments are both reference types. 您想要的功能称为协方差 ,只有当类型参数都是引用类型时,C#才会在IEnumerable<T>上支持它。 That is, IEnumerable<string> may be converted to IEnumerable<object> , but IEnumerable<int> may not be so converted. 也就是说, IEnumerable<string>可以转换为IEnumerable<object> ,但IEnumerable<int>可能不会被转换。

The reason is: when you get a sequence of strings, those string references are already legal object references. 原因是:当您获得一系列字符串时,这些字符串引用已经是合法的对象引用。 But an int only becomes a legal object reference when it is boxed; 但是当一个int被装箱时,它只会成为一个合法的对象引用; where does the compiler know to insert the boxing operation? 编译器在哪里可以插入装箱操作? It doesn't, so the conversion is illegal. 它没有,所以转换是非法的。

To convert an IEnumerable<int> to IEnumerable<object> you have to do the boxing explicitly via a projection: 要将IEnumerable<int>转换为IEnumerable<object>您必须通过投影明确地进行装箱:

from number in items select (object)item

or 要么

items.Select(item => (object) item)

That will be IEnumerable<object> , and you can then do what you like to that. 那将是IEnumerable<object> ,然后你就可以做你喜欢的了。

Or use the Cast sequence operator 或者使用Cast序列运算符

items.Cast<object>()

which does the same thing. 它做同样的事情。 Or use its query form: 或使用其查询表单:

from object item in items select item

Or simply use the non-generic IEnumerable , which gives you a sequence of boxed values if in fact it is a sequence of structs. 或者简单地使用非泛型IEnumerable ,它为您提供一系列盒装值,如果它实际上是一系列结构。

I note though that your plan of then casting IEnumerable<object> to IEnumerable<string> via the Cast extension method is doomed to failure. 我注意到你通过Cast扩展方法将IEnumerable<object>IEnumerable<string>的计划注定要失败。 Those items will be boxed ints. 这些物品将是盒装的。 Boxed ints cannot be unboxed to string. 盒装的int不能拆箱到字符串。

It seems like you are fighting the type system here instead of working with it. 看起来你在这里打击类型系统而不是使用它。 Perhaps you should describe your real problem, rather than your attempts to do an end-run around the type system to solve it. 也许您应该描述您的真实问题,而不是您尝试围绕类型系统进行最终运行来解决它。

Why don't you do this 你为什么不这样做?

var source = ... /// IEnumerable<???>
var destination = source.Select(item => item.ToString());

You could update Map 's signature as well: 你也可以更新Map的签名:

object Map<TItem, TSource>(TSource source) 
  : where TSource : IEnumerable<TItem>

or 要么

object Map<TItem>(IEnumerable<TItem> source) 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我们如何键入强制转换 IEnumerable <keyvaluepair<string, ienumerable<classa> &gt;&gt; objOld 变成 IEnumerable <keyvaluepair<string, ienumerable<classb> &gt;&gt; 新对象? </keyvaluepair<string,></keyvaluepair<string,> - How can we type cast IEnumerable<KeyValuePair<string, IEnumerable<ClassA>>> objOld into IEnumerable<KeyValuePair<string, IEnumerable<ClassB>>> objNew? 如何减少IEnumerable <IEnumerable<Foo> &gt;到IEnumerable <Foo> ? - How can I reduce IEnumerable<IEnumerable<Foo>> to IEnumerable<Foo>? 如何从 Ienumerable 返回一个字符串? - How can I return a string from an Ienumerable? 如何在C#中将IEnumerable转换为IList - How can I cast an IEnumerable to an IList in C# 我该如何转换为IEnumerable <Guid> 在simple.data中? - How can I cast to IEnumerable<Guid> in simple.data? 如何转换 IEnumerable 的属性<directoryinfo>列出<string></string></directoryinfo> - How to cast property of IEnumerable<DirectoryInfo> to List<string> 我可以合并两个IEnumerable <string> 到IEnumerable <string,string> - Can I merge two IEnumerable<string> to IEnumerable<string,string> 如何转换IEnumerable <IEnumerable<IGrouping<int,string> &gt;&gt;到IEnumerable <IEnumerable<string> &gt; - How to convert IEnumerable<IEnumerable<IGrouping<int,string>>> to IEnumerable<IEnumerable<string>> 如何转换`IEnumerable <Unknown T> 到IEnumerable <Whatever> ` - How to cast an `IEnumerable<Unknown T>` to `IEnumerable<Whatever>` 如何投射IEnumerable <object> 到一个IEnumerable <runtime type> - How to cast an IEnumerable<object> to an IEnumerable<runtime type>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM