簡體   English   中英

無法將類型為“<> d__6”的對象強制轉換為“System.Object []”

[英]Unable to cast object of type '<>d__6' to type 'System.Object[]'

我正在嘗試延遲加載(帶有yield返回的擴展)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);
        }

    }

通過評論中的所有信息,現在可以清楚地了解這里發生了什么。 讓我們做一個更簡單的復制:

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以確保您不可能按名稱實際使用該類。

oIEnumerable<object[]>

conversion(o)IEnumerable<TSource> 您正在將一系列對象轉換為一系列TSource項。

然后,將IEnumerable<TSource> TSourceTSource 您基本上是在說,“將此TSource項目序列視為單個TSource項目。” 運行時告訴你的是,“我不允許將該項目序列視為TSource項目,因為它不是它的TSource

您幾乎肯定想要實際做的只是用以下內容替換最后一行:

return conversion(o);

您有一系列TSource項目,這正是您需要返回的內容。 你試圖使用迭代器塊來過度思考它。

如果你確實想要使用迭代器塊,那么你需要生成序列中的每個項目,如下所示:

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

但為什么這么麻煩。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM