C#:覆盖返回类型 [英] C#: Overriding return types

查看:24
本文介绍了C#:覆盖返回类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is there way to override return types in C#? If so how, and if not why and what is a recommended way of doing it?

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

My case is that I have an interface with an abstract base class and descendants of that. I would like to do this (ok not really, but as an example!) :

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 列表的一部分,用户可能不一定知道或关心他们的放射性粪便.希望这是有道理的...

My reason for wanting this is so that those who use Cat objects could use the Excrement property without having to cast the Poo into RadioactivePoo while for example the Cat could still be part of an Animal list where users may not necessarily be aware or care about their radioactive poo. Hope that made sense...

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

As far as I can see the compiler doesn't allow this at least. So I guess it is impossible. But what would you recommend as a solution to this?

推荐答案

我知道已经有很多解决方案可以解决这个问题,但我想我已经提出了一个解决方案来解决我在现有解决方案中遇到的问题.

I know there are a lot of solutions for this problem already but I think I've come up with one that fixes the issues I had with the existing solutions.

我对现有的一些解决方案不满意,原因如下:

  • Paolo Tedesco 的第一个解决方案:猫和狗没有共同的基类.
  • Paolo Tedesco 的第二个解决方案:它有点复杂且难以阅读.
  • Daniel Daranas 的解决方案:这可行,但会因大量不必要的强制转换和 Debug.Assert() 语句而使您的代码变得混乱.
  • hjb417 的解决方案:此解决方案不允许您将逻辑保留在基类中.这个例子中的逻辑非常简单(调用构造函数),但在现实世界的例子中就不是这样了.
  • Paolo Tedesco's first solution: Cat and Dog do not have a common base class.
  • Paolo Tedesco's second solution: It is a bit complicated and hard to read.
  • Daniel Daranas's solution: This works but it would clutter up your code with a lot of unnecessary casting and Debug.Assert() statements.
  • hjb417's solutions: This solution doesn't let you keep your logic in a base class. The logic is pretty trivial in this example (calling a constructor) but in a real world example it wouldn't be.

我的解决方案

这个解决方案应该通过使用泛型和方法隐藏来克服我上面提到的所有问题.

This solution should overcome all of the issues I mentioned above by using both generics and method hiding.

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

interface IAnimal
{
    Poo Excrement { get; }
}

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

    public PooType Excrement
    {
        get { return new PooType(); }
    }
}

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

使用此解决方案,您无需覆盖 Dog OR Cat 中的任何内容!以下是一些示例用法:

With this solution you don't need to override anything in Dog OR Cat! Here is some sample usage:

Cat bruce = new Cat();
IAnimal bruceAsAnimal = bruce as IAnimal;
Console.WriteLine(bruce.Excrement.ToString());
Console.WriteLine(bruceAsAnimal.Excrement.ToString());

这将输出:RadioactivePoo"两次,表明多态性没有被破坏.

This will output: "RadioactivePoo" twice which shows that polymorphism has not been broken.

进一步阅读

  • 显式接口实现
  • 新修饰符.我没有在这个简化的解决方案中使用它,但您可能需要在更复杂的解决方案中使用它.例如,如果您想为 BaseAnimal 创建一个接口,那么您需要在PooType Excrement"的声明中使用它.
  • 排除通用修饰符(协方差).同样,我没有在这个解决方案中使用它,但是如果你想做一些事情,比如从 IAnimal 返回 MyType 并从 BaseAnimal 返回 MyType 那么你会需要使用它才能在两者之间进行转换.
  • Explicit Interface Implementation
  • new Modifier. I didn't use it in this simplified solution but you may need it in a more complicated solution. For example if you wanted to create an interface for BaseAnimal then you would need to use it in your decleration of "PooType Excrement".
  • out Generic Modifier (Covariance). Again I didn't use it in this solution but if you wanted to do something like return MyType<Poo> from IAnimal and return MyType<PooType> from BaseAnimal then you would need to use it to be able to cast between the two.

这篇关于C#:覆盖返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆