简体   繁体   中英

Passing a generic object with type that is derived from the required type

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);
    }

}

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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM