为什么调用一个 Action(即 null)会抛出 NullReferenceException

本文关键字:null NullReferenceException 一个 调用 为什么 Action | 更新日期: 2023-09-27 18:30:52

为什么我必须检查Action是否未null以避免NullReferenceException?如果没有行动,那么什么都不做就可以继续,这不是合乎逻辑的吗?我不明白为什么它必须抛出异常。 Action是一个类,为什么它不自己处理呢?

为什么调用一个 Action(即 null)会抛出 NullReferenceException

您正在尝试在对象上调用实例方法 ( Invoke )。如果您使用的是null引用1,则执行此操作始终会失败并显示NullReferenceException。例如:

 object x = null;
 string y = x.ToString();

object.ToString()也应该处理这个问题吗?

基本上,这与类型系统的其余部分的工作方式一致。C# 语言本可以以不同的方式设计 - 可能仅用于action()含义action.Invoke()的"速记" - 但它不是,现在也不会改变。

如果要执行以下操作

,很容易将自己的扩展方法添加到Action

public static class ActionExtensions
{
    public static void NullSafeInvoke(this Action action)
    {
        if (action != null)
        {
            action();
        }
    }
}

或者使用 C# 6 null 条件运算符仅在引用为非 null 时调用委托:

myAction?.Invoke();

(这适用于任何委托类型,而不仅仅是操作 - 例如EventHandler,您将使用 handler?.Invoke(this, new EventArgs()) .如果 EventArgs() 为 null,则甚至不会调用 handler 构造函数。


1 至少使用 C#。有一些方法可以在 IL 中非虚拟地"在"空引用上调用实例方法,但这远非正常情况。

从 C# 6.0 开始,您可以:

myAction?.Invoke();

无需扩展方法。

Action是一个委托,而不是一个类。当您调用操作时,如下所示:

myAction();

这里真正发生的事情是这样的:

myAction.Invoke();

如果myAction null则在null实例上调用Invoke,这自然会引发NullReferenceException