Более чистый способ, чем использование Type (возможно, как?) - кодовый запах ищет более чистый способ - PullRequest
1 голос
/ 23 января 2020

Не знаю, какой тип объекта будет передан, если это тип FishDTO, у него есть другой маршрут для генерации URI, если он не fi sh, чем у млекопитающего и должен следовать стандартному маршруту. Есть ли более чистый способ сделать это? Вместо использования типа есть лучший способ использовать как ? Это работает, но выглядит ужасно:

public Uri GetAnimalImageUrl(object animalResult)
{
    if (animalResult.GetType() == typeof(FishDTO))
    {
        return new Uri(GetFishImageUrl((FishDTO)animalResult));
    }

    var mammal = (MammalDTO)animalResult;
    var mammalUrl = GetMammalImageUrl(mammal);
    if (!string.IsNullOrEmpty(mammalUrl))
    {
        return new Uri(mammalUrl);
    }

    _logger.Error("Image not found for animal");
    return null;
}

1 Ответ

6 голосов
/ 23 января 2020

Прежде всего, никогда не делайте этого:

    if (animal.GetType() == typeof(Fish))

Почему бы и нет? Потому что, если animal является Goldfish, производным типом Fish? GetType вернет typeof(Goldfish). Вместо этого всегда делайте это:

    if (animal is Fish fish)

, потому что это верно, независимо от того, animal равен Fish или Goldfish или Shark.

Во-вторых, ваш код предполагает, что все, что не является фантастическим, является млекопитающим, но я думаю, что птицы, ящерицы и ракообразные хотели бы с вами не согласиться. Ваш код не является надежным перед лицом неожиданных входных данных.

Реальный вопрос, на который нужно ответить, это , почему формальный параметр типа object в первую очередь ? Это похоже на проблему, чтобы решить. Если эта проблема не решаема, сделайте все возможное, чтобы исправить ее:

Uri HandleFish(Fish fish) ...
Uri HandleMammal(Mammal mammal) ...
Uri HandleAnimal(Animal animal)
{
  if (x is Fish fish) return HandleFish(fish);
  if (x is Mammal mammal) return HandleMammal(mammal);
  ...
  return HandleOther(x);
}
Uri HandleOther(object x) ...
Uri HandleObject(object x)
{
  if (x is Animal animal) return HandleAnimal(animal);
  ...
  return HandleOther(x);
}

Теперь, по крайней мере, вы работаете с системой типов.

Или в более новых версиях C# вы Можно сказать,

switch(x)
{
  case Fish fish: return HandleFish(fish);
  ...

Альтернативный подход заключается в том, чтобы поместить logi c в саму иерархию типов.

class Animal
{
  public virtual Uri Handle() ...
}
class Fish : Animal
{
  public override Uri Handle() ...
}

А теперь, если x равно Animal, тогда вы просто return ((Animal)x).Handle());

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...