为什么可以在面向 .NET Standard 的项目中保留未分配的输出参数?

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

我在一个以 .NET Standard 2.0 为目标的 C# (ClassLibrary) 项目中尝试了以下代码,它编译成功,同时它在另一个以 .NET Core 3.1 为目标的项目中出错

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

.NET Core 项目中的错误符合预期:

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

是这样的: 编译器不知道它是否会被初始化,那么你需要始终初始化

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

你也可以这样做:

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
}

那是因为如果结构不包含可访问的字段,则认为它已分配。例如:

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

struct Test {
    void DoSomething() {

    }
}

在 .NET Core 3.1(和其他 .NET 版本)中编译得很好。

现在,.NET Standard 参考库中存在(是?)一个问题(这些库基本上只包含一个“存根”,当代码为 运行 时实际上使用了一个“真实”库)不包括私有字段,因此 .NET Standard 2.0 参考库中的 TimeSpan 不包含任何可访问的字段,因此被编译器视为已分配,原因与上述 Test 结构相同。更详细地讨论了此问题 here。实际上,“不包含任何字段”可能更复杂,因为正如您在链接问题中所读到的那样 - 在此类参考程序集中,编译器可能会忽略某些字段。但最终结果是一样的——编译器将此结构视为不包含可访问的字段并允许有问题的使用。