C#:覆盖返回类型

标签 c# inheritance types covariance overriding

有没有办法覆盖 C# 中的返回类型?如果是如何,如果不是为什么以及推荐的方法是什么?

我的情况是,我有一个带有抽象基类及其后代的接口(interface)。我想这样做(好吧不是真的,但作为一个例子!):

public interface Animal
{
   Poo Excrement { get; }
}

public class AnimalBase
{
   public virtual Poo Excrement { get { return new Poo(); } }
}

public class Dog
{
  // No override, just return normal poo like normal animal
}

public class Cat
{
  public override RadioactivePoo Excrement { get { return new RadioActivePoo(); } }
}

RadioactivePoo当然继承自Poo

我想要这样做的原因是那些使用 Cat 对象的人可以使用 Excrement 属性,而不必将 Poo 转换为 RadioactivePoo 而例如 Cat 可能仍然是 Animal 列表的一部分,用户可能不一定知道或关心他们的放射性便便。希望这是有道理的...

据我所知,编译器至少不允许这样做。所以我想这是不可能的。但是你会推荐什么来解决这个问题?

最佳答案

通用基类怎么样?

public class Poo { }
public class RadioactivePoo : Poo { }

public class BaseAnimal<PooType> 
    where PooType : Poo, new() {
    PooType Excrement {
        get { return new PooType(); }
    }
}

public class Dog : BaseAnimal<Poo> { }
public class Cat : BaseAnimal<RadioactivePoo> { }

编辑:一个新的解决方案,使用扩展方法和标记接口(interface)...

public class Poo { }
public class RadioactivePoo : Poo { }

// just a marker interface, to get the poo type
public interface IPooProvider<PooType> { }

// Extension method to get the correct type of excrement
public static class IPooProviderExtension {
    public static PooType StronglyTypedExcrement<PooType>(
        this IPooProvider<PooType> iPooProvider) 
        where PooType : Poo {
        BaseAnimal animal = iPooProvider as BaseAnimal;
        if (null == animal) {
            throw new InvalidArgumentException("iPooProvider must be a BaseAnimal.");
        }
        return (PooType)animal.Excrement;
    }
}

public class BaseAnimal {
    public virtual Poo Excrement {
        get { return new Poo(); }
    }
}

public class Dog : BaseAnimal, IPooProvider<Poo> { }

public class Cat : BaseAnimal, IPooProvider<RadioactivePoo> {
    public override Poo Excrement {
        get { return new RadioactivePoo(); }
    }
}

class Program { 
    static void Main(string[] args) {
        Dog dog = new Dog();
        Poo dogPoo = dog.Excrement;

        Cat cat = new Cat();
        RadioactivePoo catPoo = cat.StronglyTypedExcrement();
    }
}

这样 Dog 和 Cat 都继承自 Animal(如评论中所述,我的第一个解决方案没有保留继承)。
有必要使用标记接口(interface)显式标记类,这很痛苦,但也许这可以给您一些想法...

第二次编辑 @Svish:我修改了代码以明确显示扩展方法没有以任何方式强制执行 iPooProvider 继承自 BaseAnimal< 的事实。 “更强类型”是什么意思?

关于C#:覆盖返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1048884/

相关文章:

swift - 如何基于 Int 创建一个新的类型安全的原始类型?

c# - 如何使用 asp.net 检查在 TreeView 子节点中导航页面的权限?

c# - 我在构建 Linq 查询时做错了什么

Java:强制实现覆盖 toString 的设计接口(interface)

ios - 为什么在子类中看不到继承的实例变量?

Python,元组索引必须是整数,而不是元组?

c++ - 在两个模板堆栈之上打印不同的数据类型 (C++)

c# - 将 iTextSharp PDF 作为内存流返回导致 StreamNotSupported

C# 加载非托管 DLL : big performance difference between console application and webapp on IIS

python 继承函数在 init 期间重写