Nano Hash - криптовалюты, майнинг, программирование

Включить регистр для типа c #

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

Привет, предположим, я получил большое 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;

}

}



Ответы:


1

Обновить C # 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));
}

До C # 7

No.

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

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

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

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

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

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/

31.08.2011
  • Я не согласен с разработчиками языка. Во многих языках есть переключатели типов. В любом случае, пока нет переключателя типов, достаточно просто реализовать переключатель см. stackoverflow.com/questions/7252186/switch-case-on-type-c/ 04.09.2011
  • Где остальной ответ? теперь он заканчивается на ..., например, так: 18.10.2011
  • Меня не волнует, что он говорит. Это просто'. Скорее было бы, если бы они с самого начала проектировали C # лучше. Я слышал, что для всей грамматики есть 10+ проходов :(. Switch - это, по сути, obj.member. Vtable - недоступный член. Если его обрабатывают как значение (например, int), вы можете его использовать. 05.01.2013
  • @ oɔɯǝɹ Я предоставил ссылку на источник моей информации, если вы хотите прочитать всю статью. Я не собирался вставлять цитату полностью, если вы можете прочитать ее в источнике. Ответ прост: нет. 05.01.2013
  • Добавил остальной ответ :) 30.04.2016
  • ОБНОВЛЕНИЕ для всех, кто попадает на эту страницу: ответ - да, начиная с C # 7. Теперь вы можете полностью писать случаи переключения над типами. См .: blogs.msdn .microsoft.com / dotnet / 2016/08/24 / 14.05.2017
  • Стив: Пожалуйста, обновите свой ответ. Это уже не актуально. 17.11.2017
  • @LanderV, тогда я должен быть сбит с толку, потому что мне кажется, что сопоставление с образцом ВСЕГДА принимает экземпляр, а не тип, поэтому вы все равно не можете включить тип AFAICT. 03.05.2019
  • Это НЕ дубликат этого вопроса - он спрашивает об экземпляре, это спрашивает о включении типа. Что невозможно. Я пробовал эту реализацию с сопоставлением с образцом C # 8, но она никогда не соответствует: return typeof(T) switch {IThingOne _ => new ThingOne(), _ => throw new NotImplementedException()}; :( 03.05.2019
  • Здесь необходимо понимать, что, хотя Microsoft не ошибается в реализации переключателя сложных типов, нет необходимости из-за этого усложнения устранять возможность работы с примитивными типами. То, что я не могу все делать, не означает, что я вообще ничего не могу. 22.11.2019
  • Тип включения теперь поддерживается в C # 9 и выше, обновите свой ответ 07.12.2020

  • 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); }
    }
    
    04.09.2011
  • Очень интересное решение ... в каком-то смысле это ужасно :) ... но в каком-то смысле это невероятно (особенно в том случае, если какой-то другой внешний разработчик может подключиться к этой системе, создав класс X, а затем предоставив 'что для делать с логикой X ... вроде как mini DI / Ioc) 05.09.2011
  • Когда в чем-то это ужасно? 19.07.2013
  • @cdiggins, есть ли способ добавить что-то вроде значения по умолчанию или ни одного из них? 19.07.2013
  • Ух ты!! Очень интересное решение! 06.11.2014
  • @cdiggins, хотя это умный камуфляж, но не лучше, чем использование if, else if, как он будет вести себя, когда он будет последовательно проходить через операторы Case 13.02.2016
  • @ Pedro77 Да, вы можете проверить наличие ключа в методе Switch, и если он не существует, используйте typeof (Object) для случая по умолчанию в конце цепочки случаев 13.02.2016
  • Это не работает с производными типами. Фигово. 19.06.2019

  • 3

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

    switch (obj.GetType().Name)
    {
        case "TextBox":...
    }
    
    31.08.2011
  • К вашему сведению, это решение не будет работать, если ему дать public class MyCustomTextBox : TextBox 31.08.2011
  • Вы бы просто сделали case "TextBox: "MyCustomTextBox": ... 31.08.2011
  • Конечно, если вы знаете все возможные подклассы. 31.08.2011
  • Я полагаю, что человек, пишущий этот код, пишет его по какой-то причине ... и знает все подклассы: P - Пример, он, вероятно, пытается добавить имя CssClass для всех текстовых полей, а затем для всех датпикеров или чего-то еще. 31.08.2011
  • Я очень внимателен в случае разоблачения @Steve, так что это не решение для меня. Благодарность :-( 31.08.2011
  • @Timothy Я полагаю, что человек, пишущий этот код, пишет его по какой-то причине ... и знает все подклассы - маловероятно, что он будет знать подклассы, которые еще не были написаны. 05.09.2011
  • Я знаю, что это старый, но мне нравится ваш ответ, и я согласен с вашим рассуждением о том, что человек, пишущий это, будет знать все свои подклассы, если он использует оператор switch для указания действий для определенных классов, а не всех детские классы 16.05.2013
  • этот код - обходной путь, поскольку он не проверяется во время компиляции, он может легко создать недостижимый код. 17.09.2013
  • Не используйте строки и ожидайте рефакторинга! :) 03.05.2019

  • 4

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

    Вызывающий код выглядит так:

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

    У тебя почти слезы на глазах, правда?

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

    31.08.2011
  • +1 однозначно умно. Не уверен, что я бы использовал его в производственном коде (не то чтобы с ним что-то не так само по себе). 31.08.2011
  • Новые [] {и} излишни. 04.09.2011
  • Хе-хе, милый. Я согласен с @Steve, но +1 04.09.2011
  • @cdiggins - я согласен, что они лишние, но я написал код, позволяющий отказаться от инициализатора массива в пользу списка параметров. Синтаксис инициализатора массива становится немного более читаемым, IMHO, если у вас более трех параметров. И это больше похоже на нормальный синтаксис switch - если прищуриться! 05.09.2011
  • @Enigmativity понравилось это умное решение, но, когда я прищурился, нашел его, так же, как если бы, иначе, если цикл, а не действительно случай переключения, это снова будет связывать вызовы, пока не найдет первый случай, который не равен нулю. Но согласился красивый камуфляж. 13.02.2016

  • 5

    Самым простым может быть использование динамики, то есть вы определяете простые методы, как в ответе Ювала Пеледа:

    void Test(WebControl c)
    {
    ...
    }
    
    void Test(ComboBox c)
    {
    ...
    }
    

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

    dynamic dynObj = obj;
    Test(dynObj);
    
    31.08.2011
  • Классное решение! Получил свой голос :-) 03.07.2012
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..