我该如何在C# .Net Core中实现未知的数组类型?

4

我有以下代码,但还没有弄清如何实现var results =部分,以便result[c] = valuesArray;可以正常工作?

    var result = Array.CreateInstance(typeof(Array), dt.Columns.Count);

            foreach (int c in Enumerable.Range(0, dt.Columns.Count))
            {
                // Create a list to hold values of the required type for the column
                var valuesArray = Array.CreateInstance(typeof(float), dt.Rows.Count);

                // Get the data to be written to the parquet stream
                for (int r = 0; r < dt.Rows.Count; r++)
                {
                    DataRow row = dt.Rows[r];

                    valuesArray.SetValue(row[c], r);
                }

                result[c] = valuesArray;

错误信息是:

Error: CS0021 = Cannot apply indexing with [] to an expression of type 'Array'

我该如何实例化Array以使其正常工作?

4个回答

2

看起来result.SetValue(valuesArray, c)会起作用。

你还可以通过以下方式获取值

result.GetValue(c);

因此,如果您需要遍历 result,您可以编写一个类似于您已经编写的 foreach 的循环。

foreach (int c in Enumerable.Range(0, dt.Columns.Count))
{
   var x = result.GetValue(c);
}

谢谢。我忘了那部分了。我该如何迭代以获取值? - cdub

2

就像你使用SetValue()方法给valuesArray设置值一样,你也可以对result进行相同的操作:

result.SetValue(valuesArray, c);

如果您需要在迭代过程中检索值,则可以使用result.GetValue(c)

foreach (int c in result)
{
    var retrievedResult = result.GetValue(c);
}

如何从results.GetValue()中获取一个值,以便在整个范围的for循环中使用result[c]作为结果? - cdub
这恰恰相反:result.GetValue(c); - David L
是的,谢谢。我已经这样做了并看到了一个错误,但这个错误来自于我传递给它的API,所以一切都很好。再次感谢。 - cdub

2
我尝试并成功的 Nice 方法是:

以下是具体步骤:

 var result = (dynamic)Array.CreateInstance(typeof(Array), columnLength);

示例代码如下:
int columnLength = 8;
var result = (dynamic)Array.CreateInstance(typeof(Array), columnLength);

foreach (int c in Enumerable.Range(0, columnLength)) {
    // Create a list to hold values of the required type for the column
    var valuesArray = Array.CreateInstance(typeof(float),columnLength);

    // Get the data to be written to the parquet stream
    for (int r = 0; r < columnLength; r++) {

        valuesArray.SetValue(r, r);
    }

    result[c] = valuesArray;
}

foreach (var arr in result)
    foreach (var value in arr)
        Console.Write($"{value}\t");
Console.ReadLine();

输出结果为:
0       1       2       3       4       5       6       7       0       1       2       3       4       5       6
        7       0       1       2       3       4       5       6       7       0       1       2       3       4
        5       6       7       0       1       2       3       4       5       6       7       0       1       2
        3       4       5       6       7       0       1       2       3       4       5       6       7       0
        1       2       3       4       5       6       7

1
你可以使用泛型来实现这个功能。唯一需要反射的是每列执行一次内部函数。
  • 初始数组可以不使用 Array.CreateInstance
var method = this.GetType().GetMethod("GetArray");

var result = new Array[dt.Columns.Count];

for (int c = 0; c < dt.Columns.Count; c++)
{
    var generic = method.MakeGenericMethod(dt.Columns[c].DataType);
    result[c] = (Array)generic.Invoke(null, new[]{dt.Rows, c});
}

public static Array GetArray<T>(DataRowCollection rows, int c)
{
    var valuesArray = new T[rows.Count];
    for (int r = 0; r < rows.Count; r++)
    {
        DataRow row = rows[r];
        valuesArray[r] = (T)row[c];
    }
    return valuesArray;
}

在高性能场景下,您甚至可以缓存通用函数的委托。
static MethodInfo method = this.GetType().GetMethod("GetArray");

static Dictionary<Type, Func<DataRowCollection, int, Array>> funcs = new();

var result = new Array[dt.Columns.Count];

for (int c = 0; c < dt.Columns.Count; c++)
{
    if(!funcs.TryGetValue(dt.Columns[c].DataType, out var func)
    {
        func = funcs[dt.Columns[c].DataType] =
          (Func<DataRowCollection, int, Array>) method.MakeGenericMethod(dt.Columns[c].DataType)
             .CreateDelegate(typeof(Func<DataRowCollection, int, Array>));
    }
    result[c] = func(dt.Rows, c);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接