Подтвердить что ты не робот

Корпус выключателя типа С#

Возможный дубликат:
С# - Есть ли более эффективная альтернатива этому типу включения?

Здравствуйте, предположим, я получаю большой тип if if else. это там способ сделать это с корпусом коммутатора?

Пример:

function test(object obj)
{
if(obj is WebControl)
{

}else if(obj is TextBox)
{

}
else if(obj is ComboBox)
{

}

и т.д.

Я хотел бы создать что-то вроде

switch(obj)
{
case is TextBox:
break;
case is ComboBox:
break;

}

}

4b9b3361

Ответ 1

Нет.

http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx

Мы получаем много запросов на дополнения к языку С#, и сегодня я собираюсь поговорить об одном из наиболее распространенных - включении типа. Переключение типа выглядит довольно полезной и простой функцией: добавьте подобную переключателю конструкцию, которая включает тип выражения, а не значение. Это может выглядеть примерно так:

switch typeof(e) { 
        case int:    ... break; 
        case string: ... break; 
        case double: ... break; 
        default:     ... break; 
}

Этот тип оператора был бы чрезвычайно полезен для добавления виртуального метода, такого как диспетчеризация, по непересекающейся иерархии типов или по иерархии типов, содержащей типы, которые вам не принадлежат. Увидев пример, подобный этому, вы можете легко сделать вывод, что эта функция будет простой и полезной. Это может даже заставить вас задуматься: "Почему эти ленивые дизайнеры языка С# # &% $ просто не облегчат мою жизнь и не добавят эту простую, экономящую время функцию?"

К сожалению, как и многие "простые" языковые функции, переключение типов не так просто, как кажется на первый взгляд. Проблемы начинаются, когда вы смотрите на более важный и не менее важный пример, подобный этому:

class C {}
interface I {}
class D : C, I {}

switch typeof(e) {
case C: … break;
case I: … break;
default: … break;
}

Ссылка: https://blogs.msdn.microsoft.com/peterhal/2005/07/05/many-questions-switch-on-type/

Обновление С# 7

Да: источник

switch(shape)
{
    case Circle c:
        WriteLine($"circle with radius {c.Radius}");
        break;
    case Rectangle s when (s.Length == s.Height):
        WriteLine($"{s.Length} x {s.Height} square");
        break;
    case Rectangle r:
        WriteLine($"{r.Length} x {r.Height} rectangle");
        break;
    default:
        WriteLine("<unknown shape>");
        break;
    case null:
        throw new ArgumentNullException(nameof(shape));
}

Ответ 2

Следующий код работает более или менее, так как можно было бы ожидать, что тип-переключатель будет смотреть только на фактический тип (например, то, что возвращается GetType()).

public static void TestTypeSwitch()
{
    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"); 
}

Вот механизм, необходимый для его работы.

public class TypeSwitch
{
    Dictionary<Type, Action<object>> matches = new Dictionary<Type, Action<object>>();
    public TypeSwitch Case<T>(Action<T> action) { matches.Add(typeof(T), (x) => action((T)x)); return this; } 
    public void Switch(object x) { matches[x.GetType()](x); }
}

Ответ 3

Да, вы можете включить имя...

switch (obj.GetType().Name)
{
    case "TextBox":...
}

Ответ 4

Здесь вариант, который остается как истинный, я мог бы сделать это требование OP, чтобы иметь возможность включать тип. Если вы достаточно сильно прищурились, это почти похоже на реальный оператор switch.

Вызывающий код выглядит следующим образом:

var @switch = this.Switch(new []
{
    this.Case<WebControl>(x => { /* WebControl code here */ }),
    this.Case<TextBox>(x => { /* TextBox code here */ }),
    this.Case<ComboBox>(x => { /* ComboBox code here */ }),
});

@switch(obj);

x в каждой лямбда выше строго типизирован. Не требуется литье.

И для выполнения этой магической работы вам понадобятся эти два метода:

private Action<object> Switch(params Func<object, Action>[] tests)
{
    return o =>
    {
        var @case = tests
            .Select(f => f(o))
            .FirstOrDefault(a => a != null);

        if (@case != null)
        {
            @case();
        }
    };
}

private Func<object, Action> Case<T>(Action<T> action)
{
    return o => o is T ? (Action)(() => action((T)o)) : (Action)null;
}

Почти приносит слезы на глаза, верно?

Тем не менее, он работает. Наслаждайтесь.

Ответ 5

Простейшей задачей может быть использование динамики, т.е. вы определяете простые методы, например, в Yuval Peled:

void Test(WebControl c)
{
...
}

void Test(ComboBox c)
{
...
}

Тогда вы не можете напрямую вызвать Test (obj), потому что во время компиляции выполняется разрешение перегрузки. Вы должны назначить свой объект динамическому, а затем вызвать метод Test:

dynamic dynObj = obj;
Test(dynObj);