C# 目标类型条件表达式

标签 c#

查看 Target-Typed Conditional Expression in C# 9 的文档.

在引入此功能后,文档中针对以下场景引用了歧义,但它仍然似乎每次都会调用M(long, long)时间。即没有歧义?

M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.

static void M(short i, short ii) => Console.WriteLine("short");
static void M(long i, long ii) => Console.WriteLine("long");

编译为:

public static void Main()
{
    M(1L, 1L);
}

private static void M(short i, short ii) { Console.WriteLine("short, short"); }
private static void M(long i, long ii) { Console.WriteLine("long, long"); 

最佳答案

您所描述的情况的歧义完全是内部的。它不会暴露给用户。

为了清楚起见,情况是这样的:

static void Main()
{
    M(1, 2); // Case A
    M(true ? 1 : 2, 3); // Case B
    bool b = true;
    M(b ? 1 : 2, 3);  // Case C
}
static void M(short a, short b) => Console.WriteLine($"{a} {b} {a.GetType()}");
static void M(long a, long b) => Console.WriteLine($"{a} {b} {a.GetType()}");

情况 A 和 B 可以由构建器进行评估(情况 B 生成 IL 代码 M(1, 3); - 条件甚至不会呈现给运行时),因此两者都解析为short 实现,但情况 C 是歧义所在。

当运行时需要决定调用哪个版本时,它会执行第一遍并确定两个表达式解析为不同的类型。 b? 1 : 2 单独考虑时解析为 int3 也解析为 int,但在上下文中对于此问题,模式匹配器需要将两者解析为 shortlong

模式匹配器不想完全评估 b 吗? 1 : 2(或者甚至确定可能的类型 - 请记住这可能是一个昂贵的嵌套情况),但它已被预先确定为 int 类型。 3 可以表示为 short 以匹配第一种情况,但 int 不能隐式转换为 short ,只到long,所以它迈出了第一步。

因此,我们调用了 M(long, Short) 类型的 M,这是不明确的。这可以通过以下任一方法解决:

  1. 将第二个参数 3 隐式转换为 long
  2. 计算第一个参数 b ? 1 : 2看看是否可以表示为short

当出现这些选项时,如果该选项存在,运行时将始终执行第一个选项。来自 proposal您发布的内容已通过以下方式“澄清”:

The updated terminology引用(新提案是 here ),在这种情况下,C1 是上面列表中的选项 1(不是条件表达式转换 - 即隐式),而 C2 是选项 2(是条件表达式转换),因此 C1 被认为“更好”。

链接中的最后一行为我澄清了事情:

Therefore we treat the conditional expression conversion as a last resort in a cast, to preserve existing behavior.

基本上,它会猜测最适合的是什么,而在 b 中? 1 : 2,两个结果都解析为 int,因此在决定调用哪个方法时,它要做的最后事情就是将该条件评估为发现 short 效果更好,并且 intshort 都可以隐式转换为 long

当然,这可以用 M((short)(b ? 1 : 2), 3); 强制执行,但这有什么乐趣呢?

希望这有帮助。

关于C# 目标类型条件表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76302041/

相关文章:

c# - 如何给 ListBox 项目上色?

c# - $(this) 在 C# 中等效

c# - LINQ 连接具有不同类型的多个条件

c# - 应用程序启动时的线程安全

c# - 无法在WPF中单击单选按钮生成动态文本框

c# - 获取gridview一列的值

c# - 当前进程终止时运行代码?

c# - 使用异常消息属性检查特定错误是否是一种不好的做法?

c# - ASP.NET Core 2 MVC 全局异常处理不起作用

c# 如何修复 foreach ,当我尝试 console.write 列表中的元素 <string>