首页 > 解决方案 > Using 语句中的对象不是不可变的?

问题描述

在我工作的一些遗留项目中,我看到很多引用 dbContext 的 using 语句:

using (myContext dal = new myContext())
{
    dal.DoSomeDatabaseThing
}

我相信这是相当标准的,并且没有看到问题。然而,在很多地方,我看到这样的事情:

using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(...)
{
    sqlBulkCopy.DestinationTableName = myTable;
    sqlBulkCopy.BatchSize = 10000;
}

这么多年来,我已经明白 using 语句中引用的对象是不可变的。事实上,MSDN 文档指出,“在 using 块中,对象是只读的,不能修改或重新分配。” 尽管如此,像上面这样的代码块似乎工作得很好。

我在这里想念什么?明确地为对象的属性赋值是在修改对象,不是吗?我与团队负责人交谈,但他似乎并不关心——如果它没有坏,就不要修理它——诸如此类的事情。但是,这让我很生气!

有什么想法吗?谢谢

标签: c#using-statement

解决方案


规范对在 using 语句中获取的资源的只读性有这样的说法:

在资源获取中声明的局部变量是只读的,并且必须包含初始化程序。如果嵌入语句尝试修改这些局部变量(通过赋值或 ++ 和 -- 运算符)、获取它们的地址或将它们作为 ref 或 out 参数传递,则会发生编译时错误。

值得注意的是,正如评论中所指出的,这与局部变量本身有关,而不是它引用的对象,如果using不走极端,语句可能无法使其本身不可变。

假设您IDisposable有一个方法,该方法在调用时会增加一个私有字段以在处理之前跟踪使用情况。该对象显然是可变的,但该突变是作为副作用隐藏的。是否应该using尝试阻止这种情况?我强烈怀疑。不可变性在 C# 中并不是特别容易实现,在设计类型时必须牢记不可变。即使标记一个字段readonly只影响字段变量引用类型,仍然可以通过方法调用和设置字段或属性来修改。


推荐阅读