使用空赋值修复“使用未分配的局部变量”。 为什么?
使用这样的一段代码,编译器在c.MyProperty
上c.MyProperty
:
MyClass c; try { throw new Exception(); } catch (Exception) { } c.MyProperty = 2; // "Use of unassigned local variable 'c'".
但是,如果在初始化中为c
分配null
,则不会抱怨:
MyClass c = null; try { throw new Exception(); } catch (Exception) { } c.MyProperty = 2; // no complains this time.
那么,为什么这有效呢? 如果c
没有赋值为null
并且编译器假设允许它,那么不会在c.MyProperty
抛出相同的exception, 对象引用没有设置为对象的实例吗?
当你给变量赋值null
时,你告诉编译器退出,因为你比他更了解所以他不应该抱怨这个。
这可能是由于分配null
被认为暗示开发人员的明确行为。
可以这样想,编译器并没有告诉你它会抛出一个空引用,因此无法编译,而是编译所需的条件之一,即它具有明确分配。
根据规范,null是ac#literal:“null-literal可以隐式转换为引用类型或可空类型”
在任务方面:(取自规范)
从规范中开始引用
5.3.3确定明确赋值的精确规则为了确定每个使用的变量是明确赋值的,编译器必须使用与本节中描述的相同的过程。
编译器处理每个函数成员的主体,该成员具有一个或多个最初未分配的变量。 对于每个最初未分配的变量v,编译器在函数成员中的以下每个点确定v的明确赋值状态:
·在每个陈述的开头
·在每个陈述的终点(§8.1)
·在每个弧上将控制转移到另一个语句或语句的结束点
·每个表达式的开头
·每个表达式的结尾
报价结束
因此,即使null实际上没有指向内存中的对象,它确实满足了明确赋值的要求,这就是编译器允许它的原因。
这是因为C#语言规范v.4.0第1.6.6.2节“方法主体和局部变量”声明如下:
方法体可以声明特定于方法调用的变量。 这些变量称为局部变量。
[跳过]
C#需要在可以获得其值之前明确赋值 。
这是为了避免让你自己在脚下射击,正如Binary Worrier巧妙地指出的那样。
此exception的原因是您没有为变量分配默认值,例如
if (Request.Files != null && Request.Files.Count > 0) { Image = Request.Files.AllKeys[0]; } var stream = new FileStream(Image,FileMode.Open);
现在Image变量会给编译器错误
使用未分配的局部变量’Image’
这是因为有可能条件变为真,控制永远不会知道Image变量是什么。 所以要么放置一个else块,要么指定一个默认值,如下所示。
string Image = ""; if (Request.Files != null && Request.Files.Count > 0) { Image = Request.Files.AllKeys[0]; } var stream = new FileStream(Image,FileMode.Open);