Search code examples
c#.netref-struct

Does assigning default and null literals to a 'ref struct' have the equivalent effect?


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 structs.


Solution

  • 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.