C# 泛型与继承

4

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

假设下面的代码来描述这个想法:

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>());

为什么方法Reflect不能与Case<GoodPerson>一起调用, 但是没有Case也是可以的,如下所示:

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

    return (BadPerson)person;
}

1
这可能会帮助您理解为什么 Case<GoodPerson> 不是 Case<Person> 的一种。 - Sweeper
Case<Person>Case<GoodPerson> 显然是不同的类型,你可以引入一个接口并使用协变。 - Pavel Anikhouski
1个回答

4

由于Case<Person>Case<GoodPerson>不是相同的类型
就像Case<int>Case<string>不是相同的类型一样

您的反射器期望一个强类型的Case<Person>,但您提供了一个不同的强类型Case<GoodPerson>(这就像向期望Case<int>的方法提供Case<string>一样)

要使其正常工作,请让您的反射器接受T为人或人的派生类的情况下的Case,如下所示:

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

}

@PavelAnikhouski,我同意,我没有关注方法内部的操作,通常人们会隐藏他们的方法实现的所有内容,只展示类型之间的传递。已修复。 - G.Y
where T: Person solve the method calling issue, okay. but what is the benefit of that since I can't use the derived classes (GoodPerson)person.PersonType - Shrembo
我不确定你的意思,你已经传递了GoodPerson对象,它已经在你的调用代码中实例化了。你的反射器只是用于查询属性-这不是你想要的吗? - G.Y
这是我正在寻找的那部分内容:“由于Case<Person>不是与Case<GoodPerson>相同的类型”。 - Shrembo
1
@shrembo 理解,但没关系,这对于在同一领域遇到相似问题的其他人仍然是有用的信息。 - G.Y
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接