【问题标题】:T to Object works but List<T> to List<Object> doesnt work at all [duplicate]T to Object 有效,但 List<T> to List<Object> 根本不起作用[重复]
【发布时间】:2021-05-04 15:29:30
【问题描述】:

你好,下面的代码。我知道 T 将始终是基类“Item”中的一种类型。 但我不能将列表转换为项目。对于 T 项目它的工作。

private List<Item> activeItemList;
private Item activeItem;


public void StartBuildingSystem<T>(List<T> itemList, T item, int count, string name) where T : Item
{
    UiPlacementActivate(itemList, item,count);
    PlacingAreas(GetActiveBluePrint(name), GetActiveType(itemList, name));
    activeBuildingType = GetActiveBuildingType(name);
    activeItem = item;
    //activeItemList = itemList;//
}

// // 中的代码不起作用,因为我无法将 List T 转换为 List Item。有更好的方法吗?如果我知道传入的列表将始终来自基类“项目”,但它来自不同的库存(冷却、安全、....),或者有没有办法我可以轻松地将列表转换为项目列表,就像它适用于T 项目到项目。

【问题讨论】:

  • 你能发布你得到的确切错误吗?在不知道您正在使用的所有方法的确切签名的情况下,很难看到它......一般来说,您可能会使用Linq Cast&lt;T&gt;
  • 在 C# 中查找协方差——大量的 SO 帖子和其他关于它的文章

标签: c# unity3d


【解决方案1】:

您不能在各种类型的列表之间进行转换,因为 List&lt;T&gt; 是不变的。更多信息请参见still confused about covariance(或查看3,000 questions on Stackoverflow about it)。

您可以转换列表而不是转换(通过一次转换一个项目)。所以不是

activeItemList = itemList;

使用

activeItemList = itemList.Select( x => (Item)x ).ToList();

【讨论】:

    【解决方案2】:

    如果您可以在代码中进行以下更改,它将允许协方差:

    private IEnumerable<Item> activeItemList; // previously List<Item>
    private Item activeItem;
    
    public void StartBuildingSystem<T>(List<T> itemList, T item, int count, string name) where T : Item
    {
        UiPlacementActivate(itemList, item,count);
        PlacingAreas(GetActiveBluePrint(name), GetActiveType(itemList, name));
        activeBuildingType = GetActiveBuildingType(name);
        activeItem = item;
        activeItemList = itemList; //it will now work
    }
    

    【讨论】:

      【解决方案3】:

      可变集合无法实现方差。要了解原因,请根据您的代码查看以下示例:

      private List<Fruit> currentFruitList;
      private Fruit currentFruit;
      
      
      public void StartBuildingSystem<T>(List<T> fruitList, T fruit) where T : Fruit
      {
          currentFruit = fruit;
          currentFruitList = fruitList;
      }
      

      让我们想象一下上面的代码可以编译(它不会)。现在想象你这样做:

      List<Apple> apples = new();
      Apple apple = new();
      
      StartBuildingSystem(apples, apple);
      
      Orange orange = new();
      currentFruit = orange; //fine!
      currentFruitList.Add(new Orange()); //this is a problem!
      

      但是,不可变集合可以处理这个问题。为了扩展这个例子,如果你将你的 List&lt;Fruit&gt; 更改为 IEnumerable&lt;Fruit&gt; 一切都会编译得很好,因为你不会不小心将橙色添加到 IEnumerable&lt;Apple&gt;

      This 是微软在这个主题上提供的最好的文章之一。

      【讨论】:

        【解决方案4】:

        约翰的回答看起来可行,但这是另一种选择:

        // add "using System.Linq;" beforehand
        activeItemList = itemList.Cast<Item>().ToList();
        

        其他答案也解释了这一点,但基本上,activeItemList 不能分配给属于Item 的严格子类型(比如BlueItem)的列表,因为那样的话,这个列表将更加“有限” " 并且无法处理Item其他 个非重叠子类型(例如RedItem)。

        【讨论】:

          猜你喜欢
          • 2018-02-13
          • 2018-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多