举个例子,我有一个应用程序,使水果冰沙。我可以让苹果冰沙的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();
}
}
您需要将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
被限制为仅显示为在通用类,接口或方法的方法返回(出站)的值