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

Checking if an object is null in C#

提问人:developer 提问时间:6/21/2011 最后编辑:Peter Mortensendeveloper 更新时间:9/11/2023 访问量:1265785

问:

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

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

if (!data.Equals(null))

if (data != null)

但是,我收到一个 at .如果对象为 null,它甚至不应该输入 -语句!NullReferenceExceptiondataList.Add(data)if

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

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;
}

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

C# nullReferenceException

评论

15赞 Nix 6/21/2011
您还应该使用与throw e;throw new Exception(e.ToString());
23赞 Kyle Trauberman 6/21/2011
在 C# 中,应始终在 null 检查中使用。 如果对象为 null,将始终引发异常。!= null.Equals
58赞 Jon 6/21/2011
@Nix:也好不到哪里去。另一方面。。。throw e;throw;
4赞 Jon 6/21/2011
@developer:将生成一个字符串,该字符串不仅包含错误消息,还包含所有错误消息和堆栈跟踪。所以这是一个非常胖的异常消息。如果您(正确地!)想要保留此信息,并保留其所属的位置,请简单地使用 .e.ToString()InnerExceptionsthrow;
24赞 David Peterson 2/24/2014
try/catch 目前不执行任何操作。每个人都在说只使用“throw”,但如果你没有做任何事情,而是重新抛出它,为什么还要有一个try/catch块呢?通常,您会捕获异常以优雅地处理它们,清理资源(最好使用“finally”子句)或在重新引发异常之前执行某种日志记录。这些都不会在此代码中发生,因此根本不需要 try/catch。

答:

28赞 glosrob 6/21/2011 #1

你的 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;
    }
    return success;
}

评论

3赞 DaveShaw 6/21/2011
另外,只需补充一点,如果数据为 null,它不会崩溃,您可以将 null 添加到 List<Object>。
8赞 glosrob 6/21/2011
但是试图做.等于 null 将引发异常。应该做 != null
0赞 developer 6/21/2011
@glosrob: 啊!!真是疏忽大意!我以为NullReferenceException来自对象。.不是名单!我是 c# 的新手,我认为在 c# 中有一种特殊的方法来检查 null!
0赞 DaveShaw 6/21/2011
那也是,但我看到 Ed S. 已经覆盖了它。
1赞 developer 6/21/2011
@DaveShaw:谢谢你的提醒。不过,我想避免添加 null 对象以供以后处理,因此我仍然会进行检查。:)
290赞 Jon 6/21/2011 #2

不是那样,而是.datanulldataList

您需要创建一个

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

更好的是:既然它是一个领域,那就让它.如果没有什么能阻止你,那就让它也成为.只是好的做法。privatereadonly

旁白

检查无效的正确方法是 。这种检查对于引用类型是无处不在的;甚至会覆盖相等运算符,以便在检查无效时成为更方便的表达方式。if(data != null)Nullable<T>nullable.HasValue

如果你这样做,那么你会得到一个 if .这有点滑稽,因为避免这个例外是首先的目标。if(!data.Equals(null))NullReferenceExceptiondata == null

您也在这样做:

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

这绝对不好。我可以想象你把它放在那里只是为了让你可以在方法内部闯入调试器,在这种情况下,忽略这一段。否则,不要无缘无故地捕获异常。如果你这样做了,只需使用 .throw;

评论

7赞 Luca 7/8/2011
为此,我还看到了 Object.ReferenceEquals(obj, null)。是为了避免平等覆盖吗?
2赞 Svish 10/25/2011
@LucaPiccioni我在使用泛型时用它来防止值类型抱怨: geekality.net/2009/11/13/generics-and-checking-for-null
5赞 jpmc26 6/28/2014
我更喜欢.将常量放在首位会将骨头错别字变成编译器错误,而不是无意的赋值。(也适用于 。null != datanull = data==
9赞 Jon 6/30/2014
@jpmc26:在 C# 中,编译时已经存在错误,因此即使花了几十年的时间才达到这个目标,我们也不需要再提防了。即使是 C++ 编译器也很容易生成有关该代码可能意外分配的警告。if (data = null)
1赞 Flater 5/4/2018
只是为了扩展你的答案:每当你看到一个 时,你通常会看到对象后面跟着一个 .以此为经验法则,很明显,例外只能是 。比较;对于 ,问题可能位于 或 。(脚注:我没有看到这是一个 7 年的死灵柱。对不起)NullReferenceExceptionnull.datalist.Add(data)datalistdatalist.Add(data.Value)datalistdata
7赞 Jeffrey L Whitledge 6/21/2011 #3

在这种情况下,问题不在于 null。它本身就是空的。datadataList

在声明的位置,您应该创建一个新对象并将其分配给变量。dataListList

List<object> dataList = new List<object>();
10赞 Ed S. 6/21/2011 #4

不,您应该使用 .如果实际上为 null,则由于尝试调用 上的方法,您的程序将崩溃并显示 。还要注意,如果你特别想检查引用是否相等,你应该使用该方法,因为你永远不知道是如何实现的。!=dataNullReferenceExceptionEqualsnullObject.ReferenceEqualsEquals

您的程序正在崩溃,因为您从未初始化它,因此为 null。dataList

2赞 DiableNoir 6/21/2011 #5

杰弗里·惠特利奇(Jeffrey L Whitledge)是对的。你的 'dataList'-Object 本身是 null。

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

必须首先初始化传递给 ref 参数的参数。这与 out 不同,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) {
        //...
      }
    }
2赞 user 6/21/2011 #6

正如其他人已经指出的那样,事实并非如此,而是很可能如此。除此之外...datadataListnull

catch-throw是一种反模式,几乎总是让我每次看到它都想吐。想象一下,在召唤的东西深处出了点问题。你得到的只是一个物体,扔在里面。没有堆栈跟踪,没有调用信息,没有状态,根本没有任何东西来指示问题的真正根源,除非你进入并切换调试器以在引发异常时中断,而不是在未处理异常时中断。如果你捕捉到一个异常,并以任何方式重新抛出它,特别是如果try块中的代码在任何方面都是非平凡的,请帮你自己(以及你的同事,现在和将来)一个忙,扔掉整个-块。诚然,它比其他选择要好,但你仍然给自己(或其他任何试图修复代码中的错误的人)带来完全不必要的麻烦。这并不是说 try-catch-throw 本身一定是邪恶的,只要你对 catch 块中抛出的异常对象做了一些相关的事情doOtherStuff()ExceptionthrowAddData()trycatchthrow;

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

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

22赞 gatopeich 4/11/2012 #7

[编辑以反映@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'

评论

2赞 Kelly Elton 10/8/2012
实际上,我刚刚尝试过这个,并且评论“隐含的优点是它忽略了数据类中可能存在的任何覆盖,例如”运算符 !=”。似乎不成立。
84赞 Jowen 2/7/2014 #8

C# 6 具有 monadic null 检查:)

以前:

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

后:

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

评论

8赞 Adam Cox 4/5/2017
我来这里是为了寻找更好的语法来表达,你的例子提示我写.男人!!这太鬼鬼祟祟了。我仍然喜欢编码......result = myObject == null ? null : myObject.SomePropertyresult = myObject?.SomeProperty
2赞 Jose Ortega 2/1/2017 #9
  public static bool isnull(object T)
  {
      return T == null ? true : false;
  }

用:

isnull(object.check.it)

有条件使用:

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

更新(另一种方式)更新于 2017 年 8 月 31 日和 2021 年 1 月 25 日。谢谢你的评论。

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

演示Demostration on Visual Studio console application

为了记录,你在 Github 上有我的代码,去看看: https://github.com/j0rt3g4/ValidateNull PS:这个特别适合你 Chayim Friedman,不要使用测试版软件假设这一切都是真的。等待最终版本或使用您自己的环境进行测试,然后再假设真正的测试版软件,而无需您提供任何文档或演示。

评论

7赞 lericson 4/23/2017
cond ? true : false;完全等同于.这不会增加任何内容。cond
0赞 Jose Ortega 4/24/2017
对不起,但如果您检查该函数,它必须返回一个布尔值。我正在做形式主义。所以重新检查一下
5赞 MQoder 5/11/2017
他的意思是也返回一个布尔值!return T == null;
1赞 md2perpe 3/24/2018
而不是只使用 .return T == null ? true : false;return T == null;
1赞 md2perpe 3/24/2018
如果真的会回来吗?return T ? true : false;trueTnull
5赞 Ali 6/17/2017 #10

除了@Jose奥尔特加的回答, 它更适合使用扩展方法

 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 //
   }

评论

1赞 md2perpe 3/23/2018
为什么而不仅仅是?return T == null ? true : false;return T == null;
2赞 Jamie Twells 10/17/2018
我不确定我是否同意。在对象上调用方法以检查它是否为 null 看起来很奇怪。如果不知道它是一个扩展方法,你会认为它会引发一个空引用异常。
0赞 James King 3/27/2019
可以完全确认杰米是正确的 - 这是行不通的。我知道,因为我有一个脑洞大开的时刻,并写了一个类似的扩展方法:P代码总是抛出一个空引用异常,它绝对不会进入扩展方法。
0赞 Ali 4/11/2019
实际上,我想说你可以用扩展方法做到这一点......可能是代码有问题,可以改进!
0赞 Tim Barrass 6/21/2019
可以在 null 对象上调用扩展方法;您只需要将 T(在本例中)与 null 进行比较即可小心。杰米是对的,不过,这看起来很奇怪。
1赞 user3483639 4/30/2018 #11

每当您创建类对象时,您都必须使用以下代码检查对象是否为 null。

例: object1 是类的对象

void myFunction(object1)
{
  if(object1!=null)
  {
     object1.value1 //If we miss the null check then here we get the Null Reference exception
  }
}
187赞 kofifus 7/4/2018 #12

if (obj is null)

对于 null,请使用:

(C# > 9)
if (obj is object)if (obj is not null)

这些将忽略对象定义的任何或定义(当然,除非您想将它们用于 null 检查)==!=

有关详细信息,请参阅《C# 语言参考》中的 is 运算符

评论

2赞 sehe 7/7/2018
我想知道有没有“不是空”?(python 会说obj is not null)
157赞 Nick Bull 9/13/2019
希望他们能实施:(if (obj aint null)
18赞 yatskovsky 10/19/2019
因为 isn't null 有if (obj is object)
6赞 mitchellJ 11/22/2019
@OrnKristjansson,因为 != 和 == 可以被覆盖。
2赞 user11909 3/10/2020
我想念 VB.NET 中的运算符(以及布尔运算符和 - 比 && 和 ||) 更具可读性)IsNotAndOr
0赞 Mohan Stanky 8/22/2019 #13

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

var obj = new Object();
var objStr = obj.ToString();
if (!string.IsNullOrEmpty(objStr)){
  // code as per your needs
}
6赞 Darren Ruane 1/13/2020 #14

C# 8 开始,可以使用“空”属性模式(具有模式匹配)来确保对象为 null:

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

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

您可以将其视为以下的反义词。当对象不引用某物的实例时,它将返回 true。if (obj is null)...

有关 C# 8.0 中的模式的详细信息,请阅读此处

评论

0赞 Joseph Lennox 11/13/2020
看起来每次运行时都会分配一个新对象,该对象正在添加不需要的 GC 压力/是一种反模式。
0赞 Darren Ruane 11/13/2020
这是假设还是事实?测试应用中的编译输出显示它被编译为简单的检查。!= null
0赞 Joseph Lennox 11/14/2020
你是对的,这是一个假设,因为这是对象初始值设定项语法。但即使在调试版本中,它也会编译成这意味着您绝对正确,不会发生分配。我感到非常惊讶,并为造成混乱而道歉。ldloc.0; ldnull; cgt.un
0赞 EKW 3/25/2021
如果它被编译为更简单的,为什么这会是一个改进,因为它更清晰?!= null!= null
0赞 Darren Ruane 3/25/2021
@EKW因为运算符可以在类中重载(从而调用自定义实现),而上面使用模式匹配,它不会调用任何重载运算符。我现在无法检查,但我相信上述代码的编译输出将始终将对象转换为(确保不调用任何重载运算符)。!=object
0赞 Gilles5678 3/11/2020 #15

我做了更简单(积极的方式),它似乎效果很好。

因为任何一种“对象”至少都是一个对象


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

26赞 Eugene Chybisov 5/21/2020 #16

C# 9 开始,您可以执行以下操作

if (obj is null) { ... }

对于非 null 使用

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

如果需要覆盖此行为,请相应地使用 和。==!=

8赞 Ygalbel 9/15/2020 #17

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

if (name is null) { }

if (name is not null) { }

你可以在这里获得更多信息

0赞 AHAMED AAQIB 11/19/2020 #18

您可以尝试如下

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;

}

0赞 Rob L 1/6/2021 #19

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

/// <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);
}
-1赞 Manish Sharma 3/13/2021 #20
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;
    }

评论

1赞 Wai Ha Lee 3/13/2021
这似乎没有回答这个问题,即关于检查引用是否为 null。
2赞 Uche Igbokwe 2/25/2022 #21

.NET 6 中有一个单行代码

ExampleMethod(null);

void ExampleMethod(object param)
{
    ArgumentNullException.ThrowIfNull(param);
    // Do something
}