【问题标题】:C# generics with inheritance具有继承的 C# 泛型
【发布时间】:2020-05-17 19:40:52
【问题描述】:

我的问题是由于某种原因,当我通过泛型传递派生类时,我不能使用派生类作为基础。

让我们假设下面的代码来描述这个想法

public class Person
{
    public virtual bool IsGood { get; }
}
public class GoodPerson : Person
{
    public override bool IsGood { get; } = true;

}
public class BadPerson : Person
{
    public override bool IsGood { get; } = false;
}

public class Case<T>
{
    public T PersonType { get; set; }
}
public class TypeReflector
{
    public Person Reflect(Case<Person> person)
    {
        if (person.PersonType.IsGood)
            return (GoodPerson)person.PersonType;

        return (BadPerson)person.PersonType;
    }
}

并调用如下:

        var reflector = new TypeReflector();
        var result = reflector.Reflect(new Case<GoodPerson>());

为什么不能用Case&lt;GoodPerson&gt; 调用方法Reflect。 但如果没有Case,如下所示:

public Person Reflect(Person person)
{
    if (person.IsGood)
        return (GoodPerson)person;

    return (BadPerson)person;
}

【问题讨论】:

  • this 可能会帮助您理解为什么Case&lt;GoodPerson&gt; 不是Case&lt;Person&gt; 的一种。
  • Case&lt;Person&gt;Case&lt;GoodPerson&gt; 显然是不同的类型,你可以引入一个接口并为此使用协方差

标签: c# oop generics inheritance


【解决方案1】:

由于Case&lt;Person&gt;Case&lt;GoodPerson&gt; 不是同一类型
很像..
Case&lt;int&gt;Case&lt;string&gt; 不是同一类型

您的反射器需要一个强类型 Case&lt;Person&gt;,但您为它提供了一个不同的强类型 Case&lt;GoodPerson&gt;(所以这就像将 Case&lt;string&gt; 提供给一个需要 Case&lt;int&gt; 的方法)

为了让它工作,让你的反射器接受这样的情况,其中 T 是一个人或一个人的派生类:

public class TypeReflector
{
    public Person Reflect<T>(Case<T> person) where T:Person
    {
        return person.PersonType;
    }
}

但下面是我认为您真正想要实现的目标,即根据描述符类型中提供的属性获取类型的实例。类型 Person 一旦实例化就不能“提升”到 GoodPerson 实例,而没有另一个 new 关键字。(顺便说一句,相反的情况是可能的,创建一个 GoodPerson 并转换为更基本的 Person 类)

using System;

namespace ConsoleApp25
{
    class Program
    {
        static void Main(string[] args)
        {

            var personDescriptor = new PersonDescriptor { IsGood = true };

            var resultPerson = personDescriptor.CreateInstance();

            Console.WriteLine(resultPerson.IsGood);
            Console.WriteLine(resultPerson.GetType().Name);

            Console.ReadLine();
        }
    }

    public class PersonDescriptor
    {
        public bool IsGood { get; set; }

        public Person CreateInstance()
        {
            if (IsGood)
                return new GoodPerson(); //create new instance!
            return new BadPerson(); //create new instance!
        }
    }

    public abstract class Person
    {
        public abstract bool IsGood { get; }
    }

    public class GoodPerson : Person
    {
        public override bool IsGood { get; } = true;
    }

    public class BadPerson : Person
    {
        public override bool IsGood { get; } = false;
    }

}

【讨论】:

  • if (person.PersonType.IsGood) 没有意义。
  • @PavelAnikhouski,我同意,我没有关注方法在内部做什么,通常人们隐藏他们方法实现的全部内容,只是在类型之间的段落。固定
  • where T: Person 解决方法调用问题,ok。但是这样做有什么好处,因为我不能使用派生类(GoodPerson)person.PersonType
  • 我不确定你的意思,你已经通过了 GoodPerson,它已经从你的调用代码中实例化了。您的反射器只是用来询问属性 - 这不是您想要的吗?
  • @shrembo 理解,但没关系,对于在同一地区遇到困难的其他人来说,这仍然是一个很好的信息
猜你喜欢
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
相关资源
最近更新 更多