传递易失性引用类型的值

时间:2018-12-18 11:37:15

标签: c# pass-by-reference volatile pass-by-value

我没有看到与我类似的问题,所以希望我不要错过任何事情。

我很好奇在按值传递该字段时是否保留了类内字段的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工具提示可以告诉我很多。但是,如果我只是按值传递,我不会收到任何警告/通知。

有人对此有任何经验吗?谢谢,祝你愉快。

1 个答案:

答案 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);
    }
}