4

My problem is for some reason, I can't use derived class as the base when I pass it through a generic.

Let's suppose the below code to describe the idea

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

and called as below:

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

why the method Reflect can't be called with Case<GoodPerson>. but it possible without the Case as below:

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

    return (BadPerson)person;
}
2
  • 1
    this might help you understand why Case<GoodPerson> is not a kind of Case<Person>. Commented Feb 1, 2020 at 9:48
  • Case<Person> and Case<GoodPerson> are different types obviously, you can introduce an interface and use covariance for that Commented Feb 1, 2020 at 9:49

1 Answer 1

4

Since Case<Person> is not the same type as Case<GoodPerson>
Much like..
Case<int> is not the same type like Case<string>

Your reflector expected a strong type Case<Person> but you're providing it a different strong type Case<GoodPerson> (so this is like providing Case<string> to a method which expects Case<int>)

To make it work, make your reflector accept Case where T is a person or derived class of a person like this:

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

But below is what I think you really want to achieve, getting an instance of a type based on properties supplied in descriptor type. A type Person once instantiated cannot be "elevated" to GoodPerson instance without another new keyword somewhere.. (btw, the opposite is possible, creating a GoodPerson and casting to the more basic Person class)

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

}
Sign up to request clarification or add additional context in comments.

7 Comments

if (person.PersonType.IsGood) doesn't make sense then.
@PavelAnikhouski, I agree, I didn't focus on what the method do inside, usually people hide the entire content of their methods implementations, just on the passages between the types. fixed
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
I'm not sure what you mean, you already passing GoodPerson, it was instantiated already from your calling code. your reflector just meant to interrogate on the properties - is it not what you wanted?
@shrembo understood, but It ok, it is still good info for others who stumble the same area
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.