在C#6索引初始值设定项中使用C#8允许空值的运算符

时间:2019-09-28 15:49:14

标签: c# c#-8.0 collection-initializer nullable-reference-types

使用索引初始值设定项填充字典而不在此之前重新创建字典时,是否可以选择在某个地方指定允许空值的运算符?

示例:

public class Program
{
    public IDictionary<string, string>? NullableDictionary { get; set; }
       = new Dictionary<string, string>();

    public static void Main(string[] args)
    {
        new Program
        {
            NullableDictionary =
            {
                ["key"] = "value"
            }
        };
    }
}

我知道这种用例(在索引初始化new Dictionary<string, string>之前不重新创建{ [...] = ... })可能不是很常见。 但是我仍然想知道是否有一种解决方案可以防止在上述情况下出现此编译器警告:

  

[CS8602]取消引用可能为空的引用。

我可以想象使用像这样的null宽容运算符:

new Program
{
    NullableDictionary! =
    {
        ["key"] = "value"
    }
};

1 个答案:

答案 0 :(得分:1)

  

我仍然想知道是否有解决方案来防止此编译器警告

除了显而易见的#pragma方法之外,我认为您的意思是:

#pragma warning disable 8602
    new Program
    {
        NullableDictionary = { ["key"] = "value" }
    };
#pragma warning restore

显然可以。或者,当然是上述“空引用类型”的特定版本:

#nullable disable
    new Program
    {
        NullableDictionary = { ["key"] = "value" }
    };
#nullable restore

这两种方法都暂时并明确禁用了相关警告。可以为null的运算符实际上会执行此操作,当然,仅适用于它所应用的特定表达式。

无论好坏,我认为没有一种方法可以完全按照您的意愿进行。通常,仅在实际变量声明中才允许使用collection-initializer语法。根据场景的相似性,在对象初始化器语法上下文中使用该语言是一种特殊情况,即使所生成的代码与实际的变量初始化(尤其是您要在其中实际上是在初始化集合的同时初始化变量的值。

因此,当编译器处理集合初始值设定项语法时,编译器必须继续进行的工作是,它正在生成对Add()方法的调用,并且正在进行这些调用根据您之前的声明,该值可能为空。

所有这些,我发现您尝试使用那里的null宽容运算符是非常明智的。如果编译器通过在生成的每个Add()调用中包含该运算符,来解释该运算符在该上下文中的用法,那将是很好的。

您甚至可以针对该语言提出Git问题,并要求将其添加为功能。我认为,这不会是一个重大变化,因为该语法目前只是完全非法的,并且在不使用该语法时允许它不会改变编译器的行为。