I'm trying to lazy load (extension with yield return) the rows in a 2D object array. I get the following error:
c# Unable to cast object of type '<>d__6' to type 'System.Object[]'.
The exception occurs on this line found in the Parse
method:
yield return (TSource) conversion(o);
I don't understand why C#
thinks the return value is <>d__6
instead of Object[]
. I normally program in VB.NET
so I don't think I'm understanding the nuances of C#
. What am I doing wrong? I looked at the other similar questions/answers but am still confused.
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 method:
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;
}
}
I know this question has been asked before, but the other answers didn't make sense to me unfortunately (I program in VB mostly).
Code you can use to compile and test (In VB.NET
):
Basically I'm getting a 2D object array from Excel and wanting to put it in a class and use Linq to evaluate.
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
Where the class is:
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
Final Solution
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);
}
}