[英]C# casting derived generic type to parent
Before I ask my question this is my structure: 在我问我的问题之前,这是我的结构:
public class Data : ScriptableObject {...}
public class ItemData : Data {...}
public class WeaponData : ItemData {...}
public abstract class Item<T> : Visual<T> where T : ItemData {...}
public class Weapon<T> : Item<T> where T : WeaponData {...}
I get an error (Cannot cast from source type to destination type) when I create a Weapon
object and assign it to Item<ItemData>
. 当我创建一个
Weapon
对象并将其分配给Item<ItemData>
时,我收到一个错误(无法从源类型转换为目标类型)。
Weapon<Foo> weapon = new Weapon<Foo>();
Item<ItemData> other = weapon;
Why is that? 这是为什么?
In C#, covariance (assigning a derived type to a base type) cannot be applied to generic classes. 在C#中,协方差(将派生类型分配给基类型)不能应用于泛型类。 As a result, you would need to apply an interface specifically marked as covariant, using the out parameter modifier on a new
IItem
interface. 因此,您需要在新的
IItem
接口上使用out参数修饰符来应用专门标记为协变的接口。
However, that by itself isn't enough. 但是,这本身是不够的。 You do not have a way to tell
Item
that it will allow an instance of Weapon
to be assigned to it when Weapon
has a generic type parameter that could be anything provided it inherits from ItemData
. 你没有办法告诉
Item
,它将使实例Weapon
将被分配给它当Weapon
有可能是任何东西 ,只要它从继承的泛型类型参数ItemData
。 This places the compiler in a difficult predicament since it can't assure you that the relationship is valid. 这使编译器陷入困境,因为它无法向您保证关系是有效的。 However, if you apply a new
IItemData
interface to ItemData
, the cast will be permissible. 但是,如果将新的
IItemData
接口应用于ItemData
,则允许使用IItemData
转换。
void Main()
{
Weapon<Foo> weapon = new Weapon<Foo>();
IItem<ItemData> other = weapon;
}
public interface IItem<out T> {}
public interface IItemData {}
public class Foo : WeaponData {}
public class Data : ScriptableObject {}
public class ItemData : Data, IItemData {}
public class WeaponData : ItemData {}
public abstract class Item<T> : Visual<T>, IItem<T> where T : IItemData {}
public class Weapon<T> : Item<T> where T : WeaponData {}
public class ScriptableObject {}
public class Visual<T> {}
This requires Item<T>
be updated to be constrained to IItemData
instead of constrained to a concrete type. 这需要将
Item<T>
更新为约束到IItemData
而不是约束到具体类型。
Generics get all weird when you deal with this kind of stuff. 当你处理这类东西时,泛型会变得奇怪。 I've not investigated this in C#, but if it's anything like Java - which I suspect it is - you can only set a variable of a given generic type if the generic parameters match.
我没有在C#中对此进行过调查,但如果它像Java一样 - 我怀疑它是 - 如果泛型参数匹配,则只能设置给定泛型类型的变量。 For example, other would have to be an Item of type Foo (
Item<Foo>
), not of type ItemData
. 例如,其他必须是Foo类型的Item(
Item<Foo>
),而不是ItemData
类型。 The reason goes something like this: 原因是这样的:
class A {...}
class B : A {...}
class C {
public static void main(string[] args) {
List<B> BL = new List<B>();
List<A> AL = BL;
AL.Add(new A()); // Now the List of B instances has an A instance in it!!
}
}
I'm not sure if there's a way to do something like Java's List<? extends A>
我不确定是否有办法像Java的
List<? extends A>
List<? extends A>
in C#, though. 但是,在C#中
List<? extends A>
。 That would be the Java-type solution. 这将是Java类型的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.