检查c#中的对象是否为空

如果对象为空,我想防止对其进行进一步处理。

在下面的代码中,我检查对象是否为空:

if (!data.Equals(null))

而且

if (data != null)

然而,我在dataList.Add(data)处收到了一个NullReferenceException。如果对象为空,它甚至不应该进入if-statement!

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

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)?

1171913 次浏览

你的dataList是空的,因为它还没有被实例化,从你发布的代码判断。

试一试:

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

null不是data,而是dataList

你需要创建一个

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

更好的是:因为它是一个字段,所以将它设置为private。如果没有什么可以阻止你,把它也设为readonly。只是很好的练习。

一边

检查null值的正确方法是if(data != null)。这种检查对于引用类型是普遍存在的;甚至Nullable<T>也会重写相等操作符,以便在检查是否为null时更方便地表示nullable.HasValue

如果执行if(!data.Equals(null)),则如果执行data == null,则会得到NullReferenceException。这有点滑稽,因为避免这种异常是首要目标。

你也在这样做:

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

这绝对不好。我可以想象,您把它放在那里只是为了在仍然在方法内部的情况下进入调试器,在这种情况下忽略这段。否则,不要无缘无故地捕获异常。如果你这样做,只使用throw;重新抛出它们。

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

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

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

不,你应该使用!=。如果data实际上是空的,那么你的程序会因为试图在null上调用Equals方法而导致NullReferenceException崩溃。还要注意,如果你特别想检查引用是否相等,你应该使用Object.ReferenceEquals方法,因为你永远不知道Equals是如何实现的。

你的程序崩溃是因为dataList是空的,因为你从来没有初始化它。

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

您的代码还有另一个问题:您使用了ref-关键字,这意味着参数数据不能为空!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) {
//...
}
}

正如其他人已经指出的那样,data不是data,而更有可能是dataListnull。除此之外……

catch-throw是一个反模式,每次看到它几乎总是让我想吐。想象一下,在doOtherStuff()调用的某个东西的深处出了问题。你所返回的只是一个Exception对象,它被扔给了AddData()中的throw。没有堆栈跟踪,没有调用信息,没有状态,没有任何东西表明问题的真正根源,除非您进入并切换调试器,在抛出异常时中断,而不是在未处理的异常时中断。如果你正在捕捉一个异常并只是重新抛出无论如何,特别是如果try块中的代码在任何方面都不是平凡的,请帮你自己(以及你现在和将来的同事)一个忙,抛出整个try-catch块。当然,throw;比其他选项更好,但你仍然给自己(或其他试图修复代码中的错误的人)带来完全不必要的麻烦。这并不是说try-catch-throw本身就一定是邪恶的,只要你在catch块内throw0。

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

另一件让我感到非常危险的事情是,data可能在函数执行期间更改值,因为您是通过引用传递的。因此空检查可能会通过,但在代码对该值做任何操作之前,它已经被更改了——可能是null。我不确定这是否值得关注(可能不是),但这似乎值得关注。

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

真正的

c# 6有一元空校验:)

之前:

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

后:

var bestValue = points?.FirstOrDefault()?.X ?? -1;
  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;
}
< p >骨干示范  Visual Studio控制台应用程序演示 < / p > 为了记录,你在Github上有我的代码,去看看: https://github.com/j0rt3g4/ValidateNull PS:这一点是特别为你准备的,Chayim Friedman,不要使用测试软件,假设这一切都是真的。等待最终版本或使用您自己的环境进行测试,然后在没有任何文档或演示的情况下假设真正的beta软件

除了@Jose奥尔特加 answer, 最好使用扩展方法

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

当你创建类的对象时,你必须使用下面的代码检查对象是否为空。

< p >的例子: Object1是类

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

在c# >7使用if (obj is null)

对于 null使用:
c# 7-8: if (obj is object)
c# 9-: if (obj is not null)

它们将忽略对象定义的任何==!=(当然除非你想使用它们进行空检查)

有关更多信息,请参见c#语言参考中是运营商

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

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

C # 8开始,你可以使用'empty'属性模式(带有模式匹配)来确保对象是 null:

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

这种方法意味着“如果对象引用某个对象的实例”(即它不是空)。

你可以把它看成是:if (obj is null)...的反义词。当对象没有引用某个对象的实例时,返回true。

有关c# 8.0中模式的更多信息,请阅读在这里

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

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


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


对于C # 9你可以这样做

if (obj is null) { ... }

非空用

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

如果需要重写此行为,则相应使用==!=

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

if (name is null) { }


if (name is not null) { }

你可以有更多的信息在这里

你可以像下面这样试试

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;

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

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

在。net 6中有一个一行程序

ExampleMethod(null);


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