Eche un vistazo al siguiente ejemplo:
struct MyStruct { private volatile int _field; public void Set(int v) => _field = v; } class MyClass { private MyStruct _myStruct; // is it same as _myStruct.Set(0)? public void SomeMethod() => _myStruct = new MyStruct(); }Básicamente, la pregunta es si reasignar toda la estructura con un campo volátil dentro usa la misma semántica volátil que asignar el campo directamente.
El prefijo volatile se implementa mediante un atributo del compilador modreq , y el compilador solo lo aplica si el acceso se realiza directamente a través del campo marcado como volatile .
La especificación ECMA-335 en realidad no tiene ningún atributo volatile para los campos como tales, y CLR no impone el acceso volátil a dicho campo, por lo que depende del compilador emitir un volatile. prefijo en el IL generado. Solo hace esto si accede directamente al campo.
Puede ver esto fácilmente descompilando el siguiente código
public class C { static s s1; static s s2; public void M() { s1 = new s(); s2 = s1; s2.i = s1.i; } } struct s{ public volatile int i; } .class public auto ansi beforefieldinit C extends [System.Private.CoreLib]System.Object { // Fields .field private static valuetype s s1 .field private static valuetype s s2 // Methods .method public hidebysig instance void M () cil managed { // Method begins at RVA 0x2050 // Code size 47 (0x2f) .maxstack 8 IL_0000: nop IL_0001: ldsflda valuetype s C::s1 IL_0006: initobj s IL_000c: ldsfld valuetype s C::s1 IL_0011: stsfld valuetype s C::s2 IL_0016: ldsflda valuetype s C::s2 IL_001b: ldsflda valuetype s C::s1 IL_0020: volatile. IL_0022: ldfld int32 modreq([System.Private.CoreLib]System.Runtime.CompilerServices.IsVolatile) s::i IL_0027: volatile. IL_0029: stfld int32 modreq([System.Private.CoreLib]System.Runtime.CompilerServices.IsVolatile) s::i IL_002e: ret } // end of method C::M .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { // Method begins at RVA 0x2080 // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method C::.ctor } // end of class C .class private sequential ansi sealed beforefieldinit s extends [System.Private.CoreLib]System.ValueType { // Fields .field public int32 modreq([System.Private.CoreLib]System.Runtime.CompilerServices.IsVolatile) i } // end of class s