C # 8.0 переключать выражения на основе типа ввода

#c# #c#-8.0

#c# #c #-8.0

Вопрос:

Возможно ли создать switch expression в C # 8 на основе типа ввода?

Мои входные классы выглядят так:

 public class A1
{
    public string Id1 {get;set}
}

public class A2 : A1
{
    public string Id2 {get;set}
}

public class A3 : A1
{
    public string Id3 {get;set;}
}
  

Я хочу запускать разные методы на основе типа ввода ( A1 , A2 , или A3 ):

 var inputType = input.GetType();
var result = inputType switch
{
       inputType as A1 => RunMethod1(input); // wont compile, 
       inputType as A2 => RunMethod2(input); // just showing idea
       inputType as A3 => RunMethod3(input);

}
  

Но это не сработает. Есть идеи, как создать выражение переключения или переключения на основе типа ввода?C

Комментарии:

1. Попробуйте сначала запустить переключатель с наиболее специфичным типом (A3) и перейти к наименее специфичному (A1)

2. Но мой код не компилируется, я просто показал идею

3. О, да, я вижу это сейчас, замените как есть

Ответ №1:

Вы могли бы использовать сопоставление с образцом, сначала проверив наиболее конкретные типы.

GetType не требуется:

 var result = input switch
{
    A2 _ => RunMethod1(input),
    A3 _ => RunMethod2(input),
    A1 _ => RunMethod3(input)    
};
  

Однако более OO-подход заключался бы в определении метода для самих типов:

 public class A1
{
    public string Id1 { get; set; }
    public virtual void Run() { }
}

public class A2 : A1
{
    public string Id2 { get; set; }
    public override void Run() { }
}
  

Тогда это просто:

 input.Run();
  

Комментарии:

1. Хорошая идея, но ваш код не компилируется. Я получаю эту ошибку: The Pattern has already been handled by previous arm of switch expression

2. @michasaucer Для меня он отлично компилируется: dotnetfiddle.net/1dGHUz

3. Ваш ответ тоже компилируется для меня… Итак, теперь мне нужно выяснить, почему это не используется в моем сценарии (я только что вставил базовый пример здесь в SO). Спасибо!

4.@JohnathanBarclay если вы измените экземпляр на A2 или A3 он не будет компилироваться, см. Второй пункт «примечания» в моем ответе.

5. @Jamiec Да, я, вероятно, должен был явно ввести переменную в моей скрипке.

Ответ №2:

Вы можете, но в подобной иерархии наследования вам нужно начинать с наиболее конкретного и двигаться вниз к наименьшему:

 A1 inputType = new A2();
var result = inputType switch
{
    A3 a3 => RunMethod(a3),
    A2 a2 => RunMethod(a2),
    A1 a1 => RunMethod(a1)
};
  

Обратите внимание, что

  • inputType является экземпляром, а не экземпляром Type
  • inputType вводится как базовый класс, но может быть экземпляром любого A1-3. В противном случае вы получите ошибку компилятора.

Живой пример: https://dotnetfiddle.net/ip2BNZ