65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 6.0 中处理空引用检查的更好方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (3投票s)

2015年10月23日

CPOL

3分钟阅读

viewsIcon

18721

该技巧是关于使用 C# 6.0 中引入的 Elvis 运算符进行空引用检查。 它给出了一个如何使用它的例子。

引言

C# 6.0 引入了一个运算符,它可以使编码更简单,代码更少。 这个运算符被称为 Elvis 运算符(未正式声明),但因为它看起来像。  =>  ?.  两只眼睛和猫王的标志性发型

Elvis 运算符可用于修复 C# 中最令人恐惧的错误 System.NullReferenceException 或简称为 Object reference not set to an instance of an object。 如果在使用未分配的对象引用之前没有正确处理空引用检查,则大多数情况下会发生此问题。 空引用检查是耗时的代码,也会导致大量编程。 它们可以在将参数传递给方法、连接字符串以进行显示/消息或将其分配给局部变量之前完成。

问题陈述

让我们举一个简单的例子,我们需要显示访客详细信息。 我为此示例创建了一个控制台应用程序,但是此错误可以发生在任何使用 C# 代码的应用程序类型中。

这里 Visitor 是一个类,具有 2 个属性 

  1. Name 
  2. 联系方式 

联系方式也是一个类,具有 2 个属性

  1. 手机号码
  2. 电子邮件地址
class Visitor
{
    public string Name { get; set; }   
    public ContactDetails ContactDetails { get; set; }
}

class ContactDetails
{
    public string Mobile { get; set; }
    public string EmailAddress { get; set; }
}

现在让我们输入一个名叫 Yash 的访客,他只提供了他的手机号码

下面的代码将抛出 System.NullReferenceException 因为 ContactDetails 为 null,并且我们正在尝试使用 Visitor 对象引用 (visitorObj) 访问其属性

class Program
    {
        static void Main(string[] args)
        {
            Visitor visitorObj = new Visitor();
            visitorObj.Name = "Yash";
            visitorObj.ContactDetails = null;

           Console.WriteLine(String.Format("Name {0} Mobile No {1} Email Address {2}", visitorObj.Name, visitorObj.ContactDetails.Mobile, visitorObj.ContactDetails.EmailAddress));
            Console.ReadLine();
       
        }
    }

解决方案 1(没有 Elvis)

为了避免此错误,我们需要进行一些空引用检查。

但在那之前,让我们分析一下在程序中可能导致空引用错误的可能性有多少

所有这些条件对于此程序示例来说可能不是必需的,但是处理它们是一个好习惯,因为您可能会将代码移到不同的程序集/类中,而这时它将变得至关重要。

  1. 如果未创建访客对象,则访客对象引用 (visitorObj) 可以为 null
  2. visitorObj.Name
  3. visitorObj.ContactDetails
  4. visitorObj.ContactDetails.Mobile
  5. visitorObj.ContactDetails.EmailAddress

因此,要编写一个可以满足上述所有可能性的程序,我们需要编写多个 if-else 循环或使用三元运算符。 让我们采用混合方法来减少代码。

   class Program
    {
        static void Main(string[] args)
        {
            Visitor visitorObj = new Visitor();
            visitorObj.Name = "Yash";
            visitorObj.ContactDetails = null;

            if(visitorObj != null)
            Console.WriteLine(String.Format("Name {0} Mobile No {1} Email Address {2}", 
visitorObj.Name!=null?visitorObj.Name:null, 
visitorObj.ContactDetails != null ? visitorObj.ContactDetails.Mobile !=null? visitorObj.ContactDetails.Mobile :null: null,
                visitorObj.ContactDetails != null ? visitorObj.ContactDetails.EmailAddress != null ? visitorObj.ContactDetails.EmailAddress : null : null));
            else
            Console.WriteLine("The object is not created");

            Console.ReadLine();
           
        }
    }

但是您可以看到由于嵌套的三元条件,上面的代码变得多么复杂。

解决方案 2(使用 Elvis)

所以让我们看看 Elvis 运算符将如何帮助我们

?. 运算符将首先将运算符的左侧与 null 进行比较,如果不是,则获取运算符的右侧

例如 val = x?.y 意味着

    if(x!=null){  
        val=x.y; }
    else val = null;

或者

    val = (x!=null)?x.y:null ;

因此,当我们替换 Elvis 运算符时,我们得到以下内容:-

            Visitor visitorObj = new Visitor();
            visitorObj.Name = "Yash";
            visitorObj.ContactDetails = null;

            Console.WriteLine(String.Format("Name {0} Mobile No {1} Email Address {2}", visitorObj?.Name, visitorObj?.ContactDetails?.Mobile, visitorObj?.ContactDetails?.EmailAddress));
            Console.ReadLine();

这里 string x = visitorObj?.ContactDetails?.Mobile 意味着 

if(visitorObj!=null && ContactDetails !=null) 
string x = visitorObj.ContactDetails.Mobile;
   
 or

string x =(visitorObj != null)?(ContactDetails !=null)?ContactDetails.Mobile:null:null;
 

上面的代码更清晰且易于实现,并且它正在处理应用程序中的所有空引用检查。 Elvis 运算符可以非常有用和方便,以避免大多数空引用检查错误。 Elvis 运算符的局限性在于,当运算符的左侧为 null 时,它将分配“null”作为默认值。 并且它没有像 if-else 那样的灵活性,您可以在 else 部分也编写代码。

Coding is Simple

 

© . All rights reserved.