有没有办法将 IEnumerable<T> 视为参数 T[] 对象?

Is there a way to treat an IEnumerable<T> as a params T[] object?

我想编写 returns Sql 服务器过程结果为 DataTable 对象的通用代码。然后我写了下面的代码,但是,我偶然发现了 DataTable.Rows.Add() 期待 params object[] 参数的问题,而我必须传递的是 IEnumerable<string>.

    public static DataTable GetProcedureResults(int id)
    {
        return GetQueryResultAsDataTable<MyProcedure_Result>(_sqlServerDB.MyProcedure(id));
    }

    private static DataTable GetQueryResultAsDataTable<T>(ObjectResult<T> objectResult)
    {
        DataTable resultAsDataTable = new DataTable("Result");
        var columns = typeof(T).GetProperties();
        foreach (var column in columns)
        {
            resultAsDataTable.Columns.Add(column.Name, typeof(string));
        }

        foreach (var resultRecord in objectResult)
        {
            var fields = resultRecord.GetType().GetProperties().Select(p => p.GetValue(resultRecord).ToString());
            resultAsDataTable.Rows.Add(fields);
        }

        return resultAsDataTable;
    }

熟悉这个问题的朋友可能已经猜到我最后的数据表是这样的:

这些值都被视为一个对象,因此都被插入到第 1 列中。

这里有什么解决方法(如果有)?我在其他帖子中读到 C#6 似乎将 修复 这个问题,除此之外没有找到清晰简洁的解决方案。

如果你有一个 IEnumerable<T> 并且一个方法需要一个 T[],只需在你的可枚举上调用 ToArray

var fields = resultRecord.GetType().GetProperties().Select(p => p.GetValue(resultRecord).ToString());
resultAsDataTable.Rows.Add(fields.ToArray());

定义 IEnumerable<T> 而不是 T[]params 参数的能力并没有最终进入 C# 6(参见 Eric Lippert's answer about the feature, which links to the announcement of the feature being removed from C# 6). However, even with that theoretical feature, it wouldn't help in this case. That feature would allow the designer of an API (e.g. the person writing DataRowCollection.Add)以接受 IEnumerable<T> 而不是 T[] 如果他们这样选择(在这种情况下,他们几乎肯定不会,因为这将是一个无声的破坏性变化)。它不允许您将 IEnumerable<T> 传递给需要 T[] 的方法。作为方法的调用者,如果您不使用参数的 params 属性(即传递单个参数而不是集合),那么它只是一个采用数组的 "normal" 方法,并且您负责将参数转换为预期类型。

您实际上可以将数组传递给 params object[],因此临时解决方案可能只是:

var fields = resultRecord.GetType().GetProperties()
                                   .Select(p => p.GetValue(resultRecord).ToString())
                                   .ToArray();
resultAsDataTable.Rows.Add(fields);