9

寻找一些最佳实践指导。假设我有这样一行代码:

Color color = someOrder.Customer.LastOrder.Product.Color;

其中 Customer、LastOrder、Product 和 Color 可能null处于正常条件下。但是,如果路径中的任何一个对象为空,我希望颜色为空;为了避免空引用异常,我需要检查每个对象的空条件,例如

Color color = someOrder == null ||
              someOrder.Customer == null || 
              someOrder.Customer.LastOrder == null ||
              someOrder.Customer.Product == null ? 
              null : someOrder.Customer.LastOrder.Product.Color;

或者我可以这样做

Color color = null;
try {color = someOrder.Customer.LastOrder.Product.Color}
catch (NullReferenceException) {}

第一种方法显然有效,但编码似乎有点乏味且难以阅读。第二种方法更容易一些,但为此使用异常处理可能不是一个好主意。

是否有另一种检查空值并在必要时将空值分配给颜色的快捷方式?或者关于在使用此类嵌套引用时如何避免 NullReferenceExceptions 的任何想法?

4

6 回答 6

13

您正在寻找 null 安全取消引用运算符。

Color color = someOrder?.Customer?.LastOrder?.Product?.Color;

不幸的是,C# 不支持它。也许稍后会添加它,但目前没有计划这样做。

有关的

于 2012-04-28T08:27:40.220 回答
2

最佳做法是遵循得墨忒耳法则,听起来是:不要与陌生人交谈。即对象应避免调用由另一个方法返回的成员对象的方法。这允许编写更少耦合、更易维护和可读的代码。

所以,避免使用“火车残骸”之类的someOrder.Customer.LastOrder.Product.Color,因为它们完全违反了得墨忒耳法则。甚至很难理解这段代码有什么商业意义。为什么你会得到其他订单产品的颜色,而不是当前订单?

移除火车残骸的可能方法 - 将功能推向更接近有趣的残骸末端。在您的情况下,还可以考虑将最后一个产品传递给您的方法,而不是使用一些订单。

于 2012-04-28T09:50:37.477 回答
1

你需要在哪里实现这一点。

用法

Color color = someOrder.ComplexGet(x => x.Customer.LastOrder.Product.Color);

或者

Color color = Complex.Get(() => someOrder.Customer.LastOrder.Product.Color);

助手类实现

public static class Complex
{
    public static T1 ComplexGet<T1, T2>(this T2 root, Func<T2, T1> func)
    {
        return Get(() => func(root));
    }

    public static T Get<T>(Func<T> func)
    {
        try
        {
            return func();
        }
        catch (Exception)
        {
            return default(T);
        }
    }
}
于 2014-03-31T09:58:15.277 回答
0

我肯定更喜欢第一种方法......第二种方法利用程序流的异常机制,恕我直言,这是不好的做法......

AFAIK 在 C# 中没有快捷方式或“空安全解除引用运算符”。

于 2012-04-28T08:29:13.117 回答
0

定义访问嵌套属性的唯一方法。例如像这样

private Customoer GetCustomer(Order order)
{
  return order != null ? order.Customer : null;
}

private Order GetLastOrder(Customer customer)
{
   return customer != null ? customer.LastOrder : null;
}

使用定义的方法在应用程序中访问您的属性

于 2012-04-28T08:50:11.930 回答
0

您还可以在 if 语句中使用 Null 条件运算符。如果有很多嵌套值,它真的很有用。

例子:

public class DummyDto
{
    public string Name { get; set; }

    public DummyDto Parent { get; set; }
}

class Program
{
    static void Main(string[] args)
    {

        var dummyDto = new DummyDto();

        //Both if statements will be true below
        if(dummyDto.Parent?.Name == null)
        {
            Console.WriteLine("DummyDto is null");
        }

        if (dummyDto.Parent == null || dummyDto.Parent.Name == null)
        {
            Console.WriteLine("DummyDto is null");
        }
    }
}
于 2020-01-14T15:17:52.177 回答