美好的一天,所有。
我可以问你逻辑为什么这是不可能的? 我在学习界面&现在通用,我认为这是可能的,因为集团实现了iPoppable& amp; iPushable。但编译器抱怨说,将iPoppable转换为Group是不可能的。我想知道为什么这是不可能的逻辑。
interface iPoppable<out T>{T Pop();}
interface iPushable<in T>{void Push(T ag_t);}
class Program
{
static void Main()
{
iPoppable<Lion> lions = new Group<Lion>();
iPoppable<Animal> animals = lions; //Possible
Group<Lion> lions2 = lions; //Not possible
}
}
class Animal{}
class Lion:Animal{}
class Group<T>:iPoppable<T>, iPushable<T>
{
public void Push(T ag_t){}
public T Pop(){return something;}
}
答案 0 :(得分:3)
好的,一步一步。
iPoppable<Lion> lions = new Group<Lion>();
Works,因为Group
实现了iPoppable
,而通用参数T
是相同的。
iPoppable<Animal> animals = lions;
可以使用,因为iPoppable
和Lion
都来自Animal
。更正式地说,这是协方差的一个例子。
使用更多派生类型参数实例化的对象将分配给使用较少派生类型参数实例化的对象。保留分配兼容性。
Group<Lion> lions2 = lions;
不起作用,因为您将接口类型分配给类类型。 iPoppable
只是说lions
有Lion Pop();
方法,不再有!通过说Group<Lion> lions2 = lions;
,您声称lions2
是一个功能齐全的Group
对象,它具有Group
类的所有方法和属性。哪个不一定为真,这就是编译器抱怨的原因。
您可以通过说
来帮助编译Group<Lion> lions2 = (Group<Lion>)lions;
因为你知道一个事实,特别是lions
,虽然类型iPoppable
实际上是Group
。
为了说明编译器害怕的内容,请参阅以下代码段。
interface iPoppable<out T>
{
T Pop();
}
interface iPushable<in T>
{
void Push(T ag_t);
}
class Program
{
static void Main()
{
// Here, we know the truth, so we cast
iPoppable<bool> group = new Group<bool>();
Group<bool> group2 = (Group<bool>)group; // Possible
// What about here? We also convert iPoppable to Group...
iPoppable<bool> notGroup = new NotGroup<bool>();
Group<bool> notGroup2 = (Group<bool>)notGroup; // Bad... Compiler was right...
notGroup2.HelloGroup = true; // HA! Runtime exception.
// That's what compiler was worrying about.
// System.InvalidCastException: Unable to cast object of
// type 'NotGroup`1[System.Boolean]' to type 'Group`1[System.Boolean]
}
}
class Group<T> : iPoppable<T>, iPushable<T>
{
public void Push(T ag_t) { }
public T Pop() { return default(T); }
public bool HelloGroup { get; set; }
}
class NotGroup<T> : iPoppable<T>, iPushable<T>
{
public void Push(T ag_t) { }
public T Pop() { return default(T); }
public bool HelloNotGroup { get; set; }
}