例如,我有一个制作水果冰沙的应用程序。我可以列出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();
}
}
答案 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
被限制为仅在通用类,接口或方法的方法中作为返回(出站)值出现