0
votes

I have a question for C# 8 nullable reference type in a static class. Here is my original code.

    public static class Foo
    {
        private static IFactory _factory;

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

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

Now I have a warning

private static IFactory _factory; //Non-nullable field is uninitialized. Consider declaring the field as nullable.

Which is correct, as without calling the Init(), _factory will be null. But I will call Init() at the very beginning of the program.

So I make it nullable private static IResultFactory? _factory; and the warning is gone. But I got one more warning

public static string GetVersion() => _factory.GetVersion(); //Dereference of a possibly null reference.

Here I know that by the time I got here it will not be null, any elegant way other than the ! (null-forgiving) operator?

Or is there something else I am missing to solve this gratefully?

Update: I know for a method there are some tips and tricks, for example:

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

Here it's saying the return will not be null, just to get rid of the warning. I'm wondering is there something similar to this.

1
My first though is using null object pattern or static constructor. Also I must say this is kind of like a service locator and I don't like to use static class like this.Leisen Chang
@LeisenChang Can you pls explain more about what is null object pattern?Andy Song
Why not live with the second warning? You say that you will always call Init at the start of the program... this means there will be an exception thrown if you do not, which is probably what you want. The exception is telling you that something is not correct and so it cannot continue executing.dodgy_coder
Your initialization isn't threadsafe so it's already problematic. You should use a static constructor, as already suggested, or System.Lazy<IFactory>Aluan Haddad

1 Answers

2
votes

First I think it's possible to use null object pattern:

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;
    }
}

If IFactory is not necessarily passed from outside, you can also consider static constructor.

public static class Foo
{
    private static IFactory _factory;

    static Foo()
    {
        _factory = new Factory();
    }

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

But after all I don't like to use static class except for extension method. I'd recommend to assign IFactory to whatever class need it.