.Net 4.5.2 中 Debug.Assert(condition, interpolatedStringMessage) 的评估顺序

Order of evaluation for Debug.Assert(condition, interpolatedStringMessage) in .Net 4.5.2

我在这里偶然发现了 C#/.Net 4.5.2 中的一个奇怪问题……

我在 Debug.Assert() 中进行了 !ContainsKey() 检查,其中包含包含值的内插字符串,如果找到,就像这样

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 下的代码中,我得到以下信息:

interpolated string evaluated before assertion condition

绝对是字符串插值(ContainsKey 没有问题),因为当我从消息中删除插值时,不会抛出异常。

评价顺序不保证?我认为如果断言为真,则不会对字符串进行插值。

或者这只是这个版本的 .Net 运行时中的一个错误(也许是一种优化,可以尽早插入断言字符串以使它们成为静态的或其他什么?)

感谢任何意见,干杯!

好吧,对于所有遇到这个问题的人来说:

不是 一个错误,显然,但实际上只是 Debug.Assert 作为一个常规方法(不是一些特殊的 built-in 帮助程序等,请参阅也 Microsoft's reference source),因此任何字符串参数 必须 进入方法之前被插入 (因为所讨论的对象可能不是在调用范围外可用)。
但是由于条件和消息都是方法参数,并且条件的评估发生在 inside 方法(并且 not 方法调用作为result of the evaluation),上面的KeyNotFoundException当然是在进入方法和检查条件之前抛出的。

唯一使 Debug.Assert 有点特别的是它具有 [System.Diagnostics.Conditional("DEBUG")] 属性,因此在 non-Debug 构建中被剥离。

所以这实际上是完全可以理解和正确的行为(在 any dot net 版本中),尽管它是一种陷阱。