为啥短路不能防止与逻辑 AND (&&) 的不可达分支相关的 MissingMethodException?
Posted
技术标签:
【中文标题】为啥短路不能防止与逻辑 AND (&&) 的不可达分支相关的 MissingMethodException?【英文标题】:Why does short-circuiting not prevent MissingMethodException related to unreachable branch of logical AND (&&)?为什么短路不能防止与逻辑 AND (&&) 的不可达分支相关的 MissingMethodException? 【发布时间】:2011-07-11 03:04:58 【问题描述】:在检查我的 windows mobile 单元上是否存在并启用了摄像头时,我遇到了一些我不明白的事情。
代码如下:
public static bool CameraP()
return Microsoft.WindowsMobile.Status.SystemState.CameraPresent;
public static bool CameraE()
return Microsoft.WindowsMobile.Status.SystemState.CameraEnabled;
public static bool CameraPresent1()
return Microsoft.WindowsMobile.Status.SystemState.CameraPresent
&& Microsoft.WindowsMobile.Status.SystemState.CameraEnabled;
public static bool CameraPresent2()
return CameraP() && CameraE();
当我调用 CameraPresent2()
时,它返回 false(没有摄像头)。但是当我打电话给CameraPresent1()
时,我收到一个 MissingMethodException 并带有注释“找不到方法:get_CameraEnabled Microsoft.WindowsMobile.Status.SystemState。”
在CameraPresent1
中评估第二个术语是否仅仅因为它们都是属性(在语言级别)?
还有什么可以解释行为差异的吗?
【问题讨论】:
如果你调用 CameraE() 你会得到同样的异常吗? “短路”在这里会比“懒惰”更好...... 让我感到困惑的部分是我在 msdn 中根本找不到对 CameraEnabled 的引用......不过我打算去“一些自定义的 && 重载”。 @The_Butcher 是的,如果我调用 CameraE() 会引发相同的异常。 @Massif:那里也找不到,但是当我从 VS2008 浏览 Microsoft.WindowsMobile.Status 时可以找到它。它适用于具有摄像头的其他单元。这给了我一些新的想法。 【参考方案1】:不计算第二项。
不评估第一项。
CameraPresent1()
方法甚至没有开始执行。
当您第一次调用CameraPresent1()
时,运行时必须将 MSIL 即时编译为本机代码。这需要解决所有的方法调用,即使是那些只能有条件地到达的方法调用。 MissingMethodException
编译失败。
使用CameraPresent2()
,只有在第一次调用CameraE()
时才会编译对CameraEnabled
的getter 的调用,这永远不会发生。
【讨论】:
很好的答案——实际上回答了这个问题 谢谢!这给了我一些深刻的见解,不仅对我的问题,而且对 JIT 编译器的工作方式和时间。 回答弗里茨的评论,由于低代表被放置在答案中,并且由于单词选择不佳被mod删除 - 属性的执行速度不比方法快。属性不过是一对方法的语法糖,getter 和 setter。 (语法糖意味着编译器将其转换为相同的输出可执行文件)【参考方案2】:C# Specification 7.12 节
&&
和||
运算符称为条件逻辑运算符。它们也被称为“短路”逻辑运算符。
&&
和 ||
运算符是 & 和 | 的条件版本运营商:
操作x && y
对应于操作x & y
,除了y
只有在x
不是false
时才会被评估。
操作x || y
对应于操作x | y
,除了y
仅在x
不是true
时才被评估。
也就是说,C# 规范保证
CameraE()
将被调用当且仅当 CameraP()
为真。
这可能是过度编译器优化的问题,因此实际程序似乎违反了语言规范...
编辑:
是否可以设置断点并显示反汇编窗口,以查看生成的确切代码?
【讨论】:
我认为他在问为什么在调用 CameraPresent1 时看起来 && 似乎是不懒惰的。 @Marc:我……不知道……我以为那只是为了玩弄……哦,天哪,我不擅长这个…… RB 是正确的。 && 运算符怎么会像没有短路一样工作。我将编辑问题标题。 “短路”是什么意思? @John Gietzen:但是CameraPresent1()
呢?显然,第二个参数被评估。这是我应该将其视为 VS2008 实现中的错误吗?【参考方案3】:
只是一个疯狂的猜测,但这有可能是 JIT 编译问题吗?调用 CameraPresent1 时,是否尝试将调用 Microsoft.WindowsMobile.Status.SystemState.CameraEnabled 映射到底层设备?由于找不到方法 get_CameraEnabled,因此整个函数失败并出现 MissingMethodException。
【讨论】:
我只是想重现问题,但无法编译,因为找不到 CameraEnabled。该应用程序是否为您编译?您有哪些项目参考资料? @Justin Largey:Microsoft.WindowsMobile.Status 的运行时版本是 v1.1.4322。 有趣,这和我的版本一模一样。我似乎无法在任何地方找到 CameraEnabled。在您的代码中,您可以尝试选择 CameraEnabled 属性,然后按 F12(转到定义)。 VS 真的带你去定义这个属性吗?项目是否有可能引用了一个针对 MS.WindowsMobile.Status 命名空间进行扩充的程序集?或者VS中的运行时和手机上的运行时不匹配。 (即 VS 中的运行时认为有一个 CameraEnabled 属性,但手机上的实际运行时没有它。) 我可以从我的代码导航到定义。您使用的是什么目标平台?我目前只安装了 Windows Mobile 6 SDK,所以我无法仔细检查它是否也适用于 WM5。但由于它只在带有 WM5 的设备上失败,我想这可能是错误发生的地方。 我认为你是对的。我有 Windows Mobile 5 SDK,它没有 CameraEnabled 属性。但是,我猜 v6 SDK 确实有这个属性。这也解释了为什么它适用于 WM6,但不适用于 WM5。【参考方案4】:查看报告的问题,似乎没有任何意义。这两个版本应该是相同的。不过,我想知道这里的问题是否是相机 API 在某些时候使用了 dynamic
,并且它正在尝试寻找 true()
/false()
/&
运算符。这可能会说服它切换到bool
逻辑:
public static bool CameraPresent1()
return ((bool)Microsoft.WindowsMobile.Status.SystemState.CameraPresent)
&& ((bool)Microsoft.WindowsMobile.Status.SystemState.CameraEnabled);
【讨论】:
仍然不会输入CameraPresent1()
。我更倾向于 Ben Voigt 的回答。以上是关于为啥短路不能防止与逻辑 AND (&&) 的不可达分支相关的 MissingMethodException?的主要内容,如果未能解决你的问题,请参考以下文章