C# 从 IEnumerable<Object> 转换为 IEnumerable<string>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/609608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 10:11:49  来源:igfitidea点击:

Casting from IEnumerable<Object> to IEnumerable<string>

c#covariancecontravariance

提问by Embedd_Khurja

Recently I found a very surprising behavior in c#. I had a method which takes IEnumerable<Object>as a parameter and i was passing IEnumerable<string>but it's not possible. While in c# everything can be upcast to Object than why this is not possible? It's totally confusing for me. Please someone clear me on this issue.

最近我在 c# 中发现了一个非常令人惊讶的行为。我有一个IEnumerable<Object>作为参数的方法,我正在传递, IEnumerable<string>但这是不可能的。而在 c# 中,一切都可以向上转换为 Object,为什么这是不可能的?这对我来说完全令人困惑。请有人在这个问题上澄清我。

采纳答案by Kurt Schelfthout

The technical term for this is that generics are invariant in C# 3.0 and earlier. From C#4.0 onward, the cast works.

技术术语是泛型在 C# 3.0 及更早版本中是不变的。从 C#4.0 开始,演员表有效。

What invariant means is that there is no relationship between two generic types just because their generic type parametersare related (i.e. are sub- or supertypes of each other).

不变的意思是两个泛型之间没有关系,因为它们的泛型参数是相关的(即彼此的子类型或超类型)。

In your example, there is no typing relationship between an IEnumerable<object>and an IEnumerable<string>, just because string is a subtype of object. They're just considered two completely unrelated types, like a string and an int (they still both are subtypes of object, but everything is)

在您的示例中, anIEnumerable<object>和 an之间没有类型关系IEnumerable<string>,只是因为 string 是 object 的子类型。它们只是被认为是两种完全不相关的类型,例如 string 和 int(它们仍然是 object 的子类型,但一切都是)

There are a few workarounds and exceptions for this issue you've run into.

对于您遇到的这个问题,有一些解决方法和例外情况。

First, you can cast each string individually to object, if you're using .NET 3.0 you can do that using the Cast<T>()extension method. Otherwise, you can use a foreach and put the result into a new variable of the static type you want.

首先,您可以将每个字符串单独转换为对象,如果您使用的是 .NET 3.0,则可以使用Cast<T>()扩展方法来实现。否则,您可以使用 foreach 并将结果放入您想要的静态类型的新变量中。

Second, arrays are an exception for reference type, i.e. passing in a string[] type to a method acccepting object[] types should work.

其次,数组是引用类型的一个例外,即将 string[] 类型传递给接受 object[] 类型的方法应该可以工作。

回答by cjk

You should be using

你应该使用

IEnumerable<T> 

if you want to pass in different types, then you can query T to find out what type it is.

如果你想传入不同的类型,那么你可以查询 T 来找出它是什么类型。

回答by 1800 INFORMATION

A good way to think about this is to ask yourself "What would happen if you could do this?". Take the following example:

思考这个问题的一个好方法是问自己“如果你能做到这一点,会发生什么?”。以下面的例子为例:

IEnumerable<String> strings=...;
IEnumerable<Object> objects = strings; // assume this were legal

objects.Add(new Integer(5)); // what the...

We just added an integer to a list of strings. The compiler does this to preserve type safety.

我们只是在字符串列表中添加了一个整数。编译器这样做是为了保持类型安全。

回答by Juozas Kontvainis

The easiest way to pass IEnumerable<string>to function requiring IEnumerable<object>is through converting function like this:

传递IEnumerable<string>给函数 requires的最简单方法IEnumerable<object>是通过如下转换函数:

public IEnumerable<object> convert<T>(IEnumerable<T> enumerable)
    {
    foreach (T o in enumerable)
        yield return o;
    }

When C# 4 comes out, this won't be neccessary, because it will support covariance and contravariance.

当 C# 4 出来时,这将是不必要的,因为它将支持协变和逆变。

回答by chuckj

As others have pointed out, generics types are invariant. IEnumerable<T>could be co-variant but C# doesn't currently support specifying variants. C# 4.0 is expected to support variants so this might be supported in the future.

正如其他人指出的那样,泛型类型是不变的。IEnumerable<T>可以是协变体,但 C# 目前不支持指定变体。C# 4.0 预计会支持变体,因此将来可能会支持。

To work around this now you can using a the LINQ extension method Cast<object>(). Assuming you have a method called Foothat takes an IEnumerable<object>>. You can call it like this,

要解决此问题,您现在可以使用 LINQ 扩展方法Cast<object>()。假设您有一个名为的方法Foo,它需要一个IEnumerable<object>>. 你可以这样称呼

Foo(stringEnumerable.Cast<object>());