为啥在面向 .NET Standard 的项目中可以不分配 Out 参数?

Posted

技术标签:

【中文标题】为啥在面向 .NET Standard 的项目中可以不分配 Out 参数?【英文标题】:Why an Out Parameter can be left unassigned in projects targeting .NET Standard?为什么在面向 .NET Standard 的项目中可以不分配 Out 参数? 【发布时间】:2021-02-06 16:27:46 【问题描述】:

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

private void SetOffset(out TimeSpan offset)

    return;

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

CS0177:必须在控制离开当前方法之前分配输出参数“offset”

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

问题是为什么代码在不应该编译的时候编译,而不是如何让代码编译。【参考方案2】:

这是因为如果 struct 不包含可访问字段,则认为它已分配。例如:

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 有更详细的讨论。实际上,“不包含任何字段”可能更复杂,因为您可以在链接的问题中阅读 - 在此类参考程序集中编译器可能会忽略某些字段。但最终结果是相同的 - 编译器将此结构视为不包含可访问字段并允许有问题的使用。

【讨论】:

以上是关于为啥在面向 .NET Standard 的项目中可以不分配 Out 参数?的主要内容,如果未能解决你的问题,请参考以下文章

无法在面向 .Net Standard 2.0 的项目中加载 Revit API

具有 .NET Standard 目标的 Azure 云服务经典

如何创建面向 .NET 2.0 和 .NET Standard 的库?

为啥 .NET Core 中 Enumerable.Zip() 的 2 参数重载但 .NET Standard 中没有? [关闭]

将 .NET Core 2.0 类库转换为 .NET Standard

为啥我们需要将 Swift 类标记为 `public` 或 `open` 以使其在 Objective-C 框架项目中可访问?