Я недавно дивився на F #, і хоча я швидше за все не стрибну огорожу, але він безумовно виділяє деякі області, де C # (або підтримка бібліотеки) може полегшити життя.
Зокрема, я думаю про можливість узгодження шаблону F #, що дозволяє отримати дуже багатий синтаксис - набагато виразніше, ніж поточний перемикач / умовні еквіваленти C #. Я не буду намагатися наводити прямий приклад (мій F # не до цього), але коротше це дозволяє:
- збігаються за типом (з повною перевіркою на дискриміновані союзи) [зауважте, це також підводить тип для пов'язаної змінної, надаючи доступ членам тощо]
- відповідати присудком
- комбінації вищевказаних (і, можливо, деяких інших сценаріїв, про які я не знаю)
Хоча C # було б прекрасно врешті-решт запозичити [ах] частину цього багатства, я тим часом переглядав, що можна зробити під час виконання - наприклад, досить легко збити деякі об'єкти, щоб дозволити:
var getRentPrice = new Switch<Vehicle, int>()
.Case<Motorcycle>(bike => 100 + bike.Cylinders * 10) // "bike" here is typed as Motorcycle
.Case<Bicycle>(30) // returns a constant
.Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
.Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
.ElseThrow(); // or could use a Default(...) terminator
де getRentPrice - функція <транспортний засіб, int>.
[зауважте - можливо, Switch / Case тут неправильні терміни ... але це показує ідею]
Для мене це набагато зрозуміліше, ніж еквівалент із використанням повторного if / else, або складеного потрійного умовного (який стає дуже безладним для нетривіальних виразів - дужки в галас). Це також дозволяє уникнути багато кастингу та дозволяє просте розширення (безпосередньо або через методи розширення) на більш конкретні збіги, наприклад, відповідність InRange (...), порівнянна з VB Select ... Case "x To y "використання.
Я просто намагаюся оцінити, чи люди думають, що від подібних конструкцій (за відсутності мовної підтримки) багато користі?
Зауважте також, що я грав з трьома варіантами вищезазначеного:
- версія Func <TSource, TValue> для оцінки - порівнянна зі складеними потрійними умовними твердженнями
- версія Action <TSource> - порівнянна з if / else if / else if / else if / else
- версія Expression <Func <TSource, TValue >> - як перша, але використана довільними постачальниками LINQ
Крім того, використання версії на основі Expression дозволяє переписати дерево Expression, по суті, вклавши всі гілки в єдиний складений умовний вираз, а не використовувати повторний виклик. Я нещодавно не перевіряв, але в деяких ранніх побудовах Entity Framework я, мабуть, згадую, що це потрібно, оскільки це не дуже сподобалось InvocationExpression. Це також дозволяє більш ефективно використовувати LINQ-до-об'єктів, оскільки це дозволяє уникнути повторних викликів делегувати - тести показують відповідність, як описано вище (використовуючи форму вираження), виконуючись з однаковою швидкістю [фактично швидше, насправді] порівняно з еквівалентною C # складений умовний вислів. Для повноти, заснована на Func <...> версія займала 4 рази довше, ніж умовна заява C #, але все ще дуже швидка і навряд чи буде головним вузьким місцем у більшості випадків використання.
Я вітаю будь-які думки / введення / критику / тощо щодо вищесказаного (або щодо можливостей багатшої підтримки мови # C ... ось сподіваюсь ;-p).
switch-case
заяви. Не зрозумійте мене неправильно, я думаю, що в ньому є місце, і я, мабуть, шукатиму спосіб здійснити.