复合 if 语句和带有失败的开关中的模式匹配

ror*_*.ap 6 .net c# pattern-matching

如果我有一个像这样的 if 语句,我无法在正文中if (currentShape is ITable table || currentShape is AutoShape autoShape)使用tableor ,因为我收到CS0165 编译器错误autoShape

对于带有失败的 switch 语句也是如此:

void Foo(object o)
{
    switch (o)
    {
        case int i:
        case string s:
        case Guid g:
            string bar = i?.ToString() ?? s?.ToString() ?? g.ToString(); // cannot use i, s, or g.
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

我明白为什么,但我想知道,这是模式匹配的限制,即您不能在复合if语句中使用它,或者是否有正确的方法来构造语句,以便我可以使用任一变量(例如,通过将它们初始化为null 所以我至少可以做一个空检查)?

Pet*_*ala 6

从 C# 9 开始,您可以执行以下操作

带 switch 语句

switch (o)
{
    case object probe when probe is int or string or Guid:
        string bar = probe.ToString();
        break;
}    
Run Code Online (Sandbox Code Playgroud)

并带有 switch 表达式

var bar = o switch
{
    int or string or Guid => o.ToString() 
};
Run Code Online (Sandbox Code Playgroud)


Mat*_*int 5

如果确实有两个单独的事情需要实现,则不要组合模式表达式。两个单独的 if 语句效果会更好。

if (currentShape is ITable table)
{
    // do something with tables
}

if (currentShape is AutoShape autoShape)
{
    // do something with autoshapes
}
Run Code Online (Sandbox Code Playgroud)

但是,您的另一个示例说明条件之间可能存在一些共同的功能。 ToString()可能是一个坏例子,你可以这样做:

string? bar = o.ToString(); // doesn't matter the type of object
Run Code Online (Sandbox Code Playgroud)

但假设您可能希望根据类型应用不同的格式。在这种情况下,switch 表达式可能会很有用。例如:

string? bar =
    o switch
    {
        int i => i.ToString("D3"), // three digits
        Guid g => g.ToString("N"), // no hyphens
        string s => s,    // no need to call ToString on a string
        _ => o.ToString() // all other types
    };
Run Code Online (Sandbox Code Playgroud)

您还询问变量是否可以用空值初始化,以便可以进行空值检查。这对于不可空类型(例如int. 对于可为 null 的类型,它会导致无关的比较操作(首先测试类型并分配 null,其次测试 null)。保持表达式分离可确保最少的操作数。