How can I work with Type.IsAssignableFrom not working with legacy interfaces?

I made a test case to illustrate the problem I was facing.

The first statement passes, but the second and third don't.

Is there a way to test either of the two unsuccessful k conditions in a different way that will work? It would be nice if it wasn't very fast as I intend to cache the results based on each type.

public interface IParentInterface
{

}

public interface IChildInterface : IParentInterface
{

}

public class ParentClass<T> where T: IParentInterface
{

}

public class ChildClass : ParentClass<IChildInterface>
{

}

public class TestClass
{
    public ChildClass Property { get; set; }
}

[TestFixture]
public class ScratchPad
{

    [Test]
    public void Assignabl()
    {
        var tc = new TestClass();
        var tct = tc.GetType();

        var pi = tct.GetProperty("Property");

        Assert.IsNotNull(pi);

        Assert.IsTrue(typeof(ParentClass<IChildInterface>).IsAssignableFrom(pi.PropertyType));
        Assert.IsTrue(typeof(ParentClass<>).IsAssignableFrom(pi.PropertyType));
        Assert.IsTrue(typeof(ParentClass<IParentInterface>).IsAssignableFrom(pi.PropertyType));

    }

}

      

+1


source to share


3 answers


By design, your second statement fails. When you write

public class ParentClass<ParentInterface>

      

it actually means that "ParentInterface" is now the symbol for the type argument (which makes it so confusing that it really confuses you completely). Recording

public class ChildClass : ParentClass<ChildInterface>

      

then sets an argument of type yout (yes, the one called ParentInterface) for the ChildInterface type. Hence, Childclass is only assigned to ParentClass <ChildInterface>.

Finally, you should make sure that you follow the conventions when defining type arguments, this will confuse you a lot less, for example.

public class ParentClass<T>

      



Labeling interfaces with "I" will also greatly improve understanding, for example.

interface IParent { }
interface IChild : IParent { }

      

I suspect that what you want is not possible until we get C # 4.0:

Parent<IChild> 

      

not assigned

Parent<IParent>

      

There is currently no co / contravariance for generics.

+2


source


Is this covariance / contravariance ?



Then it's just something C # currently doesn't support, but C # 4.0 can.

0


source


You can't, because C # 3.0 doesn't support this type of variance. In C # 4.0, you should be able to.

Using another example, let's say you have List<ParentInterface>

it and it can assign it List<ChildInterface>

:

List<ParentInterface> parentList = List<ParentInterface>();
List<ChildInterface> childList = parentList;

      

The problem is that the internal storage for parentList

is type ParentInterface

. If you got a different interface from ChildInterface

:

public interface ParentInterface2 : ChildInterface {}

      

And then tried to add it in childList

like this:

childList.Add(new ParentInterface2Implementation());

      

You will get an exception because it childList

really is List<ParentInterface>

and can only store versions ParentInterface

that are ParentInterface2

not.

0


source







All Articles