如果要将结构传递给方法以使该方法对其进行修改,则该方法必须ref
在参数上使用限定符。如果将结构传递给不带ref
参数的方法,则该方法无法修改该结构的任何字段。
请注意,有些人可能会建议将结构替换为类,这样就不必使用ref
限定符。这是一个危险的概念,因为每个接收到对可变类对象的引用的方法都可以自由地导致该对象在此后的任何时间发生变异。没有干净的方法来传递对可变类对象的引用而不允许接收者对其进行变异,也没有任何方法可以确定给定类对象引用的代码不会持久保存它并使用它来修改在任意未来时间的对象。结构没有这些问题。
如果一个对象包含一个值类型字段,例如MyBounds
type Drawing.Rectangle
,并且我打电话给我,Foo(MyBounds)
我可以确信它不可能发生Foo
变化MyBounds
。此外,如果我打电话,Bar(ref MyBounds)
我可以预期这Bar
可能会改变MyBounds
,但所有的改变都将在方法返回之前完成。如果Rectangle
它是一个可变类类型,那么如果不进行检查Foo
,Bar
我将无法知道MyBounds
未来的任何时候是否会更改 的属性。
不了解结构体与类不同的人可能会对结构体的行为方式感到困惑,但所有具有公开公共字段的结构体的行为方式都是相同的,因此,如果了解一个这样的结构体是如何工作的,就会理解所有结构体。结构有一个邪恶的方面,即在结构上定义的实例方法和属性将this
作为ref
参数接收,但如果尝试执行以下操作:
readonly System.Drawing.Rectangle myRect = whatever;
...
myRect.Offset(4,2);
系统将识别出myRect
不能作为ref
参数传递(因为它是只读的)并且将在没有任何诊断的情况下将代码更改为:
readonly System.Drawing.Rectangle myRect = whatever;
...
System.Drawing.Rectangle temp = myRect;
temp.Offset(4,2);
然而,那里的邪恶不是Rectangle
可变的事实,而是编译器假定上述代码替换在调用任何和所有值类型方法时是合法的这一事实。除非或直到 Microsoft 开始添加一个属性以指示在只读结构上调用特定方法会导致错误而不是执行此类替换,否则对结构上操作的结构方法进行编码的唯一安全方法“in- place" 将使用类似: 的格式static void Offset(ref Rectangle it, int x, int y);
,在这种情况下Rectangle.Offset(ref myRect, 4, 2);
会失败。