在using子句的上下文中对空引用调用方法是可以的

本文关键字:方法 调用 引用 子句 using 上下文 | 更新日期: 2023-09-27 18:01:51

我正在看Google Code上Stack Overflow团队设计的mvc-mini-profiler,在入门页面上有一件事让我特别奇怪:

var profiler = MiniProfiler.Current; // it's ok if this is null
using (profiler.Step("Set page title"))
{
    ViewBag.Title = "Home Page";
}

如果profiler为空,它怎么可能是"ok"?在我看来,调用Step会抛出一个NullReferenceException。在我多年的c#编程中,我从来没有听说过在任何上下文中对空引用调用方法是"ok"的。在使用从句的上下文中,这是一个特例吗?

我可以理解这是OK的(不知道它是,但显然它是?):

using (null)
{
    ...
}

但是在null引用上调用方法似乎应该抛出异常,无论它是否在using子句中。有人能解释一下这种结构是如何在幕后翻译的吗?这样我就能理解为什么这样做是可以的?

在using子句的上下文中对空引用调用方法是可以的

绝对 OK,如果profiler是null 除非 profiler.Step实际上是一个扩展方法。using语句不影响

事实证明,扩展方法部分正是正在发生的事情。miniprofile .cs的第584-587行:

public static IDisposable Step(this MiniProfiler profiler, string name,
                               ProfileLevel level = ProfileLevel.Info)
{
    return profiler == null ? null : profiler.StepImpl(name, level);
}

这就是profiler为空时profiler.Step被调用的方式。它不是一个实例方法——调用转换为:

MiniProfilerExtensions.Step(profiler, ...);

对于profiler.Step来说,返回 null是很好的,正如你问题的第二部分。

Step必须是扩展方法,正如我在评论中猜测的那样。

否则,要么你的编译器被破坏了,要么你产生了幻觉。: -)

哇,这是个好问题。我的第一反应是"这当然不好"……但我把它输入VS2010,似乎很高兴。

我在这里找到了一个可能的答案(这是否使我成为一个答案代理?):使用带有空对象的语句

如果是我,我会写一个单元测试来验证这个行为,这样如果它在将来每一次改变,测试就会失败。

再见