我有以下代码,它给出了错误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
和DataColumn
的具体类型,为什么这段代码编译得很好?编译器可以推断出using语句中的数据类型。数据表的处理是什么?
答案 0 :(得分:4)
因为DataTable.Rows
返回DataRowCollection
。 DataRowCollection
的{{1}}方法仅返回GetEnumerator
,而不是通用IEnumerable
。因此,推断出的类型是IEnumerable<T>
。
显然,您无法在object
上调用索引器方法。
编辑:
正如user7116所评论的那样,object
只会“接受”您想要的任何内容。然而,使用实际类型会产生底层强制转换。这是生成的IL:
var
这导致预期的行为。
答案 1 :(得分:2)
DataTable的行和列集合是IEnumerable
但不是IEnumerable
<T>
,因此它们确实返回object
,因为它们不是通用的。
您可以使用DataTable.AsEnumerable扩展方法(http://msdn.microsoft.com/en-us/library/system.data.datatableextensions.asenumerable.aspx)来处理前者。
答案 2 :(得分: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
的{{3}}是强类型的)