Паттерн матчинг
От: snaphold  
Дата: 02.03.23 09:05
Оценка:
Можно ли написать такую конструкцию через Паттерн матчинг реализовать?
Идея что по свойству надо создать нужный тип объекта из иерархии и вызвать специфический метод для данного типа

public Shape CreateShape(string name, int area)
{
     Shape = switch
     {
       "circle" => { 
             var circle = new Circle(area);  
                     circle.CalculateSomethingSpecialForCircle();
                     return circle;
                   }, 
        "square" => { 
             var square= new Square(area);  
                     square.CalculateSomethingSpecialForSquare();
                     return square;
                   }
    }
}
Re: Паттерн матчинг
От: Baiker  
Дата: 02.03.23 09:29
Оценка: +2 -1
Здравствуйте, snaphold, Вы писали:

S>Можно ли написать такую конструкцию через Паттерн матчинг реализовать?

S>Идея что по свойству надо создать нужный тип объекта из иерархии и вызвать специфический метод для данного типа
S> circle.CalculateSomethingSpecialForCircle();

Паттерн-матчинг тут вообще не причём, тут рефлексия нужна. Как вариант (если это возможно), назвать "специфический метод" у всех одинаково и тупо перегрузить! Классическое применение virtual.
Re: Паттерн матчинг
От: Ночной Смотрящий Россия  
Дата: 02.03.23 09:32
Оценка:
Здравствуйте, snaphold, Вы писали:

S>Можно ли написать такую конструкцию через Паттерн матчинг реализовать?


Можно. В чем проблема?
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: Паттерн матчинг
От: snaphold  
Дата: 02.03.23 09:44
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, snaphold, Вы писали:


S>>Можно ли написать такую конструкцию через Паттерн матчинг реализовать?


НС>Можно. В чем проблема?


не пойму как написать такое?
с методом если что можно как выше посоветовали с виртуальным. но общая идея что тип создаваемый определяется по некому свойству
Re[2]: Паттерн матчинг
От: snaphold  
Дата: 02.03.23 10:28
Оценка:
Здравствуйте, Baiker, Вы писали:


B>Паттерн-матчинг тут вообще не причём, тут рефлексия нужна. Как вариант (если это возможно), назвать "специфический метод" у всех одинаково и тупо перегрузить! Классическое применение virtual.


но тут вроде похожее что-то по свойству


string GetMessage(Person? p) => p switch
{
    { Language: "english" } => "Hello!",
    { Language: "german", Status: "admin" } => "Hallo, admin!",
    { Language: "french" } => "Salut!",
    { } => "undefined",
    null => "null"       // если Person p = null
};


мне по сути надо вмсто Language подставить свой name(circle, square) и выполнить здесь

=> "Hello!"


свою логику.
возможно я неправильно понимаю паттерн матчинг но выглядит вроде похоже для моего кейса
Re[2]: Паттерн матчинг
От: dmitry_npi Россия  
Дата: 02.03.23 10:40
Оценка:
Здравствуйте, Baiker, Вы писали:

B>Паттерн-матчинг тут вообще не причём, тут рефлексия нужна. Как вариант (если это возможно), назвать "специфический метод" у всех одинаково и тупо перегрузить! Классическое применение virtual.


Именно. Вызов разных методов в зависимости от типа — это как раз то, для чего нужен virtual.
Что касается создания объектов, создать объект можно только точно зная его тип, иначе не получится. Нужно только выбрать и изолировать точку в приложении, где это знание будет храниться. Весь смысл в том, чтобы такая точка была одна, чтобы не плодить switch/case по всему коду.

Например, можно зарегистрировать нужные типы, при этом все они должны быть производные от базового класса/интерфейса.


Dictionary<string, Type> registry = new();

// один раз при запуске программы
registry.Add("circle", typeof(Circle));
registry.Add("square", typeof(Square));

// затем в вашем методе
public Shape CreateShape(string name, int area)
{
   var type = registry[name];
   var shape = (Shape)Activator.CreateInstance(type);
   shape.CalculateSomethingSpecial(); // это базовый виртуальный метод. вызовется на соответствующем классе.
}


Остаётся только дописывать классы, производные от абстрактного Shape и не забывать регистрировать их.
Можно пойти чуть дальше и цеплять информацию об имени прямо на эти классы, например, при помощи атрибутов, а потом автоматически находить все такие классы и регистрировать их. Собственно, так устроена библиотека MEF (https://learn.microsoft.com/ru-ru/dotnet/framework/mef/). Для Net Core тоже есть аналог или порт.
Атмосферная музыка — www.aventuel.net
Re: Паттерн матчинг
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.03.23 11:30
Оценка: +1
Здравствуйте, snaphold, Вы писали:

S>Можно ли написать такую конструкцию через Паттерн матчинг реализовать?

S>Идея что по свойству надо создать нужный тип объекта из иерархии и вызвать специфический метод для данного типа

S>
S>public Shape CreateShape(string name, int area)
S>{
S>     Shape = switch
S>     {
S>       "circle" => { 
S>             var circle = new Circle(area);  
S>                     circle.CalculateSomethingSpecialForCircle();
S>                     return circle;
S>                   }, 
S>        "square" => { 
S>             var square= new Square(area);  
S>                     square.CalculateSomethingSpecialForSquare();
S>                     return square;
S>                   }
S>    }
S>}
S>

Ну вы в принципе практически рабочий код написали.

public Shape CreateShape(string name, int area)
{
  switch(name)
  {
    case "circle": 
      var circle = new Circle(area);
      circle.CalculateSomethingSpecialForCircle();
      return circle;
    case "square":  
      var square= new Square(area);  
      square.CalculateSomethingSpecialForSquare();
      return square;
  }
}

В чём подвох?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Паттерн матчинг
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.03.23 11:35
Оценка: +1
Здравствуйте, snaphold, Вы писали:

S>Можно ли написать такую конструкцию через Паттерн матчинг реализовать?

S>Идея что по свойству надо создать нужный тип объекта из иерархии и вызвать специфический метод для данного типа

S>
S>public Shape CreateShape(string name, int area)
S>{
S>     Shape = switch
S>     {
S>       "circle" => { 
S>             var circle = new Circle(area);  
S>                     circle.CalculateSomethingSpecialForCircle();
S>                     return circle;
S>                   }, 
S>        "square" => { 
S>             var square= new Square(area);  
S>                     square.CalculateSomethingSpecialForSquare();
S>                     return square;
S>                   }
S>    }
S>}
S>

Если непременно чешется использовать switch expression, а не switch statement, то можно так:

public static class Hacks
{
  public static T Apply(this T object, Action<T> action)
  {
    action(object);
    return object;
  }
}

...

public Shape CreateShape(string name, int area) =>
  name switch
  {
    "circle" => (new Circle(area)).Apply(c=>c.CalculateSomethingSpecialForCircle()),
    "square" => (new Square(area)).Apply(s=>s.CalculateSomethingSpecialForSquare()),
    _ => throw new ArgumentException("name");
  }
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Паттерн матчинг
От: Ночной Смотрящий Россия  
Дата: 02.03.23 12:16
Оценка: +1
Здравствуйте, snaphold, Вы писали:

НС>>Можно. В чем проблема?

S>не пойму как написать такое?

Re: Паттерн матчинг
Автор: Sinclair
Дата: 02.03.23


S>с методом если что можно как выше посоветовали с виртуальным. но общая идея что тип создаваемый определяется по некому свойству


Я по прежнему не понимаю в чем ты видишь проблему. Твой пример не компилируется только потому что синтаксис switch expression не позволяет statements. Переход на switch statement либо вынос стейтментов в отдельный метод (можно локальный) эту проблему решает.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: Паттерн матчинг
От: snaphold  
Дата: 02.03.23 12:49
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>В чём подвох?


но это вроде не паттерн матчинг когда кейс есть, а простой свитч кейс. хотел понять можно ли вынести объявление Shape за пределы свитча и убрать явные кейсы.

то есть чтобы результат свитча сразу присвоился Shape
Re[3]: Паттерн матчинг
От: Ночной Смотрящий Россия  
Дата: 02.03.23 12:55
Оценка:
Здравствуйте, snaphold, Вы писали:

S>>В чём подвох?

S>но это вроде не паттерн матчинг когда кейс есть, а простой свитч кейс.

Нет, это тоже pattern matching. И даже внутри if все равно он.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: Паттерн матчинг
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.03.23 14:19
Оценка:
Здравствуйте, snaphold, Вы писали:
S>но это вроде не паттерн матчинг когда кейс есть, а простой свитч кейс. хотел понять можно ли вынести объявление Shape за пределы свитча и убрать явные кейсы.
Строгое определение паттерн матчинга приведено в первоисточнике: https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/pattern-matching
switch там не обязателен.
S>то есть чтобы результат свитча сразу присвоился Shape
В вашем примере, Shape — это тип. Ему ничего присвоить нельзя. И по логике вашего кода вы собственно пытаетесь вернуть фигуру из метода, а не присваивать её в какую-либо переменную (да и зачем?).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.