C# - 为什么我不能创建通用接口(interface)类型的 IEnumerable?

标签 c# generics interface ienumerable

例如,我有一个制作水果冰沙的应用程序。我可以做一个IEnumerable苹果冰沙列表,并且有效。

我希望能够制作一份通用的冰沙列表 IEnumerable<ISmoothie<IFruit>>万一我决定在生产线上添加另一种水果,比如橙子。当我尝试这样做时,代码将无法编译并且出现错误:

Cannot implicitly convert type 'System.Collections.Generic.List>' to 'System.Collections.Generic.IEnumerable>'. An explicit conversion exists (are you missing a cast?)

public class Program
{
    public static void Main()
    {
        IEnumerable<ISmoothie<Apple>> appleSmoothies = new List<ISmoothie<Apple>>();   // I Can specifically make Apple Smoothies!
        IEnumerable<ISmoothie<IFruit>> genericSmoothies = new List<Smoothie<Apple>>(); // Does Not Compile - What if I want generic Smoothies? 
        Console.WriteLine("Hello World");
    }

    public class Apple : IApple
    {
        // Concrete Implimentation of an Apple
    }

    public interface IApple : IFruit
    {
        // Specific Interface for Apples
    }

    public interface IFruit
    {
        // Basic Fruit Interface for all Fruits
    }

    public class Smoothie<T> : ISmoothie<T> where T : IFruit
    {
        // Generic Fruit Smoothie
        public List<T> Ingredients {get; set;}
        public int Size {get; set;}
        public void Drink()
        {
            // Drink Logic
        }
    }

    public interface ISmoothie<T> where T : IFruit
    {
        List<T> Ingredients {get; set;}
        int Size {get; set;}
        void Drink();
    }
}

最佳答案

您需要将out 参数添加到您的界面以指定Covariance

public interface ISmoothie<out T> where T : IFruit
{
}

out (generic modifier) (C# Reference)

For generic type parameters, the out keyword specifies that the type parameter is covariant. You can use the out keyword in generic interfaces and delegates.

Covariance enables you to use a more derived type than that specified by the generic parameter. This allows for implicit conversion of classes that implement covariant interfaces and implicit conversion of delegate types. Covariance and contravariance are supported for reference types, but they are not supported for value types.

更新

使用out参数时有限制,

public class Smoothie<T> : ISmoothie<T> where T : IFruit
{
   // Generic Fruit Smoothie
   public T Type { get; set; } // we can do this
}

public interface ISmoothie<out T> where T : IFruit
{
   T Type { get; set; } // compiler error CS1961 Invalid variance: 
}

out T 表示类型 T 被限制为仅作为返回(出站)值出现在泛型类、接口(interface)或方法的方法中

关于C# - 为什么我不能创建通用接口(interface)类型的 IEnumerable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54525907/

相关文章:

java - 使用Java接口(interface)

Java 通用接口(interface)返回类型

c# - 如何向 NET Core 2.0 的 SignalR alpha 上的所有客户端发送消息

java - Java 8 中的通用函数名称

c# - 使用 Rhino Mock 报告被调用的函数

c# - .NET 管理层关系

generics - 如何获得 PsiField 的通用类型

java - 如何在 C# 中使用匿名类重新实现 Java 监听器

c# - 如何接受 HTTP 400 和 HTTP 500 作为 Visual Studio 负载测试中的有效响应代码?

c# - ASP.NET 3.5 Url 路由不工作