检查C#中的对象是否为null

时间:2011-06-20 21:40:36

标签: c# null nullreferenceexception

如果对象为null,我想阻止对象的进一步处理。

在下面的代码中,我通过以下方式检查对象是否为空:

if (!data.Equals(null))

if (data != null)

但是,我在NullReferenceException收到了dataList.Add(data)。如果对象为null,则它应该永远不会输入if - 语句!

因此,我问这是否是检查对象是否为空的正确方法:

public List<Object> dataList;
public  bool AddData(ref Object data)
    bool success = false;
    try
    {
        // I've also used "if (data != null)" which hasn't worked either
        if (!data.Equals(null))
        {
           //NullReferenceException occurs here ...
           dataList.Add(data);
           success = doOtherStuff(data);
        }
    }
    catch (Exception e)
    {
        throw new Exception(e.ToString());
    }
    return success;
}

如果这是检查对象是否为空的正确方法,我做错了什么(如何防止对象进一步处理以避免NullReferenceException)?

21 个答案:

答案 0 :(得分:223)

data不是null,而是dataList

您需要使用

创建一个
public List<Object> dataList = new List<Object>();

更好:因为它是一个字段,所以请private。如果没有什么可以阻止你的话,也可以readonly。只是好习惯。

<强>除了

检查无效的正确方法是if(data != null)。对于参考类型,这种检查无处不在;在检查无效时,偶数Nullable<T>会覆盖等于运算符,以便更方便地表达nullable.HasValue

如果您执行if(!data.Equals(null)),则会NullReferenceException data == null。这是一种滑稽的,因为首先避免这种例外是目标。

你也是这样做的:

catch (Exception e)
{
    throw new Exception(e.ToString());
}

这绝对不是好事。我可以想象你把它放在那里只是为了你可以在方法内部进入调试器,在这种情况下忽略这一段。否则,不要抓住异常。如果你这样做,只需使用throw;重新抛出它们。

答案 1 :(得分:46)

C#6有monadic null checking:)

之前:

if (points != null) {
    var next = points.FirstOrDefault();
    if (next != null && next.X != null) return next.X;
}   
return -1;

后:

var bestValue = points?.FirstOrDefault()?.X ?? -1;

答案 2 :(得分:27)

您的dataList为null,因为它尚未实例化,根据您发布的代码判断。

尝试:

public List<Object> dataList = new List<Object>();
public  bool AddData(ref Object data)
bool success = false;
try
{
    if (!data.Equals(null))   // I've also used if(data != null) which hasn't worked either
    {
       dataList.Add(data);                      //NullReferenceException occurs here
       success = doOtherStuff(data);
    }
}
catch (Exception e)
{
    throw new Exception(e.ToString());
}
return success;

}

答案 3 :(得分:20)

在C#7中,最好的是

import { Injectable } from '@angular/core'; import { AdMobFree, AdMobFreeBannerConfig } from '@ionic-native/admob-free'; @Injectable() export class AdsProvider { constructor(public admob: AdMobFree) { } showAd(){ const bannerConfig: AdMobFreeBannerConfig = { id: '', isTesting: false, autoShow: true, bannerAtTop: false }; this.admob.banner.config(bannerConfig); this.admob.banner.prepare().then((res) => { console.log('Admob status: '+res); }, (err) => { console.log(err); }); } ...

这将忽略对象定义的任何==或!=(除非您当然要使用它们...)

如果不相等,您可以if (obj is null)(丑陋)

答案 4 :(得分:17)

[编辑反映@ kelton52的提示]

最简单的方法是object.ReferenceEquals(null, data)

由于(null==data)无法保证正常工作:

class Nully
{
    public static bool operator ==(Nully n, object o)
    {
        Console.WriteLine("Comparing '" + n + "' with '" + o + "'");
        return true;
    }
    public static bool operator !=(Nully n, object o) { return !(n==o); }
}
void Main()
{
    var data = new Nully();
    Console.WriteLine(null == data);
    Console.WriteLine(object.ReferenceEquals(null, data));
}

产地:

  

比较''与'Nully'

     

     

答案 5 :(得分:9)

不,你应该使用!=。如果data实际上为空,则由于尝试在NullReferenceException上调用Equals方法,您的程序将因null而崩溃。还要意识到,如果您特别想要检查引用相等性,那么您应该使用Object.ReferenceEquals方法,因为您永远不知道Equals是如何实现的。

您的程序崩溃,因为dataList为空,因为您从未初始化它。

答案 6 :(得分:7)

C# 9开始,您可以

if (obj is null) { ... }

非空使用

if (obj is not null) { ... }

如果您需要覆盖此行为,请分别使用==!=

答案 7 :(得分:6)

这种情况下的问题不是data为空。这是dataList本身为空。

在您声明dataList的地方,您应该创建一个新的List对象并将其分配给变量。

List<object> dataList = new List<object>();

答案 8 :(得分:5)

除了@Jose Ortega回答, 它更适合使用extension method

 public static bool IsNull(this object T)
     {
        return T == null;
     } 

对所有对象使用IsNull方法,如:

object foo = new object(); //or any object from any class
if (foo.IsNull())
   {
     // blah blah //
   }

答案 9 :(得分:5)

C# 8开始,您可以使用“空”属性模式(与pattern matching一起使用)以确保对象为 not null:

if (obj is { })
{
    // 'obj' is not null here
}

这种方法的意思是“ 如果对象引用某事物的实例”(即它不为空)。

您可以认为这与if (obj is null)...相反。当对象未引用某事物的实例时,它将返回true。

有关C#8.0中的模式的更多信息,请阅读here

答案 10 :(得分:3)

  public static bool isnull(object T)
  {
      return T == null ? true : false;
  }

使用:

isnull(object.check.it)

有条件使用:

isnull(object.check.it) ? DoWhenItsTrue : DoWhenItsFalse;

更新(另一种方式)更新于08/31/2017。感谢您的评论。

public static bool isnull(object T)
{
    return T ? true : false;
}

答案 11 :(得分:2)

Jeffrey L Whitledge是对的。你的`dataList'-Object本身是空的。

您的代码还有另一个问题:您正在使用ref-keyword,这意味着参数数据不能为空! MSDN说:

  

必须首先初始化传递给ref参数的参数。这与out不同,其参数在传递之前不必显式初始化

使用类型为“Object”的泛型也不是一个好主意。泛型应避免装箱/拆箱,并确保类型安全。如果你想要一个普通的类型,你的方法是通用的。最后,您的代码应如下所示:

public class Foo<T> where T : MyTypeOrInterface {

      public List<T> dataList = new List<T>();

      public bool AddData(ref T data) {
        bool success = false;
        try {
          dataList.Add(data);                   
          success = doOtherStuff(data);
        } catch (Exception e) {
          throw new Exception(e.ToString());
        }
        return success;
      }

      private bool doOtherStuff(T data) {
        //...
      }
    }

答案 12 :(得分:2)

正如其他人已经指出的那样,它不是data,而是可能dataList null。除此之外......

catch - throw是一个反模式,几乎总是让我每次看到它都想要呕吐。想象一下doOtherStuff()调用的东西出了问题。你得到的只是一个Exception对象,在throw AddData()处抛出。没有堆栈跟踪,没有调用信息,没有状态,没有任何东西可以指示问题的真正根源,除非你进入并切换调试器以在异常抛出时中断,而不是异常未处理。如果您正在捕获异常并且以任何方式重新抛出 ,特别是如果try块中的代码以任何方式都是非常重要的话,请自己(以及您的同事,现在和将来)一个忙并抛弃整个try - catch块。当然,throw;比替代方案更好,但你仍然给自己(或者其他任何人试图修复代码中的错误)完全不必要的麻烦。这并不是说try-catch-throw本身就是邪恶的,只要你做一些与catch块中抛出的异常对象相关的东西。

然后首先捕获Exception存在潜在问题,但这是另一回事,特别是因为在这种特殊情况下你会抛出异常。

另一件令我印象深刻的事情是,data可能会在执行函数期间改变值,因为您通过引用传递。因此,null检查可能会通过,但在代码对值进行任何操作之前,它已更改 - 可能更改为null。如果这是一个问题或者不是(可能不是),我不肯定,但似乎值得关注。

答案 13 :(得分:1)

无论何时创建类的对象,都必须使用以下代码检查对象是否为null。

实施例: object1是类

的对象
void myFunction(object1)
{
  if(object1!=null)
  {
     object1.value1 //If we miss the null check then here we get the Null Reference exception
  }
}

答案 14 :(得分:1)

使用c#9(2020),您现在可以使用以下代码检查参数是否为空:

if (name is null) { }

if (name is not null) { }

您可以获取更多信息here

答案 15 :(得分:0)

我做得更简单(肯定的方式),而且看起来效果很好。

由于任何一种“对象”至少都是一个对象


    if (MyObj is Object)
    {
            //Do something .... for example:  
            if (MyObj is Button)
                MyObj.Enabled = true;
    }

答案 16 :(得分:0)

我只是遵循了通常在Java脚本中遵循的方法。将对象转换为字符串,然后检查它们是否为空。

var obj = new Object();
var objStr = obj.ToString();
if (!string.IsNullOrEmpty(objStr)){
  // code as per your needs
}

答案 17 :(得分:0)

您可以尝试以下操作

public List<Object> dataList;
public  bool AddData(ref Object data)
bool success = false;
try
{
    if (data != null)
    {
       dataList.Add(data);
       success = doOtherStuff(data);
    }
}
catch (Exception e)
{
    throw new Exception(e.ToString());
}
return success;

}

答案 18 :(得分:0)

以下是我使用的一些扩展:

/// <summary>
/// Extensions to the object class
/// </summary>
public static class ObjectExtensions
{
    /// <summary>
    /// True if the object is null, else false
    /// </summary>
    public static bool IsNull(this object input) => input is null;

    /// <summary>
    /// False if the object is null, else true
    /// </summary>
    public static bool NotNull(this object input) => !IsNull(input);
}

答案 19 :(得分:0)

您不能在空对象上使用 ToString(),因此使用 Null Coalescing Operator 将空字符串分配给空对象,然后使用 IsNullOrEmpty 进行评估

        var foo = obj ?? "";

        if (!String.IsNullOrEmpty(foo.ToString()))
        {
          //Do something
        }

编辑

或者更简洁的方法,正如@EKW 指出的那样,删除变量赋值并改为这样做:

!String.IsNullOrWhitespace(obj?.ToString())

答案 20 :(得分:-1)

public bool IsVisible(object ClaimCount)
    {
        bool flag = true;
        #region || HIDE COLUMNS ON CONDITION BASIS
        if (!String.IsNullOrEmpty(Convert.ToString(ClaimCount)))
        {
            Int32 ClaimCnt = Convert.ToInt32(ClaimCount);
            if (ClaimCnt == 1)
            {
                flag = false;
            }
        }
        #endregion
        return flag;
    }