Я читал Github-репозиторий о концепциях чистого кода, применяемых к С#, и был удивлен, что стратегия сопоставления с образцом рекомендована для того, чтобы избежать проверки типов (в дополнение https://github.com/thangchung/clean-code-dotnet# Во избежание типа проверки частей-1
Я могу понять, когда на самом деле у вас нет контроля над типами, определенными сторонними разработчиками, но, кроме этого, я думаю, что было бы определенно лучше определить интерфейс для обработки некоторых действий.
Пример, используемый в этом хранилище:
// Bad: btw this example cannot even work, the methods are not defined in Object. Going to fork and PR.
public Path TravelToTexas(object vehicle)
{
if (vehicle.GetType() == typeof(Bicycle))
{
vehicle.PeddleTo(new Location("texas"));
}
else if (vehicle.GetType() == typeof(Car))
{
vehicle.DriveTo(new Location("texas"));
}
}
// Good: parent class / interface
public Path TravelToTexas(Traveler vehicle)
{
vehicle.TravelTo(new Location("texas"));
}
or
// Good: pattern matching
public Path TravelToTexas(object vehicle)
{
if (vehicle is Bicycle bicycle)
{
bicycle.PeddleTo(new Location("texas"));
}
else if (vehicle is Car car)
{
car.DriveTo(new Location("texas"));
}
}
За исключением того, что switch
сопоставления с образцом /is
переводится во что-то эквивалентное if
/else if
/else
с использованием оператора is
(переводится как obj as TargetType != null
) + некоторые условия (и тот факт, что вам не нужно объявлять некоторые переменные заранее).
У меня вопрос, есть ли какая-либо оптимизация, о которой я не знаю, когда использую switch
сопоставления с образцом /is
причиной, иначе я действительно не вижу смысла рекомендовать эту стратегию...?
И выдержка из: https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching#when-clauses-in-case-expressions
Чтобы проиллюстрировать эти новые идиомы, давайте работать со структурами, которые представляют геометрические фигуры, используя операторы сопоставления с образцом. Вы, вероятно, знакомы с построением иерархий классов и созданием виртуальных методов и переопределенных методов для настройки поведения объекта в зависимости от типа объекта во время выполнения.
Эти методы невозможны для данных, которые не структурированы в иерархии классов. Когда данные и методы разделены, вам нужны другие инструменты. Новые конструкции сопоставления с образцом позволяют использовать более чистый синтаксис для проверки данных и управления потоком управления на основе любого состояния этих данных. Вы уже пишете операторы if и переключаете это тестирование значения переменной. Вы пишете это заявления, которые проверяют тип переменной. Сопоставление с образцом добавляет новые возможности к этим утверждениям.
Например, вместо этого невозможно использовать шаблон адаптера и в основном обернуть объекты третьей стороны во что-то, над чем вы можете иметь контроль. Я имею в виду, за исключением смертельного случая, чтобы получить неинформативный object
я не вижу смысла делать это.
(переводится как
obj as TargetType != null
)
Хорошо, это не совсем правильно. Проверьте пример на MSDN.
Старый способ:
public static double ComputeArea(object shape)
{
if (shape is Square)
{
var s = (Square)shape;
return s.Side * s.Side;
}
else if (shape is Circle)
{
var c = (Circle)shape;
return c.Radius * c.Radius * Math.PI;
}
// elided
throw new ArgumentException(
message: "shape is not a recognized shape",
paramName: nameof(shape));
}
Обратите внимание на явное приведение. Теперь версия С# 7.0:
public static double ComputeAreaModernIs(object shape)
{
if (shape is Square s)
return s.Side * s.Side;
else if (shape is Circle c)
return c.Radius * c.Radius * Math.PI;
else if (shape is Rectangle r)
return r.Height * r.Length;
// elided
throw new ArgumentException(
message: "shape is not a recognized shape",
paramName: nameof(shape));
}
Так что изменилось? Ну, старый способ, которым вы должны были: 1) привести объект и 2) использовать явное приведение в случае типов значений. То есть использование as
для типа значения было исключением. Теперь is
ключевое слово обновляется здесь, чтобы бросить и присвоить переменной, но она также обрабатывает типы значений (не используется, as
за кулисами). Это делает код немного более лаконичным/простым в обслуживании. Или, по словам MSDN
В этой обновленной версии выражение
is
одновременно проверяет переменную и присваивает ее новой переменной правильного типа. Также обратите внимание, что эта версия включает типRectangle
, который являетсяstruct
. Новоеis
выражение работает с типами значений, а также ссылочных типов.
Возможно, только небольшое преимущество, но в документации MSDN указывается, что новый объект ограничен по объему, в зависимости от оператора if
. Возможно, вы уже делали это раньше (приведение внутри блока if
), но теперь это происходит автоматически.