重载构造函数时如何避免NullReferenceException ?

本文关键字:NullReferenceException 何避免 构造函数 重载 | 更新日期: 2023-09-27 18:07:31

为了更好地解释我的情况,我编了一个例子

void Main()
{
    var a = new Lol(null);
}
public class Lol
{
    public Lol(string a, string b)
    {
        if(a == null || b == null)
        {
            throw new Exception();
        }
    }
    public Lol(Tuple<string, string> k)
        : this(k.Item1, k.Item2)
    {
    }
}

在这种情况下,我在第二个构造函数中得到一个NullReferenceException。是否有一种方法可以从方法内部处理它,保持相同的结构,或者我应该创建一个私有方法,并有两个构造函数调用这个方法?

重载构造函数时如何避免NullReferenceException ?

您可以将逻辑抽象为一个helper方法,并让两个构造函数都调用该helper。

public class Lol
{
    public Lol(string a, string b)
    {
        LolHelper(a, b);
    }
    public Lol(Tuple<string, string> k)
    {
        (k!=null)
            ?LolHelper(k.Item1, k.Item2)
            :LolHelper(null, null);
    }
    private void LolHelper(string a, string b)
    {
        if(a == null || b == null)
        {
            throw new Exception();
        }
    }
}

无需更改任何逻辑,您可以:

public class Lol
{
    public Lol(string a, string b)
    {
        if(a == null || b == null)
        {
            throw new Exception();
        }
    }
    public Lol(Tuple<string, string> k)
    : this(k != null ? k.Item1 : null, k != null ? k.Item2 : null)
    {
    }
}

然而,在更复杂的情况下,这可能不起作用(尽管你不应该在构造函数链中添加任何复杂的逻辑)。

首先在构造函数中不传递null。如果您希望对应于a和b的字段或属性为空,只需将其放入构造函数中,如下所示:

private string a;
private string b;
public Lol()
        {
            a= null;
            b= null;
        }

在Main()中使用:

var a = new Lol();

如果你想传递值,而不是null,使用合适的构造函数

这应该适用于VS2015和c# 6:

this(k?.Item1, k?.Item2)
最后

:

void Main()
{
    var a = new Lol(null);
}
public class Lol
{
    public Lol(string a, string b)
    {
        if(a == null || b == null)
            throw new Exception();
    }
    public Lol(Tuple<string, string> k)
        : this(k?.Item1, k?.Item2)
    {
    }
}

这是设计,您需要在第二个构造函数

中进行检查
public Lol(Tuple<string, string> k)
{
    if(k == null || k.Item1 == null || k.Item2 == null)
    {
        throw new Exception();
    }
}

我的方法是一个扩展方法:

public static class Requirements
{
    public static T NotNull<T>(this T value, string parameterName, string message)
        where T : class =>
        value ?? throw new ArgumentNullException(parameterName, message);
    public static T NotNull<T>(this T value, string parameterName)
        where T : class =>
        value ?? throw new ArgumentNullException(parameterName);
}

用法:

public class Lol
{
    public Lol(string a, string b)
    {
        if(a == null || b == null)
        {
            throw new ArgumentNullException();
        }
    }
    public Lol(Tuple<string, string> k)
        : this(k.NotNull(nameof(k)).Item1, k.NotNull(nameof(k)).Item2)
    {
    }
}