Loading...
Lexinor avatar Lexinor 0 Точки

Switch-Case с Интервал от стойности?

Здравейте на Всички Програмисти!

Интересуваме ме нещо съвсем Простичко!

Искам да напиша програма на C#, която да ползва оператора Switch-Case. Но не за едан определена стойност, а за интервал от Стойности!

Например:

1-13 - Дете

14-19 - Тийнейджър

20-35 - Младеж

36-65 - Зрял Човек

Над 66 - Възрастен

Мерси Предварително!

Тагове:
0
C# MVC Frameworks - ASP.NET
r3v3nan7 avatar r3v3nan7 365 Точки

Я виж това ще ти помогне ли http://pastebin.com/vBqvQMXJ Извинявай сега видях , че на case11 имам правописна грешка. Трябва да да е :   , а не "  

0
26/01/2016 15:41:05
moholovka avatar moholovka 169 Точки

Ми то принципно може, но едва ли би искал. С един бърз рисърч ми попадна този резултат, видимо идеален --> http://pastebin.com/ZbhRZeVb

1
26/01/2016 15:41:38
enevlogiev avatar enevlogiev 1168 Точки

Найс ; )

0
quickben avatar quickben 966 Точки

И какво му е идеалното на този подход, заделя се много излишна памет с тази структура, четимоста я няма никаква, LINQ dependancy, и е по-бавно.

Вярно самото условие не е добро ама чак от такива извращения за толкова семпъл проблем няма смисъл, най-малкото KISS принципа не са го измислили за кеф ;)

Ако трябва в реален проект да сетвам някаква такава стойност, аз лично бих го направил в сетъра на Age-a да се сетва съответното property според стойноста на age-a, по-този начин се смята само един път(при сестването на Age-a) и после само си го взимаш когато ти потрябва, и като се замисля, по-този начин ако си направил функционалност възраста да се увеличава с едно на рождения ти ден, пак ще се мине през сетъра и през логиката която сетва дали си Teen, Minor и там другите :) -> което 100% нарушава някой принцип, но няма софтуер който да ги спазва всичките стриктно, просто е почти невъзможно всичко да е перфектно.

-3
26/01/2016 16:43:35
RoYaL avatar RoYaL Trainer 6849 Точки

quickben,

Позволи ми да не се съглася с твърдението ти. Това със сетърите важи за някои ситуации, но не и за конкретната. Искаш да изпринтиш на конзолата/уеб страницата/някъде си "Teen" когато годините са между 13 и 19. Как би го реализирал?

Що се отнася до паметта, също не си особено прав. По-големите switch/cases се привеждат на компилационно ниво до dictionary lookups. Т.е. дали ще заделиш ръчно Dictionary или ще напишеш по-голям switch/case имаш еднакво заделена памет - такава за типът данни речник. Отделно ще заделиш за стойностите вътре. Делегатите са референтни типове така че се пазят 4/8 байта (според зависимост от архитектурата) за всеки делегат + 4 байта за оценяването на делегата до максимум 12 байта. Функциите също имат едни 8 байта overhead. 

Т.е. между стандартен switch/case и решението по-горе имаме много малко overhead. И според мен не четимостта не е по-лоша от if/elseif.

В C# за съжаление обаче не можеш да напишеш case-ове, които не са константи. Това е възможно в други езици, но не и тук. Съответно няма как да ползваме switch. Вариантите са if-ове, които са бързи заради джъмповете и хештаблицата, която също е бърза, просто има едни 12 байта повече памет в най-лошия случай. Т.е. имаме само memory overhead. Ако реализираме изцяло ООП (с полиморфизъм) и някакво динамично парсване (евентуално рифлекшън, за да вдигнем обекта без кейз) ще имаме отново по толкова байтове за референтен тип + overhead-а от рифлекшъна.

Но тук ще нарушим KISS принципа. Да си направя клас Teen, който ще се вдигне при определено условие си е гига overkill щом просто искам да изпринтирам думичката "teen".

Така, че вариантът с този речник според мен е толкова приемлив колкото и elseif.

1
quickben avatar quickben 966 Точки

Switch-Case-a според мен не е правилната условна конструкция за целта, switch-a е най-подходящ когато искаш различно поведение за всяка стойност, а не както е сега => еднакво поведение за range от стойности.

If, else if, else е по-подходяща за този случай, иначе ето така( http://pastebin.com/zRt9ryG4 ) можеш да го направиш, но е много грозно.

0
Lexinor avatar Lexinor 0 Точки

Благодаря зя всички Отговори! Мога да си го направя със Switch-Case и вътре да сложа If, но ме интересува Няма ли нещо Бързо като Например:

1..13 - Dete

14..19 - Teen

20..35 - Mladej

35-65  - Chovek

Default - Vyzrasten

Imashe takava Vyzmojnost na Pascal predi vreme! ;)

0
26/01/2016 15:49:39
RoYaL avatar RoYaL Trainer 6849 Точки

Паскал го може тва, делфи също, някои от стандартите на С, функционални езици като Скала и Котлин, дори Visual Basic (..6 и .NET), но, заради специфициките на оптимизацията на компилатора това не го може C#.

0
StaVykoV avatar StaVykoV 169 Точки

Switch-a работи с константи, тоест не можеш да правиш проверки в case-a. Винаги можеш да си изпишеш кейсове за всяка конкретна възраст де :Д

0
RoYaL avatar RoYaL Trainer 6849 Точки

Можеш да реализираш рейнджове с няколко контролни структурки.

Например една матрица която ти дефинира рейнджовете:

            int[,] ranges = new int[5,2];
            ranges[0, 0] = 1;
            ranges[0, 1] = 13;
            ranges[1, 0] = 14;
            ranges[1, 1] = 19;

Евентуално един масив, чиито ключове, отговарят на редовете в матрицата (0..5) с имената на възрастите

            string[] ageNames = {"Child", "Teen", "Yougnster", "Regular", "Adult"};

След това с един цикъл обикаляш рейнджовете в матрицата и добавяш в един списък от стрингове съответната стойност.

            List<string> ages = new List<string>();
            for (int i = 0; i < ranges.GetLength(0); i++)
            {
                for (int age = ranges[i, 0]; age <= ranges[i, 1]; age++)
                {
                    ages.Add(ageNames[i]);
                }
            }

Така ще резултираш в списък който изглежда:

1 => "Child",

2 => "Child",

3 => "Child",

...

13 => "Child",

14 => "Teen",

...

После когато някой ти въведе възраст, например 16, ти ще я луукъпнеш в списъка

            int userAge = int.Parse(Console.ReadLine());
            string userAgeName = ages[userAge];
            Console.WriteLine(userAgeName);

Тук при вход 16 ще върне "Teen".

Ще ти трябват допълнителни проверки дали не си излязъл извън индексите на списъка. Също нулевия индекс е хубаво да го запълниш с някакъв друг стринг, като например "Newborn" :)

Какви са предимствата на това решение:

1. Последния код не се променя. Потребителят въвежда стойност и ти я обработваш. При обработването не пишеш допълнителната логика. Това може да ти е презентационната логика

2. Бизнес логиката е достатъчно да бъде променена, за да работи презентационната. Добавяш нов рейндж и нова стойност за този рейндж:

            ranges[5, 0] = 101;
            ranges[5, 1] = 200;
            ageNames[5] = "Hundreds";

Какви са недостатъците:

1. Нямаш абсолютно никаква причина да го правиш така, ако стойностите ти са в кода. Абсолютно същото е като да отидеш и да добавиш нов if/elseif.

2. Заемаш повече памет

3. Ако имаш възрасти до 1,000,000 ще завъртиш цикъл огромен брой цикли, за да напълниш списъка

Какво е най-голямото предимство:

- Данните могат да не са в кода, а да са в база данни и съответно да се прави директен lookup на базата: SELECT AgeName FROM Ages WHERE AgeStart <= INPUT_AGE AND AgeEnd >= INPUT_AGE

В заключение: Нямаш добра причина да го правиш по различен начин от if/elseif ако имаш само тези 5 сценария и те никога forever and ever, amen, няма да се променят.

Поздрави,

Иван

1
26/01/2016 18:57:40
LoKSET avatar LoKSET 160 Точки

В Javascript по принцип може да се направи следното (и аз първоначално бях учуден че се прави така, но всъщност е логично):

            var age = 33;
            var group;

            switch (true)
            {
                case (1 <= age && age <=13): group = "child";
                    break;
                case (14 <= age && age <=19): group = "teen";
                    break;
                    и т.н.
            }

Това обаче не е възможно в C# просто защото кейсовете трябва да са константи.

-1
27/01/2016 11:58:50
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.