c#中为啥不能对using变量赋值

首先,这是语言的设计。

语言的设计指的是为了一些目的在编译阶段对语言的行为作一些约束,比如变量要在赋初始值后才能使用。这些设计通常都是为了保障运行的可靠性和代码的易维护性的。

在查询C#的语言规范(Statements)的时候可以找到:
The using statement obtains one or more resources, executes a statement, and then disposes of the resource.Using表达式的作用是获得一些“资源”,然后运行一些表达式后,释放这些资源。
using_statement : \u0026#39;using\u0026#39; \u0026#39;(\u0026#39; resource_acquisition \u0026#39;)\u0026#39; embedded_statement ;resource_acquisition : local_variable_declaration | expression ;A resource is a class or struct that implements System.IDisposable, which includes a single parameterless method named Dispose.这里声明了对于“资源”的定义就是继承了System.IDiposable接口的类或者结构。

“不可赋值”在设计文档里面写的是“只读”(Read-Only):
Local variables declared in a resource_acquisition are read-only, and must include an initializer. A compile-time error occurs if the embedded statement attempts to modify these local variables (via assignment or the ++ and -- operators) , take the address of them, or pass them as ref or out parameters.如果对资源进行赋值,会产生编译时错误。

如果你的目的是要对资源在过程中赋值,可以使用try-catch表达式。而且using表达式最终也是被替换成等价的try-catch表达式的:
A using statement is translated into three parts: acquisition, usage, and disposal. Usage of the resource is implicitly enclosed in a try statement that includes a finally clause. This finally clause disposes of the resource. If a null resource is acquired, then no call to Dispose is made, and no exception is thrown.实际上的using表达式可以视作是try-catch在特殊场景下的等价物或者语法糖,但这仅仅是实现层面的事情。在设计层面,它还是着重对“资源”的利用和释放。

要注意在描述using表达式设计的时候,这些初始化对象被称作“资源(resource)”,而不是“对象(object)”。“资源”在.NET或者运行时的语境下通常是指需要进行生命周期管理的对象,着重点在于生命周期管理。而IDisposable接口的设计是针对“非托管资源(unmanaged resources)”的。
你可以看到在语法中,初始化部分的行为被称作“资源获取/resource aquisition”,而不是“变量创建/variable creation”。
那么,为什么使用关键字“using”就好理解了,这是在“利用”资源,所以“用完就释放”是合理的使用方式。在使用资源的过程中,持有并维护资源(包括不修改/赋值),是一种合理的设计。为了配合这个设计,实际上using表达式中初始化的变量在表达式外也是无法访问的。

那么站在设计者的角度,不让“资源”被赋值也不是那么难理解了。赋值改变了资源的状态和using最初定义的资源,很多行为很难在设计上表达清楚。
比如,要是对原始资源赋值了,实际上就是把变量指向了另一个对象。那么到表达式结束的时候,到底应该释放掉原来的对象,还是现有的,还是都释放掉?如果在过程中赋值了很多次,而且这些资源来源于using表达式的外部变量,这又该怎么处理?

【c#中为啥不能对using变量赋值】 所以,using表达式中不能对其初始化的变量进行赋值,是因为这些变量被认为是“仅在表达式中有效的非托管资源”,不能被赋值的设计使得它们易于维护且提高了代码的可靠性。


推荐阅读