调试的求值顺序.在.net 4.5.2中断言(condition, interpolatedStringMessage)
本文关键字:断言 中断 condition interpolatedStringMessage 顺序 net 调试 | 更新日期: 2023-09-27 18:14:58
我偶然发现了c#/中一个奇怪的问题。Net 4.5.2这里…
我有一个!ContainsKey()
检查在Debug.Assert()
与一个插入字符串包含值,如果发现,像这样
var dict = new Dictionary<string, string>();
string invalidKey = "invalidKey";
try
{
Debug.Assert((!dict.ContainsKey(invalidKey)), $"{nameof(dict)} contains the key {dict[invalidKey]}!");
}
catch (KeyNotFoundException)
{
Console.WriteLine("AssertionString was interpolated before the check was performed!");
}
(仅在第一个版本中没有try-catch块)
我本以为永远不会遇到catch
那里,也是情况,例如检查代码在。netfiddle(见https://dotnetfiddle.net/RyQooW),然而,在Visual Studio中,在。net 4.5.2下运行代码,我得到以下内容:
插入字符串在断言条件
之前求值这绝对是字符串插值(而不是ContainsKey
的问题),因为当我从消息中删除插值时,异常不会被抛出。
求值顺序不能保证吗?我认为如果断言为真,字符串不会被插入。
或者这只是一个错误在这个版本的。net运行时(可能是一个优化插入断言字符串早期使它们静态或什么?)
感谢您的任何输入,干杯!
好了,对于每个被这个绊倒的人:
显然是不是一个bug,而实际上只是Debug.Assert
是一个常规方法(不是一些特殊的内置助手,等等,参见Microsoft的参考源代码),因此任何字符串参数都必须在进入方法之前插入(因为有问题的对象可能在调用范围之外不可用)。
但是,由于条件和消息都是方法参数,并且条件的求值发生在方法的内部(并且而不是方法调用作为求值的结果),因此当然在进入方法并检查条件之前抛出上述KeyNotFoundException
。
唯一让Debug.Assert
有点特别的是它有一个[System.Diagnostics.Conditional("DEBUG")]
属性,因此在非调试构建中被剥离。
所以这实际上是完全可以理解和正确的行为(在任何 dot net版本中),尽管它是一种陷阱。