首先,你应该always assume it's your fault,不是编译器的错; select isn't broken。您是否真的认为 ?? 运算符的 Visual Studio 2010 实现尚未经过实战测试?当您遇到与您的期望不符的事情时,请检查您的期望。拿出手册,确保你理解准确会发生什么。在这种情况下,请打开语言规范。
如果您继续阅读specification 的第 1.4 节,您将看到一个将运算符分组为优先级分组的表格;你也可以找到它online。特别是,空合并运算符?? 位于底部 附近,仅高于低级条件三元运算符和赋值以及=>。它在下面加法运算符。因此,您的声明
string tmp = "a" + "(" + date ?? "blablabla" + ")";
被编译器视为
string tmp = (("a" + "(" + date) ?? ("blablabla" + ")"));
我不会完全迂腐,并且也将第一个加法表达式1括起来。由于该语句中表达式的左侧从不为空,当然它总是分配"a("(或"a("+date.ToString()当@ 987654334@ 为真)到tmp。
主要点是你对应该发生的事情有一个错误的预期,你应该根据手册进行验证。
如果我把date ?? "blablabla" 放在括号中,它会被下划线标记为错误。
当然是。您甚至阅读了错误消息吗?它可能会告诉您,您不能在DateTime? 和string 上执行??,因为DateTime? 和string 在任一方向上都没有隐式转换。这也包含在语言规范中;见第 7.13 节。您必须阅读此消息并回复。要获得 语义 等同于您要表达的内容尝试,您将不得不求助于条件三元运算符:
date.HasValue ? date.ToString() : "blablabla"
然后将整个内容用括号括起来,因为条件三元运算符的优先级非常很低。
最后,我发现您的代码的正确括号版本相当丑陋,阅读起来并不有趣,而且维护起来可能也不愉快。请简单点:
var tmp = String.Format("a({0})",
date.HasValue ? date.ToString() : "blablabla");
现在所以清楚正在发生什么以及将要发生什么。我不必思考就能理解它。把你的想法留到你将遇到的困难问题上。
1:小心。在尝试正确确定首先评估的内容之前,我们需要添加对date.ToString(具有最高优先级)的方法调用。