我没有看到与我类似的问题,所以希望我不要错过任何事情。
我很好奇在按值传递该字段时是否保留了类内字段的volatile
属性(这意味着将创建指向初始对象的本地副本引用)。
VS警告几乎可以告诉我,通过引用volatile
字段传递并不能保持其波动性。但是我想知道按值传递是否确实保留了volatile
属性。
说明问题的代码示例:
class static Singleton
{
private static volatile MyObject myObject;
private static readonly object syncRoot = new object();
public static MyObject My => HandleObject(syncRoot, myObject);
private void HandleObject(object syncRoot, MyObject myObject)
{
if(myObject.SomeProperty) //is the myObject reference still volatile?
{ /* some other code */ }
}
}
如上所述,我的问题是myObject
方法内的volatile
参考副本是否仍然是HandleObject
?
我知道,如果将HandleObject
的签名更改为void HandleObject(object syncRoot, ref MyObject myObject)
,我会失去波动性,因为VS工具提示可以告诉我很多。但是,如果我只是按值传递,我不会收到任何警告/通知。
有人对此有任何经验吗?谢谢,祝你愉快。
答案 0 :(得分:2)
请注意,当您在参考数据类型(即对象)上应用volatile
关键字时,它仅仅会影响保留对该对象的引用的变量(例如非指针OOP语言中的“指针” ),而不是该对象内部的内容。
因此,当您将引用变量的按值传递给方法时,它的内容(对象的地址)将被复制,并且无需将波动性属性保留在复制的值上,因为它不会影响要复制的实际变量。
另一方面,如果将对引用变量的引用传递给方法,则该方法能够更改实际传递的引用,这可能会破坏编译器警告您的波动性。
请看下面的代码以更好地理解。
class SomeClass {
private volatile Object myObject = new Object();
private void HandleObject(Object theObject) {
// The `theObject` argument is a copy of the passed variable
// and the following line won't change the actual variable's
// value, but the local instance.
theObject = new Object();
}
private void HandleObjectRef(ref Object theObject) {
// The actual variable's value will be changed, when the
// following line is executed.
theObject = new Object();
}
public void DoSomething() {
// This call is safe, the `myObject` variable won't be
// changed after when `HandleObject` is executed.
this.HandleObject(myObject);
// The `myObject` will be changed after when `HandleObjectRef`
// is executed. (WARNING)
this.HandleObjectRef(ref myObject);
}
}