Consider the following ref struct
initializations:
ReadOnlySpan<char> span1 = null;
ReadOnlySpan<char> span2 = default;
Are the null
and default
literals equivalent in this context or there are some hidden quirks which dictates when to use either of those?
I've read the MS default value expressions - produce the default value article, but it hasn't shed the light on this question. I haven't been able to find anything regarding assigning null
to ref struct
s.
ReadOnlySpan<char> span2 = default;
This uses an initobj
instruction to initialize the value to default
.
ReadOnlySpan<char> span1 = null;
This is actually an implicit conversion (non-nullable structs can't normally be set to null
) because there is an implicit conversion from an array. This is declared like this in the source code:
public static implicit operator ReadOnlySpan<T>(T[]? array) => new ReadOnlySpan<T>(array);
The constructor is declared like this:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan(T[]? array)
{
if (array == null)
{
this = default;
return; // returns default
}
So it essentially comes to the same thing. Whether it would actually get inlined in the null
case is difficult to know in all cases: some quick testing on https://sharplab.io indicated not, but I suspect the difference is not noticeable except in extremely hot paths.
Note that all of this is not the same as a nullable, eg char? c = null;
because in that case initobj
is used in both cases, as Nullable<T>
is known by the compiler to have specific behaviours.