Using 语句中的对象不是不可变的?
Object in Using Statement Is NOT Immutable?
在我工作的一些遗留项目中,我看到很多引用 dbContext 的 using 语句:
using (myContext dal = new myContext())
{
dal.DoSomeDatabaseThing
}
我认为这是相当标准的,没有发现问题。然而,在很多地方,我看到这样的事情:
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(...)
{
sqlBulkCopy.DestinationTableName = myTable;
sqlBulkCopy.BatchSize = 10000;
}
这么多年了,我明白using语句中引用的对象是不可变的。事实上,MSDN 文档指出,"Within the using block, the object is read-only and cannot be modified or reassigned." 尽管如此,像上面这样的代码块似乎工作得很好。
我在这里错过了什么?显然,为对象的属性赋值就是修改对象,不是吗?我和团队负责人谈过,但他似乎并不关心——如果它没有坏,就不要修理它——类似的事情。但是,这让我很生气!
有什么想法吗?
谢谢
我认为您对 USING 的解释有误,USING 只是确保其中声明的对象的边界,一旦编译器通过此语句,对象就会自动销毁,从而在 GC 发挥作用之前释放内存。
(赋值,在这种情况下引用是可以的。)
这里有一些参考:What are the uses of "using" in C#
祝你好运。
规范对 using 语句中获取的资源的只读性有如下说明:
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.
值得注意的是,正如评论中所指出的,这与局部变量本身有关,而不是它引用的对象,using
语句可能无法使其本身不可变不走极端。
假设您的 IDisposable
有一个方法,在调用时会增加一个私有字段以在处理前跟踪使用情况。该对象显然是可变的,但这种变化作为副作用被隐藏起来了。 using
是否应该尝试阻止这种情况?我强烈怀疑。在 C# 中实现不变性并不是特别容易,必须在设计类型时考虑到不可变性。即使标记字段 readonly
仅影响字段变量引用类型,仍然可以通过方法调用和设置字段或属性进行修改。
object 在 using 块中是不可变的声明有点误导,因为实际上它暗示变量是不可变的。那就是你不能将变量重新分配给另一个实例:
using (var a = new A())
{
a = new A(); // compilation error
}
但仍然允许改变实例
using (var a = new A())
{
a.Prop = someValue;
}
道理很明显。 using
语句的目的是确保实例在您指定的那一刻被释放,重新分配会否定这一点,而内部状态变化对此没有影响。
在我工作的一些遗留项目中,我看到很多引用 dbContext 的 using 语句:
using (myContext dal = new myContext())
{
dal.DoSomeDatabaseThing
}
我认为这是相当标准的,没有发现问题。然而,在很多地方,我看到这样的事情:
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(...)
{
sqlBulkCopy.DestinationTableName = myTable;
sqlBulkCopy.BatchSize = 10000;
}
这么多年了,我明白using语句中引用的对象是不可变的。事实上,MSDN 文档指出,"Within the using block, the object is read-only and cannot be modified or reassigned." 尽管如此,像上面这样的代码块似乎工作得很好。
我在这里错过了什么?显然,为对象的属性赋值就是修改对象,不是吗?我和团队负责人谈过,但他似乎并不关心——如果它没有坏,就不要修理它——类似的事情。但是,这让我很生气!
有什么想法吗? 谢谢
我认为您对 USING 的解释有误,USING 只是确保其中声明的对象的边界,一旦编译器通过此语句,对象就会自动销毁,从而在 GC 发挥作用之前释放内存。
(赋值,在这种情况下引用是可以的。)
这里有一些参考:What are the uses of "using" in C#
祝你好运。
规范对 using 语句中获取的资源的只读性有如下说明:
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.
值得注意的是,正如评论中所指出的,这与局部变量本身有关,而不是它引用的对象,using
语句可能无法使其本身不可变不走极端。
假设您的 IDisposable
有一个方法,在调用时会增加一个私有字段以在处理前跟踪使用情况。该对象显然是可变的,但这种变化作为副作用被隐藏起来了。 using
是否应该尝试阻止这种情况?我强烈怀疑。在 C# 中实现不变性并不是特别容易,必须在设计类型时考虑到不可变性。即使标记字段 readonly
仅影响字段变量引用类型,仍然可以通过方法调用和设置字段或属性进行修改。
object 在 using 块中是不可变的声明有点误导,因为实际上它暗示变量是不可变的。那就是你不能将变量重新分配给另一个实例:
using (var a = new A())
{
a = new A(); // compilation error
}
但仍然允许改变实例
using (var a = new A())
{
a.Prop = someValue;
}
道理很明显。 using
语句的目的是确保实例在您指定的那一刻被释放,重新分配会否定这一点,而内部状态变化对此没有影响。