【问题标题】:Casting List<x> to List<y>将 List<x> 转换为 List<y>
【发布时间】:2011-09-01 11:51:34
【问题描述】:

以下代码有效:

List<JsonStock> stock = new List<JsonStock>();

foreach(tblStock item in repository.Single(id).tblStocks)                
    stock.Add((JsonStock) item);

所以你自然会认为这段代码也可以工作:

List<JsonStock> stock = repository.Single(id).tblStocks.Cast<JsonStock>().ToList()

但我收到错误 Invalid cast operation - 有人知道为什么会发生这种情况吗?

更新

tblStocks 是 LINQ to SQL 对象 tblStock 的列表。
JsonStock 是 tblStock 类的简化版本,以 JSON 形式返回到网页对象。

以下运算符是为进行强制转换而构建的:

public partial class tblStock{
    public static explicit operator JsonStock(tblStock stock){
        JsonStock item = new JsonStock
        {
            boxes = stock.boxes,
            boxtype = stock.tblBoxType.name,
            boxtype_id = stock.boxtype_id,
            grade = stock.grade,
            packrate = stock.packrate,
            weight = stock.weight
        };

        return item;
    }
}

【问题讨论】:

  • tblStocks的类型是怎么定义的?
  • 只是一个想法,不确定这一点:repository.Single(id).tblStocks 返回JsonStock 的数组或列表,因此当您尝试转换为JsonStock 时,它会抱怨...
  • @Marco - 不,它不应该抱怨。
  • tblStock 和 JsonStock 是什么关系?
  • 假设 tblStocks 是 JsonStock 的 IEnumerable,您的代码应该可以工作。那么“tblStocks 中的内容”是什么?我假设那里还有继承的“JsonStock”类的对象,因为这会导致强制转换异常。

标签: c# list casting


【解决方案1】:

Cast 用于将非泛型集合更改为泛型集合,即执行拆箱操作。它不能以您想要的方式使用。
当您查看 Cast 和它使用的 CastIterator 的实现时,您会看到,它接受一个对象并将其转换为指定的类型:

foreach (object current in source)
{
    yield return (TResult)current;
}

仅当current 确实是TResult 时才有效。在这种情况下,不会应用任何自定义转换。
这是默认行为,你可以自己测试一下:

double d = 0.0;
object tmp = d;
int i = (int)tmp; // throws the same exception you are getting

如果tblStocks 是一个通用的可枚举对象,则最好使用简单的Select 来实现您想要的:

List<JsonStock> stock = repository.Single(id).tblStocks
                                  .Select(x => (JsonStock)x).ToList();

或者,如果tblStocks 是非泛型可枚举,则需要结合CastSelect

List<JsonStock> stock = repository.Single(id).tblStocks.Cast<tblStock>()
                                  .Select(x => (JsonStock)x).ToList();

这将首先将tblStocks 中的对象拆箱为它们的真实类型(tblStock),然后将其转换为您想要的类型(JsonStocks)。

【讨论】:

    【解决方案2】:

    隐式和显式转换运算符是ignored by Cast。在你的情况下,这意味着

     public static explicit operator JsonStock(tblStock stock)
    

    被 Cast 忽略,但在 foreach 情况下不会被忽略

    【讨论】:

    • 谁说的?如果那是真的Enumerable.Cast&lt;T&gt;() 将毫无意义。 msdn.microsoft.com/en-us/library/bb341406.aspx 不包含支持您声明的信息。
    • @VVS:你不明白Enumerable.Cast&lt;T&gt;()的目的。输入是非泛型可枚举。结果是一个通用的可枚举。此扩展方法的全部目的是从您知道对象类型的非泛型枚举中创建强类型枚举。有关详细信息,请参阅我的答案。
    • @VVS 如果仔细阅读该链接确实包含支持我的主张的信息,就像我的答案中的链接一样。您提供的链接讨论了上面的 cast 运算符是 conversion 运算符。使用两者的语法是相同的(SomeType),但这并不能使它们相同。所以我真的没有得到你的反对
    【解决方案3】:

    考虑使用 OfType,而不是使用 Cast。在 Cast 中,如果您正在处理的项目不是所需的类型,您将收到 InvalidCastException。使用 OfType,它会捕获无效转换并仅返回实际是您正在寻找的类型的项目。

    List<JsonStock> stock = repository.Single(id).tblStocks.OfType<JsonStock>().ToList() 
    

    但是,如果您返回空列表,我会怀疑您的 tblStocks 实际上没有返回 JsonStocks,并且您正在尝试将其他类型(tblStock?)投影到 DTO(JsonStock)中。如果是后者,则需要使用 Select 从底层类型投影到新类型中。

    List<JsonStock> stock = repository.Single(id).tblStocks
                            .Select(stock => new JsonStock 
                                 { 
                                   Id = stock.Id,
                                   Val1 = stock.Val1,
                                   Val2 = stock.Val2,
                                   ...
                                 }
                             .ToList();
    

    【讨论】:

      【解决方案4】:

      啊,显式运算符重载的奇迹。

      因此,要解决您的问题,您可能需要事先调用 Select。

      List<JsonStock> stock = repository.Single(id).tblStocks.Select(x => (JsonStock)x).ToList() 
      

      但是我想说这个运算符重载是你应该摆脱的。考虑用像实现这样的复制构造函数替换它

      class JsonStock
      {
           public JsonStock(tblStock other)
           {
                // copy values here
           }
      }
      

      【讨论】:

        【解决方案5】:
        • tblStocks.Cast&lt;JsonStock&gt;() 进行演员阵容。
        • (JsonStock) item 执行转换或应用自定义转换

        由于 tblStock 是 LINQ to SQL 类,而 JsonStock 是您创建的自定义类,因此没有一个是另一个的子类型。因此,您不能在两者之间进行转换。

        要解决这个问题,您可以使用 LINQ 的 Select 子句并手动转换元素:

         List<JsonStock> stock = repository.Single(id).tblStocks
             .Select(item => (JsonStock) item).ToList();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-15
          • 2023-03-15
          • 2013-09-01
          • 2019-09-17
          • 1970-01-01
          • 2023-01-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多