C#8.0 switch 语句和局部变量

C#8.0 switch statements and local variables

试图了解 switch 语句的新 C#8.0 语法的限制我正在尝试将一些旧代码从 C#7.0 转换为 C#8.0。我想使用本地引入的变量(模式匹配),但显然我做错了。

作为参考,propertySelectorExpression 的类型为 Expression<Func<TObject, TProperty>> propertySelectorExpression

旧代码:

PropertyInfo propertyInfo = null;
switch (propertySelectorExpression.Body)
{
    case MemberExpression me:
        propertyInfo = me.Member as PropertyInfo;
        break;
    case UnaryExpression ue:
        propertyInfo = (ue.Operand as MemberExpression)?.Member as PropertyInfo;
        break;
}

新代码(尝试,未编译):

PropertyInfo propertyInfo = null;
propertyInfo = switch (propertySelectorExpression.Body)
{
    MemberExpression me => me.Member as PropertyInfo,
    UnaryExpression ue => (ue.Operand as MemberExpression)?.Member as PropertyInfo
}

PropertyInfo propertyInfo = null;
switch (propertySelectorExpression.Body)
{
    MemberExpression me => propertyInfo = me.Member as PropertyInfo,
    UnaryExpression ue => propertyInfo = (ue.Operand as MemberExpression)?.Member as PropertyInfo
}

我做错了什么或假设错了什么?

试试这个:

PropertyInfo propertyInfo = null;
propertyInfo = propertySelectorExpression.Body switch
{
    MemberExpression me => me.Member as PropertyInfo,
    UnaryExpression ue => (ue.Operand as MemberExpression)?.Member as PropertyInfo
}

更多信息请参阅documentation关于新的开关表达式格式

下面的代码片段应该可以工作,变量出现在 switch 关键字之前

var propertyInfo = propertySelectorExpression.Body switch
{
    MemberExpression me => (me.Member as PropertyInfo),
    UnaryExpression ue => ((ue.Operand as MemberExpression)?.Member as PropertyInfo),
    _ => null
};

您必须管理默认值,在您的案例中为空。 default 案例被替换为 _ 丢弃。

您混淆了 switch 的两种用法的语法。

你有:

  • 切换语句
  • 开关表达式

开关表达式的语法是<expression> switch { <patterns> },所以这应该编译:

PropertyInfo propertyInfo = null;
propertyInfo = propertySelectorExpression.Body switch // <-- noticed the switched order
{
    MemberExpression me => me.Member as PropertyInfo,
    UnaryExpression ue => (ue.Operand as MemberExpression)?.Member as PropertyInfo
}

(尽管编译器会警告您 switch 表达式无法处理所有可能的输入)

switch statement 的语法(你问题中的最后一个代码示例)使用 case 而不是 lambda 语法,所以这应该编译:

PropertyInfo propertyInfo = null;
switch (propertySelectorExpression.Body)
{
    case MemberExpression me:
        propertyInfo = me.Member as PropertyInfo;
        break;
    case UnaryExpression ue:
        propertyInfo = (ue.Operand as MemberExpression)?.Member as PropertyInfo;
        break;
}