Why an Out Parameter can be left unassigned in projects targeting .NET Standard?

172 views Asked by At

I tried the below code in a C# (ClassLibrary) project that targets .NET Standard 2.0 and it compiles successfully, meanwhile it gives an error in another project targeting .NET Core 3.1

private void SetOffset(out TimeSpan offset)
{
    return;
}

The error in .NET Core project is as expected:

CS0177: The out parameter 'offset' must be assigned to before control leaves the current method

2

There are 2 answers

0
Evk On BEST ANSWER

That's because if struct contains no accessible fields, it is considered assigned. For example:

private void SetOffset(out Test offset)
{
    return;
}

struct Test {
    void DoSomething() {

    }
}

Compiles just fine in .NET Core 3.1 (and other .NET versions).

Now, there was (is?) an issue in .NET Standard reference libraries (those libraries basically only contain a "stub" and a "real" library is actually used when code is run) that private fields were not included, so TimeSpan in .NET Standard 2.0 reference library doesn't contain any accessible fields, and so is considered assigned by compiler by the same reason as Test struct above. This issue is discussed in more details here. Actually it might be more complicated that "doesn't contain any fields", because as you can read in the linked issue - some fields might be ignored by compiler in such reference assembly. But in the end result is the same - compiler treats this structure as containing no accessible fields and allows the usage in question.

1
RC0D3 On

Is like this: The compiler can't know if is will be initialized, then you need initialize always

private void SetOffset(out TimeSpan offset)
{
        offset = new TimeSpan(); //reset all the timespan
}

You can do sth like this too:

private void SetOffset(out TimeSpan offset)
{
        DateTime date1 = new DateTime(2010, 1, 1, 8, 0, 15);
        DateTime date2 = new DateTime(2010, 8, 18, 13, 30, 30);
        offset = date1 - date2; //offset.Days will be -229 an will be passed a initialized timespan by minus
}