当前位置:  开发笔记 > 编程语言 > 正文

C#:在这种情况下,我是否应该费心检查null?

如何解决《C#:在这种情况下,我是否应该费心检查null?》经验,为你挑选了1个好方法。

可以说我有这种扩展方法:

public static bool HasFive(this IEnumerable subjects)
{
    if(subjects == null)
        throw new ArgumentNullException("subjects");

    return subjects.Count() == 5;
}

你觉得这个空检查和异常抛出真的有必要吗?我的意思是,当我使用这种Count方法时,ArgumentNullException无论如何都会被抛出,对吧?

我可以想到我应该这样做的一个原因,但是我想听听别人对此的看法.是的,我问的理由是部分懒惰(想要尽可能少地写),但也因为我认为一堆空检查和异常抛出了一些混乱的方法,这些方法往往最终是他们真的需要.有人应该知道比将null发送到方法更好:p

无论如何,你们怎么想?


注意: Count()是一个扩展方法,抛出一个ArgumentNullException,而不是一个NullReferenceException.见Enumerable.Count Method (IEnumerable).如果你不相信我自己尝试=)


注2:在这里给出的答案之后,我被说服开始检查更多的空值.我仍然很懒,所以我开始Enforce在Lokad共享库中使用该类.可以推荐看一下.而不是我的例子,我可以这样做:

public static bool HasFive(this IEnumerable subjects)
{
    Enforce.Argument(() => subjects);
    return subjects.Count() == 5;
}

Jon Skeet.. 19

是的,它会抛出一个ArgumentNullException.我可以想到额外检查的两个原因:

如果你以后回去并在调用之前更改方法以执行某些操作subjects.Count()并忘记在此时进行检查,则可能会在抛出异常之前产生副作用,这不太好.

目前,堆栈跟踪将显示subjects.Count()在顶部,并且可能带有source参数名称的消息.这可能会让HasFive谁可以看到subjects参数名称的调用者感到困惑.

编辑:只是为了救我不得不在其他地方再写一遍:

召唤subjects.Count()将抛出一个ArgumentNullException,而不是一个NullReferenceException.Count()这是另一种扩展方法,假设System.Linq.Enumerable正在使用实现,那就是记录(正确)抛出一个ArgumentNullException.如果你不相信我,试试吧.

编辑:让这更容易......

如果您做了很多这样的检查,您可能希望这样做更简单.我喜欢以下扩展方法:

internal static void ThrowIfNull(this T argument, string name)
    where T : class
{
    if (argument == null)
    {
        throw new ArgumentNullException(name);
    }
}

然后问题中的示例方法可以变为:

public static bool HasFive(this IEnumerable subjects)
{
    subjects.ThrowIfNull("subjects");    
    return subjects.Count() == 5;
}

另一种方法是编写一个检查值并返回它的版本:

internal static T NullGuard(this T argument, string name)
    where T : class
{
    if (argument == null)
    {
        throw new ArgumentNullException(name);
    }
    return argument;
}

然后你可以流利地调用它:

public static bool HasFive(this IEnumerable subjects)
{
    return subjects.NullGuard("subjects").Count() == 5;
}

这对于在构造函数中复制参数等也很有用:

public Person(string name, int age)
{
    this.name = name.NullGuard("name");
    this.age = age;
}

(对于不重要的地方,您可能需要没有参数名称的重载.)



1> Jon Skeet..:

是的,它会抛出一个ArgumentNullException.我可以想到额外检查的两个原因:

如果你以后回去并在调用之前更改方法以执行某些操作subjects.Count()并忘记在此时进行检查,则可能会在抛出异常之前产生副作用,这不太好.

目前,堆栈跟踪将显示subjects.Count()在顶部,并且可能带有source参数名称的消息.这可能会让HasFive谁可以看到subjects参数名称的调用者感到困惑.

编辑:只是为了救我不得不在其他地方再写一遍:

召唤subjects.Count()将抛出一个ArgumentNullException,而不是一个NullReferenceException.Count()这是另一种扩展方法,假设System.Linq.Enumerable正在使用实现,那就是记录(正确)抛出一个ArgumentNullException.如果你不相信我,试试吧.

编辑:让这更容易......

如果您做了很多这样的检查,您可能希望这样做更简单.我喜欢以下扩展方法:

internal static void ThrowIfNull(this T argument, string name)
    where T : class
{
    if (argument == null)
    {
        throw new ArgumentNullException(name);
    }
}

然后问题中的示例方法可以变为:

public static bool HasFive(this IEnumerable subjects)
{
    subjects.ThrowIfNull("subjects");    
    return subjects.Count() == 5;
}

另一种方法是编写一个检查值并返回它的版本:

internal static T NullGuard(this T argument, string name)
    where T : class
{
    if (argument == null)
    {
        throw new ArgumentNullException(name);
    }
    return argument;
}

然后你可以流利地调用它:

public static bool HasFive(this IEnumerable subjects)
{
    return subjects.NullGuard("subjects").Count() == 5;
}

这对于在构造函数中复制参数等也很有用:

public Person(string name, int age)
{
    this.name = name.NullGuard("name");
    this.age = age;
}

(对于不重要的地方,您可能需要没有参数名称的重载.)

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有