c#静态类中的8个可为空的引用类型

Posted

技术标签:

【中文标题】c#静态类中的8个可为空的引用类型【英文标题】:c# 8 nullable reference types in static class 【发布时间】:2020-03-23 15:51:00 【问题描述】:

我对静态类中的 C# 8 可空引用类型有疑问。这是我的原始代码。

    public static class Foo
    
        private static IFactory _factory;

        public static void Init(IFactory factory) => _factory = factory;

        public static string GetVersion() => _factory.GetVersion();
    

现在我有一个警告

私有静态 IFactory _factory; //非空字段未初始化。考虑将该字段声明为可为空。

这是正确的,因为不调用Init()_factory 将是null。但我会在程序一开始就打电话给Init()

所以我将其设为可空 private static IResultFactory? _factory; 并且警告消失了。 但我又收到了一个警告

公共静态字符串 GetVersion() => _factory.GetVersion(); //取消引用可能为空的引用。

在这里我知道,当我到达这里时,它不会是null,除了! (null-forgiving) operator之外还有其他优雅的方式吗?

或者我还缺少什么来解决这个问题?

更新:我知道一个方法有一些技巧和窍门,例如:

internal static T NotNull<T>([NotNull] this T? value) where T : class =>
            value ?? throw new ArgumentNullException(nameof(value));

这里是说返回不会是null,只是为了摆脱警告。 我想知道有没有类似的东西。

【问题讨论】:

我的第一个想法是使用空对象模式或静态构造函数。另外我必须说这有点像服务定位器,我不喜欢这样使用静态类。 @LeisenChang 你能解释一下什么是空对象模式吗? 为什么不接受第二个警告呢?您说您将始终在程序开始时调用 Init ......这意味着如果您不这样做,将会抛出异常,这可能是您想要的。异常告诉您某些内容不正确,因此无法继续执行。 你的初始化不是线程安全的,所以它已经有问题了。正如已经建议的那样,您应该使用静态构造函数,或者System.Lazy&lt;IFactory&gt; 【参考方案1】:

首先我认为可以使用空对象模式:

public static class Foo

    private static IFactory _factory = new NullFactory();

    public static void Init( IFactory factory ) => _factory = factory;

    public static string GetVersion() => _factory.GetVersion();


public interface IFactory

    string GetVersion();


public class NullFactory : IFactory

    public string GetVersion()
    
        return string.Empty;
    

如果IFactory不一定是从外部传入,也可以考虑静态构造函数。

public static class Foo

    private static IFactory _factory;

    static Foo()
    
        _factory = new Factory();
    

    public static string GetVersion() => _factory.GetVersion();

但毕竟我不喜欢使用静态类,除了扩展方法。我建议将 IFactory 分配给任何需要它的类。

【讨论】:

以上是关于c#静态类中的8个可为空的引用类型的主要内容,如果未能解决你的问题,请参考以下文章

C# 8.0 和可为空引用类型

C# 8 中的 Non-Nullable 引用类型的默认值是多少?

.NET 使用可为空的引用类型实现 IEnumerator

C# 8 中的不可为空的引用类型在运行时可以为空吗?

C#中的?和??的用法

如何识别泛型类型的可为空引用类型?