C# - 使用DataTable和Field <int>指定的强制转换无效

时间:2017-08-01 03:23:18

标签: c# csv datatable casting

我有一个包含8列的csv文件,我试图用8个变量填充一个对象,每个变量都是一个列表来保存csv文件中的列。首先,我使用我的csv数据填充DataTable

我现在正尝试使用DataTable

中的数据填充我的对象
DataTable d = GetDataTableFromCSVFile(file);
CoolObject l = new CoolObject();

for (int i = 0; i < d.Rows.Count; i++)
{
    l.column1[i] = d.Rows[i].Field<int>("column1"); <-- error here
}

这是我的CoolObject

public class CoolObject
{
    public List<int> column1 { set; get; }

    protected CoolObject()
    {
        column1 = new List<int>();
    }
}

不幸的是,我在突出显示的行上收到错误:

System.InvalidCastException: Specified cast is not valid

为什么不允许这样做?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

显然你DataTable包含string类型的列,所以在GetDataTableFromCSVFile方法中进行整数验证,所以这个方法的使用者不需要担心它。

显然你DataTable包含string类型的列,所以在GetDataTableFromCSVFile方法中进行整数验证,所以这个方法的使用者不需要担心它。

private DataTable GetDataTableFromCSVFile()
{
    var data = new DataTable();
    data.Columns.Add("Column1", typeof(int));

    // Read lines of file

    // line is imaginery object which contains values of one row of csv data
    foreach(var line in lines) 
    {
        var row = data.NewRow();
        int.TryParse(line.Column1Value, out int column1Value)
        row.SetField("Column1", column1Value) // will set 0 if value is invalid

        // other columns
    }

    return data;
}

然后是您的代码的另一个问题,即您通过索引向List<int>提供新值,其中list为空

l.column1[i] = d.Rows[i].Field<int>("column1");

上面的行将抛出异常,因为空列表没有索引i上的项目。

所以你最终会看到你的方法

DataTable d = GetDataTableFromCSVFile(file);
CoolObject l = new CoolObject();

foreach (var row in d.Rows)
{
    l.column1.Add(row.Field<int>("column1"));
}

如果您使用某些第三方库从csv检索数据到DataTable - 您可以检查该库是否可以在DataTable中验证/转换字符串值到预期类型。

答案 1 :(得分:-1)

听起来有人没有在其中一个单元格中输入数字。在读取值之前,您必须执行验证检查。

df1:
id  page_ids (collect_list)
12  ['1001','1001','1002','1003']
13  ['2001','2002','2003','2004']

df2:
id page_id
12 '1002'
13 '4001'

df3 = df1 \
     .join(df2,on=df1['id'] == df2['id']) \
     .filter(udf(col(page_ids),col('page_id))

或者它可能是一个数字,但由于某种原因,它是以字符串形式出现的。你可以这样试试:

for (int i = 0; i < d.Rows.Count; i++)
{
    object o = d.rows[i]["column1"];
    if (!o is int) continue;
    l.column1[i] = (int)o;
}