C# - 为什么我不能做一个通用的接口类型的IEnumerable?

问题描述 投票:1回答:1

举个例子,我有一个应用程序,使水果冰沙。我可以让苹果冰沙的IEnumerable列表和工作。

我希望能够使IEnumerable<ISmoothie<IFruit>>的情况下,我决定要添加其他水果的路线好比说一个橙冰沙的泛型列表。当我尝试这样做,该代码将无法编译,我得到的错误:

无法隐式转换类型“System.Collections.Generic.List>”到“System.Collections.Generic.IEnumerable>”。一个显式转换存在(是否缺少强制转换?)

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();
    }
}
c# generics interface ienumerable
1个回答
5
投票

您需要将out参数添加到您的界面指定协方差

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

out (generic modifier) (C# Reference)

对于一般类型参数,out关键字指定该类型参数是协变。您可以在通用接口和委托使用out关键字。

协方差可让您使用更派生类型比泛型参数指定。这允许实现协接口和委托类型的隐式转换类隐式转换。协变和逆变支持对于引用类型,但不支持值类型。

更新

使用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被限制为仅显示为在通用类,接口或方法的方法返回(出站)的值

© www.soinside.com 2019 - 2024. All rights reserved.