C#:重写返回类型 [英] C#: Overriding return types

查看:175
本文介绍了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 当然,从继承便便

我对想这是为了让那些谁使用对象可以使用排泄物属性,而无需投了便便 RadioactivePoo 而例如能仍然是一个动物列表中,用户可能不一定知道或关心他们的放射性便便的一部分。希望有意义...

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?

推荐答案

有关的通用基础类是什么?

What about a generic base class?

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> { }

修改:一种新的解决方案,使用扩展方法和标记接口...

EDIT: A new solution, using extension methods and a marker 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();
    }
}

本办法狗和猫的动物,从既继承(如评论所说,我的第一个解决方案没有preserve继承)。

因此,有必要明确标示与标记接口,这是痛苦的类,但也许这可以给你一些想法......

This way Dog and Cat both inherit from Animal (as remarked in the comments, my first solution did not preserve the inheritance).
It's necessary to mark explicitly the classes with the marker interface, which is painful, but maybe this could give you some ideas...

第二修改 @Svish:我修改了code到explitly表明扩展方法是不以任何方式强制执行的事实, iPooProvider BaseAnimal 。你是什​​么意思更是强类型?

SECOND EDIT @Svish: I modified the code to show explitly that the extension method is not enforcing in any way the fact that iPooProvider inherits from BaseAnimal. What do you mean by "even more strongly-typed"?

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

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