比使用 Type 更清洁的方式(可能是?) - 寻找更清洁方式的代码气味

bas*_*ado 1 c# types object

不知道将传入什么对象类型,如果它是 FishDTO 的类型,它有不同的路线来生成 uri,如果它不是鱼而不是哺乳动物,则应遵循标准路线。有没有更干净的方法来做到这一点?除了使用 type 有没有更好的方法使用as?这有效,但它看起来很难看:

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;
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 6

首先,永远不要这样做:

    if (animal.GetType() == typeof(Fish))
Run Code Online (Sandbox Code Playgroud)

为什么不?因为 ifanimalGoldfish,是 的派生类型Fish呢? GetType会回来typeof(Goldfish)。相反,请始终这样做:

    if (animal is Fish fish)
Run Code Online (Sandbox Code Playgroud)

因为无论animalFish还是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);
}
Run Code Online (Sandbox Code Playgroud)

现在至少您正在使用类型系统。

或者,在较新版本的 C# 中,您可以说

switch(x)
{
  case Fish fish: return HandleFish(fish);
  ...
Run Code Online (Sandbox Code Playgroud)

另一种方法是将逻辑放在类型层次结构本身中。

class Animal
{
  public virtual Uri Handle() ...
}
class Fish : Animal
{
  public override Uri Handle() ...
}
Run Code Online (Sandbox Code Playgroud)

现在如果xAnimal那么你只是return ((Animal)x).Handle());