Reputation: 3
Is it possible to pass a generic object as an argument with a class type that is derived from the expected class type?
The code below results in a compiler error, cannot convert from ItemObject<Equipment> to ItemObject<Item>
, which I find odd because Equipment
inherits from Item
.
using System.Collections.Generic;
public abstract class Item { }
public abstract class Equipment : Item { }
public class ItemObject<T> where T : Item { }
public class EquipmentManager
{
ItemObject<Equipment> equipment = new ItemObject<Equipment>();
public void Unequip()
{
Inventory.instance.AddItem(equipment);
}
}
public class Inventory
{
public static Inventory instance;
List<ItemObject<Item>> items = new List<ItemObject<Item>>();
public void AddItem(ItemObject<Item> _item)
{
items.Add(_item);
}
}
Upvotes: 0
Views: 319
Reputation: 612
The problem here isn't that Equipment
is inherited from Item
. The issue is you are creating a specific type from a generic class. ItemObject<T>
-> ItemObject<Equipment>
. There is no explicit or implicit method to convert an ItemObject<Equipment>
to an ItemObject<Item>
.
Where the implicit conversion would work is if you had an ItemObject<Item>
and tried to add an Equipment
in place of an Item
. In this case, the Equipment
would be implicitly cast as an Item
before being passed to ItemObject<Item>
's method.
Upvotes: 0
Reputation: 30092
You could achieve that using covariance, which would allow you to use a more derived type. However that can only be applied to interfaces, so you would need to do something like this:
public abstract class Item { }
public abstract class Equipment : Item { }
public interface IItemObject<out T> where T : Item { }
public class ItemObject<T> : IItemObject<T> where T : Item { }
public class EquipmentManager {
IItemObject<Equipment> equipment = new ItemObject<Equipment>();
public void Unequip() {
Inventory.instance.AddItem(equipment);
}
}
public class Inventory {
public static Inventory instance;
List<IItemObject<Item>> items = new List<IItemObject<Item>>();
public void AddItem(IItemObject<Item> _item) {
items.Add(_item);
}
}
More reading on covariance and contravariance.
Upvotes: 4