为什么采用 IEnumerable的函数不接受 IEnumerable

发布于 2024-08-26 07:37:10 字数 644 浏览 5 评论 0原文

比如说,我有一个类:

public class MyFoo : IMyBar
{
    ...
}

然后,我想使用以下代码:

List<MyFoo> classList = new List<MyFoo>();
classList.Add(new MyFoo(1));
classList.Add(new MyFoo(2));
classList.Add(new MyFoo(3));

List<IMyBar> interfaceList = new List<IMyBar>(classList);

但这会产生错误:

`Argument '1': cannot convert from 'IEnumerable<MyFoo>' to 'IEnumerable<IMyBar>' 

这是为什么?由于 MyFoo 实现了 IMyBar,因此人们会期望 MyFoo 的 IEnumerable 可以被视为 IMyBar 的 IEnumerable。一个现实世界中的常见示例是生成一个汽车列表,然后被告知这不是一个车辆列表。

这只是一个小烦恼,但如果有人能阐明这一点,我将非常感激。

Say, for instance, I have a class:

public class MyFoo : IMyBar
{
    ...
}

Then, I would want to use the following code:

List<MyFoo> classList = new List<MyFoo>();
classList.Add(new MyFoo(1));
classList.Add(new MyFoo(2));
classList.Add(new MyFoo(3));

List<IMyBar> interfaceList = new List<IMyBar>(classList);

But this produces the error:

`Argument '1': cannot convert from 'IEnumerable<MyFoo>' to 'IEnumerable<IMyBar>' 

Why is this? Since MyFoo implements IMyBar, one would expect that an IEnumerable of MyFoo could be treated as an IEnumerable of IMyBar. A mundane real-world example being producing a list of cars, and then being told that it wasn't a list of vehicles.

It's only a minor annoyance, but if anyone can shed some light on this, I would be much obliged.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

离鸿 2024-09-02 07:37:10

这将在 C# 4.0 中运行!您所说的称为通用协方差

同时,您可以使用 Cast 扩展方法:

List<IMyBar> interfaceList = new List<IMyBar>(classList.Cast<IMyBar>());

This is going to work in C# 4.0! What you are talking about is called generic covariance.

In the meantime you can use the Cast extension method:

List<IMyBar> interfaceList = new List<IMyBar>(classList.Cast<IMyBar>());
碍人泪离人颜 2024-09-02 07:37:10

.NET 4.0 中支持此功能,但更早版本不支持。

http://msdn.microsoft.com/en-我们/库/dd799517%28VS.100%29.aspx

This is supported in .NET 4.0 but not earlier.

http://msdn.microsoft.com/en-us/library/dd799517%28VS.100%29.aspx

情徒 2024-09-02 07:37:10

澄清一下,它现在不起作用的原因是 IEnumerable 不是从 IEnumerable 继承的。我再说一遍:派生类型的可枚举不是从基类型的可枚举继承的。相反,这两种类型都专门化了 IEnumerable 泛型类型。在 .Net 3.5 及更低版本中,除了专业化(不是继承)之外,它们没有其他关系,并且在类型系统中是两种完全不同的类型。

.Net 4.0 根本不会改变这些类型的关联方式。它们仍然是两种完全不同的类型,仅通过专业化相关。它将做的是允许您编写了解专业化关系的方法,并且在某些情况下允许您在编写另一个方法时替换一个方法。

To clarify, the reason it doesn't work now is because IEnumerable<MyClass> does not inherit from IEnumerable<MyBar>. I'll say that again: the enumerable of the derived type does not inherit from the enumerable of the base type. Rather, both types specialize the IEnumerable<T> generic type. In .Net 3.5 and lower, they have no other relationship beyond specialization (which is not inheritance) and are otherwise two completely different types in the type system.

.Net 4.0 will not change the way these types relate at all. They will still be two completely different types that relate only through specialization. What it will do is allow you to write methods that know about the specialization relationship and in some cases allow you substitute one when you wrote the other.

脱离于你 2024-09-02 07:37:10

如果您想在 IEnumerables 之间进行转换(如您在问题标题中所写)而不是在列表之间进行转换(如您在问题中所写),您可以等待 c# 4.0 协方差功能。
在那一天之前,您可以使用扩展方法。
但我不会使用其他答案中提到的 Cast 扩展方法,但编写我自己的方法,只能用于 IEnumerable 中的协方差转换。当/如果您切换到 C# 4.0,您将很容易找到代码中强制转换多余的所有位置。

public static class cEnumerableExtensions
{
    public static IEnumerable<TResult> CovarianceConversion<TResult, TSource>(this IEnumerable<TSource> source)
        where TSource : TResult
    {
        foreach (var item in source)
        {
            yield return item;
        }
    }
}

最终节点。似乎 netframework 4.0 没有预编译器常量< /a>,否则我会添加

    #if DOTNET4
    [Obsolete("You can directly cast in C# 4.0.")]
    #endif

If you want to cast between IEnumerables (as you wrote in the headline of your question) and not between Lists (as you wrote in your question) you can wait for the c# 4.0 covariance feature.
Before that day you can use extension methods.
But I would not use the Cast extension method noted in other answers, but writing my own method, that can be only used for covariance casting in IEnumerable. When/If you switch to C# 4.0 you will easily find all places in your code where the cast will be redundant.

public static class cEnumerableExtensions
{
    public static IEnumerable<TResult> CovarianceConversion<TResult, TSource>(this IEnumerable<TSource> source)
        where TSource : TResult
    {
        foreach (var item in source)
        {
            yield return item;
        }
    }
}

Final Node. There seems to be no precompiler constant for the netframework 4.0, otherwise I would add

    #if DOTNET4
    [Obsolete("You can directly cast in C# 4.0.")]
    #endif
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文