C# дженерики с наследованием - PullRequest
4 голосов
/ 01 февраля 2020

Моя проблема по какой-то причине, я не могу использовать производный класс в качестве базы, когда я передаю его через обобщенный c.

Давайте предположим, что приведенный ниже код описывает идею

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 Ответ

4 голосов
/ 01 февраля 2020

Так как Case<Person> отличается от типа Case<GoodPerson> Так же, как.. Case<int> отличается от типа Case<string> Ваш отражатель ожидал сильный тип Case<Person>, но вы предоставляете ему другой сильный тип Case<GoodPerson> (так что это похоже на Case<string> для метода, который ожидает Case<int>) Чтобы заставить это работать, заставьте ваш отражатель принять Случай, когда T - это человек или производный класс такого человека: Тип основан на свойствах, предоставленных в типе дескриптора. Тип Person после создания экземпляра не может быть "повышен" до GoodPerson экземпляра без другого ключевого слова new где-то еще. (Кстати, возможно обратное, создание GoodPerson и приведение к более основному c 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;
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...