【问题标题】:Invalid Arguments Error Using Generics使用泛型的无效参数错误
【发布时间】:2012-04-02 07:39:57
【问题描述】:

我正在尝试使用此处找到的功能: DataTable to List<object>

  public static IList<T> ConvertTo<T>(DataTable table)
        {
            if (table == null)
                return null;

            List<DataRow> rows = new List<DataRow>();

            foreach (DataRow row in table.Rows)
                rows.Add(row);

            return ConvertTo<T>(rows);
        }

return 语句给了我一个例外声明:

The best overloaded method match for 'Utilities.Utility.ConvertTo<T>(System.Data.DataTable)' has some invalid arguments

有人可以帮我解决这个错误吗?

【问题讨论】:

  • 这是一个编译器错误,不是例外。
  • 您阅读了邮件吗?你希望这条线做什么?
  • 你可以用table.AsEnumerable().ToList()替换整个函数
  • @SLaks 将数据表转换为 IList
  • 你认为最后一行是做什么的?

标签: c#


【解决方案1】:

不要那样做,使用 Marc 的神奇功能 (https://stackoverflow.com/a/545429/215752) 我的意思是真的......这正是你想要的......对吧?


你需要另一个函数

public static IList<T> ConvertTo<T>(IList<DataRow> rows)
    {
        IList<T> list = null;

        if (rows != null)
        {
            list = new List<T>();

            foreach (DataRow row in rows)
            {
                T item = CreateItem<T>(row);
                list.Add(item);
            }
        }

        return list;
    }

您链接的问题中有一个链接。我建议在那里寻找更多信息:

http://lozanotek.com/blog/archive/2007/05/09/Converting_Custom_Collections_To_and_From_DataTable.aspx

在那里你会找到我希望编译的所有代码。但是,我不会保证使用它的可靠性或合理性。

【讨论】:

  • 我不确定如何使用它来将数据表转换为 IList 它告诉我无法隐式转换类型 'System.Collections.Generic.List>' 到 'System.Collections.Generic.List'
  • 听起来像是错字或对 Olivier Jacot-Descombes 答案的评论
  • 当我想返回 IList 时,我无法让你的或 Olivers 的函数工作
  • 你有没有点击链接并使用@Marc函数...这样更好。
【解决方案2】:

首先,您返回的是T,而不是IList&lt;T&gt;。其次,您如何期望 DataRow 转换为未知的 T,尤其是在一行有几列的情况下?

试试这样的

public static IList<IList<T>> ConvertTo<T>(DataTable table)
{
    if (table == null)
        return null;
    List<IList<T>> rows = new List<IList<T>>();
    foreach (DataRow row in table.Rows) {
        rows.Add(row.ItemArray.Cast<T>().ToArray());
    }
    return rows;
}

更新:

自定义对象是这样的

public class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Salary { get; set; }
}

但是,在这种情况下,通用接口没有用处,因为您必须为该特定类编写代码

public static IList<Employee> GetEmployees(DataTable table)
{
    var employees = new List<Employee>();
    if (table != null) {
        foreach (DataRow row in table.Rows) {
            var emp = new Employee();
            emp.ID = (int)row["ID"];
            emp.Name = (string)row["Name"];
            emp.Salary = (decimal)row["Salary"];
            employees.Add(emp);
        }
    }
    return employees;
}

此代码对于不同的表必须不同,并且不能通用。至少不使用反射并假设属性与表列具有相同的名称。


不使用一些棘手的Reflection 代码或其他魔术技巧的解决方案是定义这样的接口

public interface IDataObject
{
    void FillFromRow(DataRow row);
}

然后你声明Employee 或任何其他类似的数据类

public class Employee : IDataObject
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Salary { get; set; }

    public void FillFromRow(DataRow row)
    {
        ID = (int)row["ID"];
        Name = (string)row["Name"];
        Salary = (decimal)row["Salary"];
    }
}

现在你可以再次使用泛型了

public static IList<T> GetItems<T>(DataTable table)
    where T : IDataObject, new()
{
    var items = new List<T>();
    if (table != null) {
        foreach (DataRow row in table.Rows) {
            T item = new T();
            item.FillFromRow(row);
            items.Add(item);
        }
    }
    return items;
}

【讨论】:

  • @Oliver 如果我想将数据表转换为 IList,你能告诉我如何使用该函数的示例吗?
  • @Oliver 这是我的编码方式,但其他人说 (decimal)row["Salary"];如果被认为是“糟糕的”编码实践。你有什么意见?
  • 谁说这是不好的编码习惯?请提供参考。
  • DataRow 将列值返回为object。你只需要投射它们。从数据库表中读取数据的一种非常有效的方法是使用DataReaderDataReader 有类型化的方法来获取像 int i = reader.GetInt32("ID"); 这样的值
  • 如果我将数据库中的字段名称从“ID”更改为“MyID”,我将不得不在代码中的所有位置更改“ID”。
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2016-03-21
  • 2013-08-04
  • 2018-12-01
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
相关资源
最近更新 更多