avoiding null reference exceptions

后端 未结 15 994
天命终不由人
天命终不由人 2020-11-28 08:50

Apparently the vast majority of errors in code are null reference exceptions. Are there any general techniques to avoid encountering null reference errors?

Unless I

15条回答
  •  遥遥无期
    2020-11-28 09:34

    Plain Code Solution

    You could always create a struct that helps catch null reference errors earlier by marking variables, properties, and parameters as "not nullable". Here's an example conceptually modeled after the way Nullable works:

    [System.Diagnostics.DebuggerNonUserCode]
    public struct NotNull where T : class
    {
        private T _value;
    
        public T Value
        {
            get
            {
                if (_value == null)
                {
                    throw new Exception("null value not allowed");
                }
    
                return _value;
            }
            set
            {
                if (value == null)
                {
                    throw new Exception("null value not allowed.");
                }
    
                _value = value;
            }
        }
    
        public static implicit operator T(NotNull notNullValue)
        {
            return notNullValue.Value;
        }
    
        public static implicit operator NotNull(T value)
        {
            return new NotNull { Value = value };
        }
    }
    

    You would use very similar to the same way you would use Nullable, except with the goal of accomplishing exactly the opposite - to not allow null. Here are some examples:

    NotNull person = null; // throws exception
    NotNull person = new Person(); // OK
    NotNull person = GetPerson(); // throws exception if GetPerson() returns null
    

    NotNull is implicitly casted to and from T so you can use it just about anywhere you need it. For example you can pass a Person object to a method that takes a NotNull:

    Person person = new Person { Name = "John" };
    WriteName(person);
    
    public static void WriteName(NotNull person)
    {
        Console.WriteLine(person.Value.Name);
    }
    

    As you can see above as with nullable you would access the underlying value through the Value property. Alternatively, you can use explicit or implicit cast, you can see an example with the return value below:

    Person person = GetPerson();
    
    public static NotNull GetPerson()
    {
        return new Person { Name = "John" };
    }
    

    Or you can even use it when the method just returns T (in this case Person) by doing a cast. For example the following code would just just like the code above:

    Person person = (NotNull)GetPerson();
    
    public static Person GetPerson()
    {
        return new Person { Name = "John" };
    }
    

    Combine with Extension

    Combine NotNull with an extension method and you can cover even more situations. Here is an example of what the extension method can look like:

    [System.Diagnostics.DebuggerNonUserCode]
    public static class NotNullExtension
    {
        public static T NotNull(this T @this) where T : class
        {
            if (@this == null)
            {
                throw new Exception("null value not allowed");
            }
    
            return @this;
        }
    }
    

    And here is an example of how it could be used:

    var person = GetPerson().NotNull();
    

    GitHub

    For your reference I made the code above available on GitHub, you can find it at:

    https://github.com/luisperezphd/NotNull

提交回复
热议问题