2

我有以下给出错误的代码cannot apply indexing with [] to an expression of type object

protected void btnMakeCards_Click(object sender, EventArgs e)
{
    string cs = ConfigurationManager.ConnectionStrings["dbcs"].ConnectionString;
    using (var con = new SqlConnection(cs))
    using (var cmd = new SqlCommand("spDrugCardGenerator", con))
    {
        con.Open();
        cmd.CommandType = CommandType.StoredProcedure;
        DataTable dt = new DataTable();
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        da.Fill(dt);

        foreach (var row in dt.Rows)
        {
            foreach (var col in dt.Columns)
            {
                Response.Write(row[col].ToString());
            }
        }
    }
}

DataRow如果我使用and的具体类型,为什么这段代码编译得很好DataColumn?编译器可以在 using 语句中推断出数据类型应该是什么。数据表是怎么回事?

4

3 回答 3

4

因为DataTable.Rows返回一个DataRowCollection. 的方法只返回, 而DataRowCollection不是泛型。所以推断的类型是。GetEnumeratorIEnumerableIEnumerable<T>object

显然,您不能在object.

编辑:

正如 user7116 所评论的那样,var只会“接受”您想要的任何信息。然而,使用实际类型会产生潜在的强制转换。这是生成的 IL:

callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
               // ^^^^^^ returned as an object
castclass [System.Data]System.Data.DataRow // only included if you 
                                           // supply DataRow in the foreach

这会导致预期的行为。

于 2013-08-08T22:18:37.273 回答
2

DataTable 的行和列集合是IEnumerable但不是IEnumerableof <T>,因此它们确实返回objects,因为它们不是通用的。

您可以使用 DataTable.AsEnumerable 扩展方法 ( http://msdn.microsoft.com/en-us/library/system.data.datatableextensions.asenumerable.aspx )处理前者。

于 2013-08-08T22:17:45.047 回答
1

问题是dt.Rows,这是一个DataRowCollection,实现IEnumerable,而不是IEnumerable<DataRow>。这意味着,当你这样做的时候foreach (var row in dt.Rows)var只能下决心object。这是您的两个选项,每个选项都只是将对象转换为适当的数据类型:

foreach (DataRow row in dt.Rows)
{
    foreach (DataColumn col in dt.Columns)
    {
        Response.Write(row[col].ToString());
    }
}
// or
foreach (var row in dt.Rows.Cast<DataRow>())
{
    foreach (var col in dt.Columns.Cast<DataColumn>())
    {
        Response.Write(row[col].ToString());
    }
}

如果您真的想使用隐式类型var,则必须诉诸类似的方法,我建议这样做。

for (var i = 0; i < dt.Rows.Count; i++)
{
    var row = dt.Rows[i];
    for (var j = 0; j < dt.Columns.Count; j++)
    {
        var col = dt.Columns[j];
        Response.Write(row[col].ToString());
    }
}

(这是因为DataRowCollection's indexer 属性是强类型的)

于 2013-08-08T22:18:17.867 回答