使用 foreach 循环时使用未分配的局部变量
use of unassigned local variable when using a foreach Loop
我有一个代码块可以从存储过程中获取一些数据。我收到数据后,想根据条件给"isExisting"赋值。我不想在声明的时候给"isExisting"赋值
bool isExisting;
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("input", value));
using (var adapter = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adapter.Fill(ds);
if (ds.Tables.Count > 0)
{
if (ds.Tables[0].Rows.Count == 0)
isExisting = false;
else
{
foreach (DataRow row in ds.Tables[0].Rows)
{
if (row["Key"].ToString() == ValueToCompareWith)
{
isExisting = true;
break;
}
else
isExisting = false;
}
}
}
else
isExisting = false;
}
}
}
if (!isExisting) //Step :getting error "use of unassigned local variable"
{
}
我想我已经涵盖了所有条件,变量 "isExisting" 在达到 "Step" 时会有一个值,但我仍然遇到编译器错误。
问题开始是因为我的代码审查工具正在发表评论
"A dead store happens when a local variable is assigned a value that is not read by any subsequent instruction. Calculating or retrieving a value only to then overwrite it or throw it away, could indicate a serious error in the code. Even if it's not an error, it is at best a waste of resources. Therefore all calculated values should be used."
不合规代码示例
void CalculateRate(int a, int b)
{
int i;
i = a + b; // Noncompliant; calculation result not used before value is overwritten
i = DoSomething(); // Noncompliant; retrieved value not used
for (i = 0; i < 10; i++)
{
// ...
}
// ...
}
编译器是个傻瓜。它不会检查所有逻辑以确保变量始终获得值。那不是它的工作。只需给 isExisting
一个默认值以使编译器满意,您的实际代码无论如何都会设置正确的值(正如您已经声明的那样)。
编译器无法确定是否每段代码都会被命中 - 例如,如果此循环中可能没有行:
foreach (DataRow row in ds.Tables[0].Rows)
因此不会命中整个 if 块。
设置默认值。
正如其他人所指出的,编译器不够智能,无法知道您是否真的在为变量赋值。
您可以通过使用一些 Linq 来解决这个歧义,并大量清理您的代码:
bool isExisting;
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("input", value));
using (var adapter = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adapter.Fill(ds);
isExisting = ds.Tables
.OfType<DataTable>()
.Take(1)
.SelectMany(t => t.Rows.OfType<DataRow>())
.Any(r => r["Key"].ToString() == ValueToCompareWith);
}
}
}
if (!isExisting)
{
}
另一种方法是将 isExisting
检查分解为单独的方法:
bool CheckIsExisting(object value, string valueToCompareWith)
{
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("input", value));
using (var adapter = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adapter.Fill(ds);
if (ds.Tables.Count != 0 && ds.Tables[0].Rows.Count != 0)
{
foreach (DataRow row in ds.Tables[0].Rows)
{
if (row["Key"].ToString() == ValueToCompareWith)
{
return true;
}
}
}
}
}
}
return false;
}
然后做:
if (!CheckIsExisting(value, ValueToCompareWith))
{
// do something...
}
Bool
的默认值是false
。在您的代码中提供它。
bool isExisting=false;
您在代码中编写的整个业务逻辑应该注意
if (!isExisting) {
}
背后的主要逻辑是编译器几乎不会打扰你编写的脚本。它只需要分配的值,然后才能在任何条件下使用它。
参考here了解更多。
我有一个代码块可以从存储过程中获取一些数据。我收到数据后,想根据条件给"isExisting"赋值。我不想在声明的时候给"isExisting"赋值
bool isExisting;
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("input", value));
using (var adapter = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adapter.Fill(ds);
if (ds.Tables.Count > 0)
{
if (ds.Tables[0].Rows.Count == 0)
isExisting = false;
else
{
foreach (DataRow row in ds.Tables[0].Rows)
{
if (row["Key"].ToString() == ValueToCompareWith)
{
isExisting = true;
break;
}
else
isExisting = false;
}
}
}
else
isExisting = false;
}
}
}
if (!isExisting) //Step :getting error "use of unassigned local variable"
{
}
我想我已经涵盖了所有条件,变量 "isExisting" 在达到 "Step" 时会有一个值,但我仍然遇到编译器错误。
问题开始是因为我的代码审查工具正在发表评论
"A dead store happens when a local variable is assigned a value that is not read by any subsequent instruction. Calculating or retrieving a value only to then overwrite it or throw it away, could indicate a serious error in the code. Even if it's not an error, it is at best a waste of resources. Therefore all calculated values should be used."
不合规代码示例
void CalculateRate(int a, int b)
{
int i;
i = a + b; // Noncompliant; calculation result not used before value is overwritten
i = DoSomething(); // Noncompliant; retrieved value not used
for (i = 0; i < 10; i++)
{
// ...
}
// ...
}
编译器是个傻瓜。它不会检查所有逻辑以确保变量始终获得值。那不是它的工作。只需给 isExisting
一个默认值以使编译器满意,您的实际代码无论如何都会设置正确的值(正如您已经声明的那样)。
编译器无法确定是否每段代码都会被命中 - 例如,如果此循环中可能没有行:
foreach (DataRow row in ds.Tables[0].Rows)
因此不会命中整个 if 块。
设置默认值。
正如其他人所指出的,编译器不够智能,无法知道您是否真的在为变量赋值。
您可以通过使用一些 Linq 来解决这个歧义,并大量清理您的代码:
bool isExisting;
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("input", value));
using (var adapter = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adapter.Fill(ds);
isExisting = ds.Tables
.OfType<DataTable>()
.Take(1)
.SelectMany(t => t.Rows.OfType<DataRow>())
.Any(r => r["Key"].ToString() == ValueToCompareWith);
}
}
}
if (!isExisting)
{
}
另一种方法是将 isExisting
检查分解为单独的方法:
bool CheckIsExisting(object value, string valueToCompareWith)
{
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("input", value));
using (var adapter = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
adapter.Fill(ds);
if (ds.Tables.Count != 0 && ds.Tables[0].Rows.Count != 0)
{
foreach (DataRow row in ds.Tables[0].Rows)
{
if (row["Key"].ToString() == ValueToCompareWith)
{
return true;
}
}
}
}
}
}
return false;
}
然后做:
if (!CheckIsExisting(value, ValueToCompareWith))
{
// do something...
}
Bool
的默认值是false
。在您的代码中提供它。
bool isExisting=false;
您在代码中编写的整个业务逻辑应该注意
if (!isExisting) {
}
背后的主要逻辑是编译器几乎不会打扰你编写的脚本。它只需要分配的值,然后才能在任何条件下使用它。
参考here了解更多。