首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Interface<TChild>类型的变量转换为Interface<TParent>

将Interface<TChild>类型的变量转换为Interface<TParent>
EN

Stack Overflow用户
提问于 2018-01-12 19:40:07
回答 2查看 78关注 0票数 0

当我尝试定义这样的变量时:

代码语言:javascript
复制
IVeterinarian<IAnimal> v = (IVeterinarian<IAnimal>)new CatVeterinarian();

以下是接口和类解密的例子:

代码语言:javascript
复制
interface IAnimal
{
}

class Dog : IAnimal
{
}

class Cat : IAnimal
{
}

interface IVeterinarian<TAnimal> where TAnimal : IAnimal
{
    void Heal(TAnimal animal);
}

class DogVeterinarian : IVeterinarian<Dog>
{
    public void Heal(Dog animal)
    {
    }
}

class CatVeterinarian : IVeterinarian<Cat>
{
    public void Heal(Cat animal)
    {
    }
}

我的例子和在对象变量的IEnumerable中声明字符串的IEnumerable有什么区别?

为什么我要拿到InvalidCastException。

有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-12 19:44:37

你不能创建这样一个实例;

代码语言:javascript
复制
IVeterinarian v = (IVeterinarian)new CatVeterinarian();

因为,您应该传递一个从IAnimal实现的类型;

代码语言:javascript
复制
IVeterinarian<Cat> v = new CatVeterinarian();

编辑

由于IVeterinarian<IAnimal>不是IVeterinarian<Cat>,甚至没有实现它,所以您将被强制转换为无效异常。

代码语言:javascript
复制
public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

正如您所看到的,IEnumerable使用out参数并使其成为协变量。请回顾一下这个页面

在您的情况下,您不能使您的泛型作为协变,因为泛型被用作签名。通过使用协变量,您可以返回问题中提到的派生类型。

代码语言:javascript
复制
IEnumerable<object> list = new List<string>();

简而言之,它与你想要尝试的案例有不同的目的。

票数 2
EN

Stack Overflow用户

发布于 2018-01-12 21:27:36

在我的使用中,我想要照顾不同的每一个动物。我找到了一个简单的方法--这是我的解决方案:

  1. 从IVeterinarian中删除泛型
  2. 创建一个实现IVeterinarian的通用基本兽医类,其中T实现IAnimal
  3. 在基类中创建一个抽象方法,其名称与获取T类型的动物参数的名称相同
  4. 用调用抽象方法实现原来的治疗方法,将动物参数抛到T上
  5. 在猫狗兽医课程中,只需重写抽象方法

下面是一个例子:

代码语言:javascript
复制
interface IAnimal
{
}

class Dog : IAnimal
{
}

class Cat : IAnimal
{
}

interface IVeterinarian
{
    void Heal(IAnimal animal);
}

abstract class BaseVeterinarian<T> : IVeterinarian
    where T : IAnimal
{
    public void Heal(IAnimal animal)
    {
        Heal((T)animal);
    }

    protected abstract void Heal(T animal);
}

class DogVeterinarian : BaseVeterinarian<Dog>
{
    protected override void Heal(Dog animal)
    {
    }
}

class CatVeterinarian : BaseVeterinarian<Cat>
{
    protected override void Heal(Cat animal)
    {
    }
}

请注意,您必须发送一个正确的IAnimal对象作为参数--否则它会抛出一个InvalidCastException。

现在,我可以使用不同的实现来创建IVeterinarian对象,就像我在问题中所提出的那样。

代码语言:javascript
复制
IVeterinarian v = new CatVeterinarian();
v.Heal(new Cat());

IVeterinarian v2 = new DogVeterinarian();
v2.Heal(new Dog());
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48233004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档