С# переключатель типа
Возможный дубликат:
С# - Есть ли более эффективная альтернатива этому типу включения?
С# не поддерживает включение типа объекта. Каков наилучший образец имитации этого:
switch (typeof(MyObj))
case Type1:
case Type2:
case Type3:
Спасибо!
Ответы
Ответ 1
Я обычно использую словарь типов и делегатов.
var @switch = new Dictionary<Type, Action> {
{ typeof(Type1), () => ... },
{ typeof(Type2), () => ... },
{ typeof(Type3), () => ... },
};
@switch[typeof(MyType)]();
Это немного менее гибко, так как вы не можете проваливать дела, продолжать и т.д. Но я все равно редко делаю это.
Ответ 2
В этом вопросе есть простой ответ на Случай переключения на тип С#, в котором используется словарь типов для поиска лямбда-функции.
Вот как это можно использовать
var ts = new TypeSwitch()
.Case((int x) => Console.WriteLine("int"))
.Case((bool x) => Console.WriteLine("bool"))
.Case((string x) => Console.WriteLine("string"));
ts.Switch(42);
ts.Switch(false);
ts.Switch("hello");
}
Существует также обобщенное решение этой проблемы с точки зрения сопоставления шаблонов (оба типа и условия проверки во время выполнения) в соглашении о сопоставлении/шаблоне
var getRentPrice = new PatternMatcher<int>()
.Case<MotorCycle>(bike => 100 + bike.Cylinders * 10)
.Case<Bicycle>(30)
.Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
.Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
.Default(0);
var vehicles = new object[] {
new Car { EngineType = EngineType.Diesel, Doors = 2 },
new Car { EngineType = EngineType.Diesel, Doors = 4 },
new Car { EngineType = EngineType.Gasoline, Doors = 3 },
new Car { EngineType = EngineType.Gasoline, Doors = 5 },
new Bicycle(),
new MotorCycle { Cylinders = 2 },
new MotorCycle { Cylinders = 3 },
};
foreach (var v in vehicles)
{
Console.WriteLine("Vehicle of type {0} costs {1} to rent", v.GetType(), getRentPrice.Match(v));
}
Ответ 3
Обновление: это исправлено в С# 7.0 с сопоставлением с образцом
switch (MyObj)
case Type1 t1:
case Type2 t2:
case Type3 t3:
Старый ответ:
Это дыра в игре С#, пока нет серебряной пули.
Вы должны гуглить по "шаблону посетителя", но он может быть немного тяжелым для вас, но все же кое-что вы должны знать.
Вот еще один пример использования Linq: http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx.
В противном случае что-то в этом роде может помочь
// nasty..
switch(MyObj.GetType.ToString()){
case "Type1": etc
}
// clumsy...
if myObj is Type1 then
if myObj is Type2 then
и т.п.
Ответ 4
Я сделал это один раз с обходным решением, надеюсь, что это поможет.
string fullName = typeof(MyObj).FullName;
switch (fullName)
{
case "fullName1":
case "fullName2":
case "fullName3":
}
Ответ 5
Я использовал эту форму switch-case
в редких случаях. Даже тогда я нашел другой способ сделать то, что хотел. Если вы обнаружите, что это единственный способ выполнить то, что вам нужно, я бы рекомендовал решение @Mark H.
Если это будет своего рода процесс принятия решения factory, есть более эффективные способы сделать это. В противном случае, я действительно не понимаю, почему вы хотите использовать переключатель типа.
Вот небольшой пример, расширяющий решение Mark. Я думаю, что это отличный способ работать с типами:
Dictionary<Type, Action> typeTests;
public ClassCtor()
{
typeTests = new Dictionary<Type, Action> ();
typeTests[typeof(int)] = () => DoIntegerStuff();
typeTests[typeof(string)] = () => DoStringStuff();
typeTests[typeof(bool)] = () => DoBooleanStuff();
}
private void DoBooleanStuff()
{
//do stuff
}
private void DoStringStuff()
{
//do stuff
}
private void DoIntegerStuff()
{
//do stuff
}
public Action CheckTypeAction(Type TypeToTest)
{
if (typeTests.Keys.Contains(TypeToTest))
return typeTests[TypeToTest];
return null; // or some other Action delegate
}