使用空分配修复“使用未分配的局部变量”。为啥?

Posted

技术标签:

【中文标题】使用空分配修复“使用未分配的局部变量”。为啥?【英文标题】:Fixing the 'Use of unassigned local variable' with a null assignment. Why?使用空分配修复“使用未分配的局部变量”。为什么? 【发布时间】:2011-09-06 23:21:24 【问题描述】:

这样一段代码,编译器会报c.MyProperty

MyClass c;

try  throw new Exception(); 
catch (Exception)  

c.MyProperty = 2; // "Use of unassigned local variable 'c'".

但是,如果您在初始化时将 null 分配给 c,它不会报错:

MyClass c = null;

try  throw new Exception(); 
catch (Exception)  

c.MyProperty = 2; // no complains this time.

那么,为什么会这样呢?如果c 没有分配null 并且编译器假设允许它,那么c.MyProperty 不会抛出相同的异常,对象引用未设置为对象的实例

【问题讨论】:

嗯,这很有趣,我的猜测是虽然这段代码(第二版)仍然会在运行时抛出异常。这可能只是一个 Visual Studio 问题,没有获得空分配- 只是猜测? 看看***.com/questions/4770426/… 问得非常漂亮优雅的问题 【参考方案1】:

当您将null 分配给变量时,您是在告诉编译器退出,因为您比他更了解,所以他不应该抱怨这一点。

这可能是因为分配null 被认为暗示了开发人员的明确操作。

【讨论】:

虽然这让我发笑,但我仍然没有接近答案。 @Andreas:这是实际的答案,这就是允许的原因。 C# 会让你有意在脚下开枪。它只是不会让您无意这样做。 虽然我回答的方式是为了给我的观点增添一些幽默感,但我真的认为这可能是编译器停止抱怨的原因,所以它是一个有效的答案,即使它在最后不是正确的一个。 我一直认为编译器是她的。【参考方案2】:

这样想,编译器并不是告诉你它会抛出一个空引用,因此它不能编译,而是编译所需的条件之一不满足,即必须明确分配。

根据规范,null 是一个 c# 文字:“null-literal 可以隐式转换为引用类型或可空类型”

以及在分配方面:(取自规范)

引用自规范的开始

5.3.3 确定明确分配的精确规则 为了确定每个使用的变量都被明确赋值,编译器必须使用与本节中描述的过程等效的过程。

编译器处理具有一个或多个初始未分配变量的每个函数成员的主体。对于每个最初未赋值的变量 v,编译器会在函数成员中的以下每个点确定 v 的明确赋值状态:

· 在每个语句的开头

· 在每个语句的结束点(第 8.1 节)

· 在将控制权转移到另一个语句或语句的终点的每条弧上

· 在每个表达式的开头

· 在每个表达式的末尾

引用结束

因此,尽管 null 实际上并不指向内存中的对象,但它确实满足了被明确分配的要求,这就是编译器允许它的原因。

【讨论】:

【参考方案3】:

这是因为 C# 语言规范 v. 4.0 第 1.6.6.2 节“方法体和局部变量”规定如下:

方法体可以声明特定于方法调用的变量。这样的变量称为局部变量。

[跳过]

C# 需要一个局部变量明确赋值才能获得它的值。

正如 Binary Warrier 巧妙地指出的那样,这是为了避免让你在脚上开枪。

【讨论】:

【参考方案4】:

此异常的原因是您没有为变量分配默认值,例如

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);

【讨论】:

以上是关于使用空分配修复“使用未分配的局部变量”。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥此 C# 代码会引发错误:使用未分配的局部变量 'n'

“使用未分配的局部变量”错误的原因是啥? [复制]

统一使用未分配的局部变量(CS0165)光线投射[重复]

分配变量后的线性搜索

使用 SQL DataReader 中的变量 [重复]

删除数据库 mdb 表单中的表