Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

​Написать класс для switch?

570  1 2 все
Murr патриот09.01.19 13:28
Murr
09.01.19 13:28 

Написать класс для switch?


Дано:

класс TModel.

public class Model
{
private const string _R33 = "R33";
private const string _R34 = "R34";


private readonly string ModelValue;


private Model(string pModelValue)
{
ModelValue = pModelValue;
}

public static Model R33 = new Model(_R33);
public static Model Р34 = new Model(_R34);

....

}

помимо указанного еще имплементируются операции сравнения... и немножко функций.

Все с целью возможности написания в коде:

Model currentModel = null;
if(currentMode == Model.R33) { ... }

все хорошо, все работает как должнО.


Однако есть дополнительная потребность использовать currentModel в операторе switch.


Т.е. хочется что-то вида

switch(currentModel)
{
case Model.R33:
....
break;
case Model.R34:
....
break;
}

Что-то у меня никак это не получается. Есть идеи как сделать?


#1 
Программист коренной житель09.01.19 16:45
NEW 09.01.19 16:45 
в ответ Murr 09.01.19 13:28

У тебя как всегда жесть :)


У switch'а в case'е должна быть константа.


А так, добавляешь оператор

    public static implicit operator string(Model val)
    {
      return val.ModelValue;
    }


и все работает:

      switch (currentModel)
      {
        case "R33":
          break;
        case "R34":
          break;
      }



#2 
  moose старожил09.01.19 16:53
NEW 09.01.19 16:53 
в ответ Программист 09.01.19 16:45

так просто? "работает", это - аргумент "не для нас"! нужно создать интерхвейс IMurrSwitchable, от него унаследовать базовый класс MurrSwitchableBase, а уже от него произвести эти уже. и вообще весть остальной мир : )

#3 
Murr патриот09.01.19 17:11
Murr
NEW 09.01.19 17:11 
в ответ Программист 09.01.19 16:45

У тебя как всегда жесть :)

-----

Ну а зачем по-другому? :)


У switch'а в case'е должна быть константа.

-----

Разумеется.

Я могу даже для простоты поменять доступ на паблик к _Rxx-констанстантам в классе для case TModel._R33:

Но решение, которое меня интересует, заключается в использовании инстанса класса TModel в качестве константы.

Т.е. интересует именно так, как написано - case TModel.R33: спок

Ну не хватает мне в шарпе плюснотого помещающего синтаксиса... хммм

#4 
Программист коренной житель09.01.19 17:21
NEW 09.01.19 17:21 
в ответ Murr 09.01.19 17:11

In C# 6, the match expression must be an expression that returns a value of the following types:

Starting with C# 7.0, the match expression can be any non-null expression.


Что тут еще можно добавить? :)

#5 
Murr патриот09.01.19 17:54
Murr
NEW 09.01.19 17:54 
в ответ Программист 09.01.19 17:21

Это все, разумеется, прочитано и понятно.

Остальные ограничения, как:

- енум не имеет функций

- статический элемент не является константой

- инстансе класса не является константой

- и т.п.

Все - понятно.


НО! Все, что представляет собой требуемый класс является или может быть представлено, типом инт/стринг с дополнительной функциональностью.


Вопрос - как обойти? - разумеется, сохранив нужный формат записи. улыб

Проще говоря - Как сказать системе, что R33 & R34 есть суть константы расширенного типа инт/стринг?

Базис для этого есть - енум.

#6 
Программист коренной житель09.01.19 18:23
NEW 09.01.19 18:23 
в ответ Murr 09.01.19 17:54
НО! Все, что представляет собой требуемый класс является или может быть представлено, типом инт/стринг с дополнительной функциональностью.

Ну так и имплицитно кастуй к инту/стрингу/енуму. switch это скушает.


А вот в case будь любезен записать константу.


Либо переходишь на C# 7.0 и пишешь что-то вроде такого (New C# 7 Features - Is Expression With Patterns And Switch...):

      switch (currentModel)
      {
        case R33 r33 when (r33.ModelValue == "R33"):
          break;
        case R34 r34 when (r34.ModelValue == "R34"):
          break;
      }


#7 
Программист коренной житель09.01.19 18:36
NEW 09.01.19 18:36 
в ответ Murr 09.01.19 13:28

Можешь в двух словах описать, зачем нужна такая чехарда?

#8 
Срыв покровов коренной житель09.01.19 22:38
NEW 09.01.19 22:38 
в ответ Программист 09.01.19 18:36

ну во-первых это красиво (с)


#9 
Murr патриот10.01.19 10:56
Murr
NEW 10.01.19 10:56 
в ответ Программист 09.01.19 18:23

А вот в case будь любезен записать константу.

-----

Ты просто внимания не обратил - оно и есть, по сути, константа. Только типа TModel, но без проблем совместимая с string/int.

То, что меня интересует - как это оформить...


case R33 r33 when (r33.ModelValue == "R33"):


скорее что-то вида:

case TModel currentModel when (currentModel == TModel.R33):

но что-то выглядит слишком сложно - можно и ифы аккуратно прописать...

Потому снова возвращаемся к простому вопросу - как описать константу некоего класса?

#10 
Murr патриот10.01.19 10:59
Murr
NEW 10.01.19 10:59 
в ответ Срыв покровов 09.01.19 22:38

А этого мало? Ну тогда

Во вторых - сохраняется привычная форма записи - легче читать, понимать, сопровождать.

Ради этого стоит поковырять несколько классов...

#11 
Программист коренной житель10.01.19 11:46
NEW 10.01.19 11:46 
в ответ Murr 10.01.19 10:56
Ты просто внимания не обратил - оно и есть, по сути, константа. Только типа TModel, но без проблем совместимая с string/int.

Это константа только для тебя. Для всех остальных это ни секунды не константа.

Чтобы понять, что это не константа, просто скажи мне, как должен реагировать switch, если ты напишешь так:

            public static Model R33 = new Model(_R33);
            public static Model Р34 = new Model(_R33);

?


Если бы это были бы константы, то при компилировании кода:

switch(currentModel)
{
   case Model.R33:
      ....
      break;
   case  Model.R34:
      ....
      break;
}

ты должен был бы получить ошибку.

#12 
Murr патриот10.01.19 12:37
Murr
NEW 10.01.19 12:37 
в ответ Программист 10.01.19 11:46

если ты напишешь так:

-----

Ну так Я и спрашиваю - как его писать?

Я бы с удовольствием написал:

public const TModel R33 = _R33;

но не понимаю (не знаю, не умейu) как определить класс ТМодел чтобы это было возможно.


В этом и есть вопрос. спок

#13 
Программист коренной житель10.01.19 13:33
NEW 10.01.19 13:33 
в ответ Murr 10.01.19 12:37
Я бы с удовольствием написал:
public const TModel R33 = _R33;
но не понимаю (не знаю, не умейu) как определить класс ТМодел чтобы это было возможно.

В этом и есть вопрос.
A constant expression is an expression that can be fully evaluated at compile time. Therefore, the only possible values for constants of reference types are string and a null reference.

Так что ответ на твой вопрос - никак.

#14 
Murr патриот10.01.19 13:55
Murr
NEW 10.01.19 13:55 
в ответ Программист 10.01.19 13:33

A constant expression is an expression that can be fully evaluated at compile time.

-----

Ты полагаешь, что Я этого не понимаю?

Понимаю и вполне отчетливо - не зря же Я упомянул помещающий синтаксис из плюсов - он как раз позволяет инициировать константы определяемых типов. Да, они полностью определяются при компиляции константированием обьекта.


Для решения проблемы в данном случае необходимо сделать две вещи:

- научится размещать в области хранения констант готовый к применению объект класса TModel. Можно ли его там разместить - не знаю - данные - точно можно, объекты стринг/инт - тоже. Т.е. в общем случае - можно. Вопрос - как.

- научить свитч понимать TModel, как инт/стринг. Практика синонимов - int == Int32 - и енумов в шарпе есть - т.е. проблема потенциально решаемая. Вопрос тот же - КАК?


#15 
Программист коренной житель10.01.19 14:14
NEW 10.01.19 14:14 
в ответ Murr 10.01.19 13:55
- научить свитч понимать TModel, как инт/стринг. Практика синонимов - int == Int32 - и енумов в шарпе есть - т.е. проблема потенциально решаемая. Вопрос тот же - КАК?

Ответ во 2-ом сообщении.

#16 
Murr патриот10.01.19 15:12
Murr
NEW 10.01.19 15:12 
в ответ Программист 10.01.19 14:14

Мне так кажется, что надо рыть вот тут:

https://docs.microsoft.com/en-us/dotnet/api/system.int32?v...


В плане - struct... и аттрибутов.

#17 
Murr патриот10.01.19 15:26
Murr
NEW 10.01.19 15:26 
в ответ Murr 10.01.19 15:12

Кажется вот это должно помочь:

        [Pure]
        public TypeCode GetTypeCode() {
            return TypeCode.Int32;
        }
#18 
dymanoid знакомое лицо10.01.19 19:29
dymanoid
NEW 10.01.19 19:29 
в ответ Murr 10.01.19 15:12

Начав баловаться со struct без понимания, что это такое и зачем его едят, можно очень легко прострелить себе обе ноги. Почти также легко, как в С++ или С.

#19 
Murr патриот11.01.19 10:11
Murr
NEW 11.01.19 10:11 
в ответ dymanoid 10.01.19 19:29
без понимания

-----

А с пониманием?


Вроде как оно и то, но пока все еще не выходит...


#20 
1 2 все