Reputation: 12583
EDIT: Maybe this is a clearer, more to the point formulation of the question:
In some generic interface IInterface<T>
, I want to return an object of a generic type, where one of the type arguments should be an implementation of IInterface<T>
.
public class OtherType<T> {}
public interface IInterface<T>
{
OtherType<IInterface<T>> Operation();
}
public class Impl : IInterface<int>
{
public OtherType<IInterface<int>> Operation()
{
return new OtherType<Impl>();
}
}
Since Impl
implements IInterface<int>
, it seems reasonable to me that I could use it this way. Yet, it seems I cannot, I get the compiler error
Cannot convert expression type
OtherType<Impl>
to to return typeOtherType<IInterface<int>>
Upvotes: 0
Views: 131
Reputation: 126884
The issue is that OtherType<T>
is a class and generic classes do not allow co/contravariance in C#. Generic interfaces
do, as long as out
types do not appear in any input positions, and in
types do not appear in any output positions. In your code sample, you could get it to compile by introducing an additional interface marked covariant, and then altering your return type.
public interface IOtherType<out T> {} // new
public class OtherType<T> : IOtherType<T> { }
public interface IInterface<T>
{
IOtherType<IInterface<T>> Operation(); // altered
}
public class Impl : IInterface<int>
{
public IOtherType<IInterface<int>> Operation()
{
return new OtherType<Impl>();
}
}
Whether or not this would actually fit your use case with your additional method definitions is something only you can know, given the limited about of detail in your code snippet.
Upvotes: 1
Reputation: 41559
OtherType<IInterface<int>>
doesn't mean "implements" - it sort of means "is a type OtherType
with a generic type parameter Interface<int>
, but that isn't how you say it.
If you just want to make sure that the return type implements IInterface<int>
then set that as the return type:
public interface IInterface<T>
{
IInterface<T> Operation();
}
public class Impl : IInterface<int>
{
public <IInterface<int>> Operation()
{
return new OtherType();
}
}
where
public class OtherType : IInterface<int>
{}
This means you can return any type that implements IInterface<int>
.
Otherwise you can make it a little more constrained on calling use a generic type constraint:
public interface IInterface<T>
{
TRet Operation<TRet>() where TRet : IInterface<T>;
}
public class Impl : IInterface<int>
{
public TRet Operation<TRet>() where TRet : IInterface<int>
{
return new OtherType();
}
}
This means that you can constraint the operation to return a particular class, which has in turn to implement IInterface<int>
.
It would be called:
Impl i = new Impl();
OtherType x = i.Operation<OtherType>();
Upvotes: 1