1

Suppose I have a List<IMyInterface>...

I have three classes which implement IMyInterface: MyClass1, MyClass2, and MyClass3

I have a readonly Dictionary:

private static readonly Dictionary<Type, Type> DeclarationTypes = new Dictionary<Type, Type>
{
    { typeof(MyClass1), typeof(FunnyClass1) },
    { typeof(MyClass2), typeof(FunnyClass2) },
    { typeof(MyClass3), typeof(FunnyClass3) },
};

I have another interface, IFunnyInteface<T> where T : IMyInterface

I have a method:

public static IFunnyInterface<T> ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
    if (DeclarationTypes.ContainsKey(node.GetType())) {
        IFunnyInterface<T> otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
        return otherClassInstance;
    }
    return null;
}

I'm trying to call the constructor of FunnyClasses and insert as parameter my MyClass object. I don't want to know which object it is: I just want to instantiate some FunnyClass with MyClass as a parameter.

What happens when I call ConvertToFunnyClass, T is of type IMyInterface, and when I try to cast it to FunnyInterface<T>, it says I can't convert FunnyClass1, for instance, to FunnyInterface<IMyInterface>

My current workaround (not a beautiful one), is this:

public static dynamic ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
    if (DeclarationTypes.ContainsKey(node.GetType())) {
        var otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
        return otherClassInstance;
    }
    return null;
}

And I don't like it because the return type is dynamic, so when I access it from somewhere else, I have no idea what type it is, and I lose intellisense, and stuff. I don't know about any performance implications either.

Any clues?

Thanks in Advance!

Resolution

As I'm using C# 4.0, I could stop casting errors using covariance (output positions only), and so I changed my IFunnyInterface to

IFunnyInteface<out T> where T : IMyInterface

Thank you all for the replies.

Conrad Clark
  • 4,533
  • 5
  • 45
  • 70

2 Answers2

1

Essentially, your problem is that you are trying to convert FunnyInterface<T> to FunnyInterface<IMyInterface>. As has been mentioned several times (one example is here, more information here), this is not valid in most circumstances. Only in .NET 4, when the generic type is an interface or delegate, and the type parameter has been explicitly declared as variant with in or out, can you perform this conversion.

Is FunnyInterface actually an interface?

Community
  • 1
  • 1
thecoop
  • 45,220
  • 19
  • 132
  • 189
1

thecoop answer points you exactly to why you can't do it.

A cleaner solution to the problem (besides using dynamic) would be a base non-Generics Interface:

public interface IFunnyInterfaceBase
{
}

public interface IFunnyInteface<T> : IFunnyInterfaceBase 
    where T : IMyInterface
{
}

And you need to move methods signature you use in that code from IFunnyInteface to IFunnyInterfaceBase.

This way you would be able to write something like this:

MyClass2 c2 = new MyClass2();
IFunnyInterfaceBase funnyInstance = c2.ConvertToFunnyClass();

The Exception you said you got in your code is not due to the extension method signature itself (the method is fine)..it is originated by the type of your lvalue (the type of the variable you use to store its return value)!

Obviously this solution applies only if you can modify IFunnyInterface source code!

Fulvio
  • 1,615
  • 1
  • 16
  • 18