无法将类型为“<>d__6”的对象强制转换为类型“System.Object[]”

本文关键字:类型 转换 Object 对象 System | 更新日期: 2023-09-27 17:56:49

我正在尝试延迟加载(具有收益返回的扩展)2D 对象数组中的行。我收到以下错误:

c# 无法将类型为"<>d__6"的对象强制转换为类型"System.Object[]"。

异常发生在 Parse 方法中找到的以下行上:

yield return (TSource) conversion(o);

我不明白为什么C#认为返回值是<>d__6而不是Object[].我通常用VB.NET编程,所以我认为我不了解C#的细微差别。我做错了什么?我查看了其他类似的问题/答案,但仍然感到困惑。

public static IEnumerable<TSource> Parse<TSource>(this object[,] array
        , Func<IEnumerable<object[]>, IEnumerable<TSource>> conversion
        , int rowStart, int columnStart, int rowCount, int columnCount)
    {
        IEnumerable<object[]> o 
            = array.ForEachRow(rowStart, columnStart, rowCount, columnCount);
        yield return (TSource) conversion(o);
    }

ForEachRow 方法:

    public static IEnumerable<object[]> ForEachRow(this object[,] array, 
               int rowStart, int columnStart, int rowCount, int columnCount)
    {
        object[] array1d=new object[columnCount];
        for (int row = rowStart; row < rowCount; row++)
        {
            for (int column = columnStart; column < columnCount; column++)
            {
                array1d[column] = array[row, column];
            }
            yield return (object[]) array1d;
        }
    }

我知道这个问题以前有人问过,但不幸的是,其他答案对我来说没有意义(我主要是用 VB 编程)。

可用于编译和测试的代码(VB.NET):

基本上,我从Excel中获取了一个2D对象数组,并希望将其放在类中并使用Linq进行评估。

 Dim oData As Object(,) = {{"OrderDate", "Region", "Rep", "Item", "Units", "Unit Cost", "Total"} _
        , {New DateTime(2011, 1, 6), "East", "Jones", "Pencil", 95, 1.99, 189.05} _
        , {New DateTime(2011, 1, 23), "Central", "Kivell", "Binder", 50, 19.99, 999.5} _
        , {New DateTime(2011, 2, 9), "Central", "Jardine", "Pencil", 36, 4.99, 179.64} _
        , {New DateTime(2011, 2, 26), "Central", "Gill", "Pen", 27, 19.99, 539.73} _
        , {New DateTime(2011, 3, 15), "West", "Sorvino", "Pencil", 56, 2.99, 167.44} _
        }
    Dim clsSales = oData.Parse(Of SaleOrder)(Function(o As Object()) New SaleOrder( _
                                         If(IsDate(o(0)), o(0), #1/1/1900#) _
                                         , o(1).ToString _
                                         , o(2).ToString _
                                         , o(3).ToString _
                                         , If(IsNumeric(o(4)), CInt(o(4)), 0) _
                                         , If(IsNumeric(o(5)), o(5), 0) _
                                         ), 1, 0, oData.GetUpperBound(0), 6)
    For Each cls In clsSales
        Console.WriteLine(cls.ToString)
    Next

类在哪里:

 Class SaleOrder
Public Sub New(ByVal date_ As Date, ByVal region_ As String, ByVal rep As String, ByVal item_ As String, ByVal units As Integer _
               , ByVal cost As Double)
    OrderDate = date_
    Region = region_
    Representative = rep
    Item = item_
    UnitCount = units
    UnitCost = cost
End Sub
Public OrderDate As DateTime
Public Region As String
Public Representative As String
Public Item As String
Public UnitCount As Integer = 5
Public UnitCost As Double
Public ReadOnly Property Total() As Double
    Get
        Return UnitCount * UnitCost
    End Get
End Property
Public Overrides Function ToString() As String
    Return String.Format("{0} {1} {2} {3} {4} {5} {6}", OrderDate, Region, Representative, Item, UnitCount, UnitCost, Total)
End Function
End Class

最终解决方案

    public static IEnumerable<TSource> Parse<TSource>(this object[,] array
        , Func<object[], TSource> conversion
        , int rowStart, int columnStart, int rowCount, int columnCount)
    {
        for (int row = rowStart; row < rowCount; row++)
        {
            object[] array1d = new object[columnCount];
            for (int column = columnStart; column < columnCount; column++)
            {
                array1d[column] = array[row, column];
            }
            yield return conversion(array1d);
        }
    }

无法将类型为“<>d__6”的对象强制转换为类型“System.Object[]”

有了评论中的所有信息,现在很清楚这里发生了什么。让我们做一个更简单的重现:

public static IEnumerable<Tiger> Parse()
{
  object obj = ForEachRow();
  yield return (Tiger) obj;
}
public static IEnumerable<Tiger> ForEachRow()
{
  yield return new Tiger();
}

好的,编译器对底部方法做什么? 它像这样重写它:

class ForEachRowEnumerable : IEnumerable<Tiger>
{
    ... a class which implements an IEnumerable<Tiger> 
    that yields a single tiger...
}
public static IEnumerable<Tiger> ForEachRow()
{
  return new ForEachRowEnumerable();
}

那么现在第一种方法有什么作用呢?

你叫ForEachRow。这将返回一个新的 ForEachRowEnumerable。您将其转换为对象。然后,将对象投射到 Tiger。但ForEachRowEnumerable不是老虎;这是一个会给你一系列老虎的类。 因此,运行时会给出错误"无法将 ForEachRowEnumerable 转换为 Tiger"。

当然,C# 编译器不会将该类命名为"ForEachRowEnumerable"。它<>d__6命名它,以确保您不可能按名称实际使用该类。

o是一个IEnumerable<object[]>

conversion(o)是一个IEnumerable<TSource>. 您正在将一系列对象转换为一系列TSource项。

然后,您将该IEnumerable<TSource>投射到 TSource . 你基本上是在说,"把这一系列TSource项目视为一个TSource项目。 运行时告诉你的是,"我不允许将该项序列视为TSource项,因为事实并非如此。

您几乎肯定要实际做的是将最后一行替换为:

return conversion(o);

您有一系列TSource物品,这正是您需要返回的。 您尝试使用迭代器块过度思考了。

如果你真的想要使用迭代器块,那么你需要在序列中产生每个项目,如下所示:

foreach (TSource item in conversion(o))
    yield return item;

但何必呢。