C#-为什么不能使IEnumerable具有通用接口类型?

时间:2019-02-04 23:38:19

标签: c# generics interface ienumerable

例如,我有一个制作水果冰沙的应用程序。我可以列出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();
    }
}

1 个答案:

答案 0 :(得分: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被限制为仅在通用类,接口或方法的方法中作为返回(出站)值出现