You are right that it is atomic, but holy kindness is a complex solution to a simple problem. If you want the structure to be long, but use links for atomic, just enter long! In fact, if you do this, you can make an atomic version of any type of structure, so let it do:
public struct SafeThing<T> where T : struct { private object boxedThing; public SafeThing(T value) { boxedThing = value; } public T Value { get { return boxedThing == null ? default(T) : (T)boxedThing; } } public static implicit operator T(SafeThing<T> value) { return value.Value; } public static implicit operator SafeThing<T>(T value) { return new SafeThing(value); } }
And you're done. Why are you doing all this with an array?
In addition, I note that in your implementation, you got explicit / implicit conversions back. A transformation must be implicit if it is lossless and does not drop. Your implicit conversion from SafeLong to long can throw, so it should not be implicit. Your explicit conversion from long to SafeLong cannot be lossless, so it can be implicit if you wanted to. As you can see, I solved the problem in my implementation by making both directions lossless and not throwing, so they are both implicit.
Note that this structure is essentially a strongly typed wrapper around the value in the box; if generic types were available in the first version of the CLR, then, of course, types with short values ββwould be implemented using a type like this, just as null value types are similarly implemented by a special generic type.
The SizeOf function always gives 4 bytes as the size of my surrogate. Does this value mean atomicity of a SafeLong-to-SafeLong copy?
Good, yes and no.
First, the "SizeOf" method does not give the size of the structure in memory; it gives the size of the structure when it is stored on a managed / unmanaged border. This does not necessarily match the size of the structure in managed memory; this is often the same, but it is not guaranteed that it will be the same. If you want to know the size of the structure in managed memory, you need to enable "unsafe" mode and use the "sizeof" operator.
Typically, a copy of a structure of size 4 will always be atomic if it is copied to a location aligned on the border of four bytes. The language specification does not guarantee that any four-byte structure will be copied atomically, although this is actually true in our implementation.
In your particular case, these four bytes are an array reference; the language specification ensures that the link is always copied atomically.