在using语句块中调用空引用的方法是否可行?

8

我在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”的呢?在我的编程经验中,无论在什么情况下都从未知道在空引用上调用方法会被认为是“ok”,这样做似乎会抛出NullReferenceException异常。这是否是使用using子句的特殊情况呢?我可以理解这个情况是可以接受的(我不知道它确实可以,但显然确实可以):

using (null)
{
    ...
}

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


Step是扩展方法还是实例方法? - user541686
巴。如果是这样的话,那就解释了一切... - Jake Petroules
3个回答

12

如果profiler为空,除非profiler.Step实际上是扩展方法,否则绝对可以。这与using语句无关。

事实证明,正是扩展方法的部分导致了这种情况。MiniProfiler.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 是可以的。


2
现在我在做脸掌动作,因为Mehrdad问Step是否是扩展方法,我意识到它确实是。感谢你们两个。 :) - Jake Petroules

5

Step必须是一个扩展方法,就像我在评论中猜测的那样。

否则,你的编译器可能有问题,或者你在幻觉中。:-)


1

哇,这是一个好问题。我的第一反应是“当然不好”...但我在VS2010中输入它并感到满意。

我为你找到了一个可能的答案(这会让我成为答案代理吗?)在这里:使用空对象的语句

如果是我,我会编写一个单元测试来验证这种行为,以便如果将来发生变化,测试将失败。

再见


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接