在哪里检查对象是否为空?

发布于 2024-07-16 08:54:57 字数 761 浏览 5 评论 0原文

在哪里检查传递给方法的对象是否为 null?

在调用方法之前是否需要测试对象? 或者在使用参数的方法中?

public class Program
{
    public static void Main(string[] args)
    {
        // Check if person is null here? or within PrintAge?

        PrintAge(new Person { Age = 1 });
    }

    private static void PrintAge(Person person)
    {
        // check if person is null here?

        Console.WriteLine("Age = {0}", person.Age);
    }
}

public class Person
{
    public int Age { get; set; }
}

在两个类中进行“空”检查似乎是太多冗余代码。

[编辑]:在调用者或被调用者中检查 null 的缺点/优点是什么?

[EDIT2]:我刚刚遇到了防御性编程,看起来像它提倡在被调用者中检查 null。 我想知道这是否是一种被广泛接受的做法。

Where do you check if an object that you are passing to a method is null or not?

Should an object need to be tested before calling a method? or within the method that is using the argument?

public class Program
{
    public static void Main(string[] args)
    {
        // Check if person is null here? or within PrintAge?

        PrintAge(new Person { Age = 1 });
    }

    private static void PrintAge(Person person)
    {
        // check if person is null here?

        Console.WriteLine("Age = {0}", person.Age);
    }
}

public class Person
{
    public int Age { get; set; }
}

Having a "null" check in both classes seem to be too much redundant code.

[EDIT]: What would be an dis/advantage of checking for null within a caller or a callee?

[EDIT2]: I just ran into Defensive Programming and it seems like it advocates checking null within a callee. I wonder if this is a widely accepted practice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

自由如风 2024-07-23 08:54:57

如果你设计一个库,就会有暴露给外部世界的方法。 您应该检查此方法中传入的数据。 在您不公开的方法中不需要进行检查,因为只有您的代码调用它们,并且其逻辑应该处理您在所调用的公开方法中接受的所有情况。

                    --------------------------
                   |                          |
                   |         Library          |
                   |                          |
 -------        ---------        ----------   |
|       |      |         |      |          |  |
| Outer |      | Library |      | Library  |  |
|       | ===> | Entry   | ===> | Backend/ |  |
| World |      | Method  |      | Helpers  |  |
|       |      |         |      |          |  |
 -------        ---------        ----------   |
                   |                          |
                   |                          |
                    --------------------------

如果您已经接受了输入方法中提供的数据,则应该执行请求的操作并返回预期的结果,即处理所有剩余的情况。

更新

澄清图书馆内部的情况。 可能存在空检查,但这只是因为逻辑,而不是因为参数验证。 库内空检查的位置有两种可能性。 第一个如果被调用的方法知道如何处理空值。

private CallingMethod()
{
   CalledMethod(someData);
}

private CalledMethod(Object parameter)
{
   if (parameter == null)
   {
      // Do something
   }
   else
   {
      // Do something else
   }
}

第二种情况是调用无法处理空值的方法。

private CallingMethod()
{
   if (someData == null)
   {
      // Do the work myself or call another method
   }
   else
   {
      CalledMethod(someData);
   }
}

private CalledMethod(Object parameter)
{
   // Do something
}

整个想法是拒绝您无法立即处理的案件并妥善处理所有剩余案件。 如果输入无效,则会抛出异常。 这迫使库调用者仅提供有效值,并且不允许调用者以无意义的返回值继续执行(除了调用者浅化异常并继续)。

If you design a library, there will be methods exposed to the outer world. You should check the incoming data in this methods. No checks are required in methods that you do not expose, because only your code calls them and its logic should handle all cases you accepted in the exposed method called.

                    --------------------------
                   |                          |
                   |         Library          |
                   |                          |
 -------        ---------        ----------   |
|       |      |         |      |          |  |
| Outer |      | Library |      | Library  |  |
|       | ===> | Entry   | ===> | Backend/ |  |
| World |      | Method  |      | Helpers  |  |
|       |      |         |      |          |  |
 -------        ---------        ----------   |
                   |                          |
                   |                          |
                    --------------------------

If you have accepted the supplied data in the entry method, you should perform the requested action and return the expected result, that is handle all remaining cases.

UPDATE

To clarify the situation inside the library. There might be null checks, but only because of the logic, not because of parameter validation. There are two possibilities for the location of null checks inside the library. The first one if the called method knows how to handle null values.

private CallingMethod()
{
   CalledMethod(someData);
}

private CalledMethod(Object parameter)
{
   if (parameter == null)
   {
      // Do something
   }
   else
   {
      // Do something else
   }
}

And the second situation if you call a method that cannot handle null values.

private CallingMethod()
{
   if (someData == null)
   {
      // Do the work myself or call another method
   }
   else
   {
      CalledMethod(someData);
   }
}

private CalledMethod(Object parameter)
{
   // Do something
}

The whole idea is to reject cases you cannot handle immediately and handle all remaining cases properly. If the input is not valid you throw an exception. This forces the library caller to supply only valid values and does not allow the caller to continue execution with meaningless return values (besides the caller shallows the exception an continues).

梅窗月明清似水 2024-07-23 08:54:57

您在 Main 中没有任何需要检查的内容 - 您使用的 new 运算符永远不会返回 null(Nullable 除外) 。

检查 PrintAge 是完全合理的,特别是如果它被公开的话。 (对于私有 API,进行参数检查不太重要,但它仍然非常有用。)

if (person == null)
{
    throw new ArgumentNullException("person");
}

在 C# 3.0 中,我通常 为此使用扩展方法

You've got nothing to check in Main - you're using the new operator which never returns null (except for Nullable<T>).

It would be entirely reasonable to check in PrintAge, particularly if it were made public. (For private APIs it's less important to do argument checking, but it can still be very useful.)

if (person == null)
{
    throw new ArgumentNullException("person");
}

These days in C# 3.0 I usually use an extension method for this.

夜清冷一曲。 2024-07-23 08:54:57

您可以设计一种仅使用有效对象的方法。

这意味着您希望收到有效对象(在您的情况下不为空)。
这意味着您不知道如何做出反应以及如何处理无效对象:

  • 从函数中静默返回
    不是解决方案;
  • 抛出异常意味着您将责任移交给上层
    方法,它们可以在传递给您之前检查值。

因此,如果您的方法不确切知道如何处理无效对象,并且该方法在无效情况下不会遵循额外的逻辑,您应该将其放在

Debug.Assert( Person );

PrintAge 开始,这将强制您通过调用堆栈进行检查

层次结构中越低的功能,它应该执行的检查越少。 以下是在执行该工作的函数中进行检查的缺点

  • 正在做实际工作的函数
    必须尽可能清楚
    如果没有大量的 if
  • 函数将会被调用很多次
  • 这样的函数可以调用这样的函数并且它们可以再次调用这样的函数。 他们每个人都会执行相同的验证

You can design a method to work with valid objects only.

That means you are expect to receive valid objects ( not null in your case ).
That means you don't know how to react and what to do with invalid objects:

  • returning silently from the function
    is not a solution;
  • throwing an exception will mean you move responsibility to the upper
    methods where they can check the value already before passing to you.

So if your method don't know exactly how to handle invalid object and the method won't follow additional logic in the invalid case you should put

Debug.Assert( Person );

at the PrintAge begin and this will force you to make checks upper by call stack.

The lower function in hierarchy is the less checks it should do. The following is disadvantages of doing checks in the functions that do the work.

  • Function that is doing actual work
    has to be as clear as possible
    without mass of ifs
  • Function will be called more then many times
  • Such function can call such functions and they can call such functions again. Each of them will perform the same validation
药祭#氼 2024-07-23 08:54:57

我想说,在 PrintAge 中检查它似乎更有意义,因为这是履行例程的合同。 当然,您可以用 Debug.Assert() 代码替换空检查,以在测试时进行检查,但不能在发布时进行检查。

I would say that checking it n PrintAge seemed to make more sense as that is fulfiling the contract for the routine. You could, of course, replace the null checks with Debug.Assert() code to check at test time, but not at release time.

罪#恶を代价 2024-07-23 08:54:57

你的意思是检查这两种方法? 我肯定会检查 PrintAge 以及它在 Main 中是否也有意义。 我认为一般来说没有明确的答案。 这取决于 :-)

You mean checking in both methods? I'd check in PrintAge for sure and if it makes sense within Main as well. I don't think there is a definite answer in general. It depends :-)

ぺ禁宫浮华殁 2024-07-23 08:54:57

我通常让空检查由我的期望控制; 如果我期望某些内容为空或不确定,我会添加一个检查。 否则我不会。 空指针异常是最容易跟踪的问题之一,因此过多的检查会使代码膨胀。 在具体的示例中,我不会检查任何内容,因为它很直观,它不为空。

I normally let my null checks be controlled by my expectations; if I expect something to be null or am unsure of it, I add a check. Otherwise I don't. Nulllpointer exceptions are among the easiest problems to track, so excessive sprinkling of checks bloats code. In the specific example I'd check nothing, because it's intutitive it's not null.

ペ泪落弦音 2024-07-23 08:54:57

如果实例为空,您想做什么?

我认为这取决于你提供的API & 定义契约(.net 框架类的方式)。 话虽如此,如果该方法定义了传递给它的空引用情况下的预期结果,则不需要检查空值(在 main 中)。

What would you want to do, if instance is null?

I think it depends on the API you provide & define contract (the way .net framework classes do). Having said that, you need not do a check for null (in main), if the method defines what is expected outcome in case of null reference passed to it.

无人接听 2024-07-23 08:54:57

据我了解你的问题比你的例子所说明的更普遍。 我的偏好如下:

  • 所有可公开访问的方法都必须检查 NULL 输入并酌情抛出异常。 因此,如果您正在构建一个供其他人使用的框架,请进行防御性编码。
  • 如果您知道这是在其他地方完成的或者参数永远不会为 NULL,私有方法可以省略 NULL 检查,但一般来说,我更喜欢显式的 ArgumentNullException 而不是 NullRefereceException。

Brad Abrams 在此提供了更多信息:http://blogs。 msdn.com/brada/archive/2004/07/11/180315.aspx

As I understand your question it is more general than illustrated by your example. My preferences are as follows:

  • All publicly accessible methods must check for NULL input and throw exceptions as appropriate. So if you're building a framework for others to use, code defensively.
  • Private methods may omit the NULL check if you know that this is done elsewhere or that arguments will never be NULL, but in general I prefer the explicit ArgumentNullException to NullRefereceException.

Brad Abrams has some more input here: http://blogs.msdn.com/brada/archive/2004/07/11/180315.aspx

一场信仰旅途 2024-07-23 08:54:57

只有一种情况,构造函数可以在 Nullable] 上返回 null [new()] - 因此调用代码不需要检查。

被调用者可能应该检查; 如果为 null,则抛出 ArgumentNullException。 在 .NET 4.0 中,代码契约将更好地满足这一需求。 但还没有;-p

There is only one occasion that a constructor can return null [new() on a Nullable<T>] - so the calling code doesn't need to check.

The callee probably should check; throwing an ArgumentNullException if it was null. In .NET 4.0 this will be better served by code contracts. But not yet ;-p

仙女山的月亮 2024-07-23 08:54:57

冗余代码不是最优雅的,但它是安全的。

这取决于您的目标用户是谁,如果是您,那么您可以控制所有内容的使用方式,并且仅当您不确定变量的状态时才需要进行检查。

如果你做这个供其他人使用,那么空检查可能是一个好主意。 即使您只是抛出 NullPointerException,最好还是快速失败。

Redundant code isn't the most elegant but its safe.

This depends on who your intended user is, if its you then your in control of how everything is used and the checks are only necessary if your unsure of what the state of your variables will be.

If your making this for someone else to use then null checks are probably a good idea. Even if you just throw a NullPointerException its better to fast fail.

呆橘 2024-07-23 08:54:57

一定要检查PrintAge,这是一个正确的检查位置。 它可能是多余的,但不会伤害任何人,除非你每秒执行 1000 次。 (根据检查抛出异常或修复它,如果可以的话)

其他检查取决于您的实际流程,在本例中您没有流程,所以我无法对此发表评论。 但通常认为你的参数被污染了。

Definitely check in PrintAge, it's a right place to check. It can be redundant but won't hurt anyone unless you execute it 1000 times per second. (Depending on the check throw an exception or fix it if you can)

Other check is depend on your actual flow, in this example you don't have a flow so I can't comment on that bit. But generally consider your parameters as tainted.

养猫人 2024-07-23 08:54:57

PrintAge 应该是 Person 上的一个方法,而不是一个以 Person 作为参数的静态方法。 无需检查。

检查空值会使代码变得不必要的复杂。 构建代码以限制(或消除)可能值为 null 的情况,并且您需要编写的检查会少得多。

PrintAge should be a method on Person, not a static taking a Person as parameter. No check needed.

Checking for null values makes the code unnecessarily complex. Structure your code so as to limit (or eliminate) the occasions where null is a possible value, and you'll have much fewer checks to write.

岁月静好 2024-07-23 08:54:57

我更喜欢在方法内部进行空检查,原因有两个。

  1. 我认为函数应该是“完整的”,即处理空值/“边缘情况”并且不依赖调用者。 这有两个原因,

    • 稍后调用该方法的人可能会忘记添加 null 检查
    • 在单元测试中使用边缘情况测试方法会更容易。
  2. 在方法内进行 null 检查会减少代码内的 null 检查总数,这通常意味着代码更具可读性

I prefer null checks inside methods for two reasons.

  1. I think functions should be 'complete', ie handle null values/'edge cases' and not rely on callers. This is for two reasons,

    • someone calling the method later might forget to add null checks
    • it's easier to test the method with edge cases in unit tests.
  2. having null checks inside the method reduces overall number of null checks inside the code, which usually means more readable code

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文