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

问题描述 投票:0回答:2

如果我有像

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

对于带有fall-through的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;
    }
}

我明白为什么,但我想知道,这是模式匹配的限制,即你不能在复合

if
语句中使用它,或者是否有正确的方法来构造该语句,以便我可以使用任一变量(例如通过将它们初始化为空,这样我至少可以进行空检查)?

c# .net pattern-matching
2个回答
6
投票

C# 9 起,您可以使用...来完成此操作

切换语句:

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

切换表情:

var bar = o switch
{
    int or string or Guid => o.ToString() 
};

5
投票

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

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

if (currentShape is AutoShape autoShape)
{
    // do something with autoshapes
}

但是,您的另一个示例表明,条件之间可能存在一些共同的功能。

ToString()
可能是一个坏例子,你可以这样做:

string? bar = o.ToString(); // doesn't matter the type of object

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

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
    };

您还询问变量是否可以用空值初始化,以便您可以进行空值检查。 这对于像

int
这样的不可空类型不起作用。 对于可为 null 的类型,它会导致无关的比较操作(首先测试类型并分配 null,其次测试 null)。 保持表达式分离可确保最少的操作数量。

© www.soinside.com 2019 - 2024. All rights reserved.