I want a reference to a delegate that returns an instance of a generic interface, where the type parameter is covariant. If I specify the type of T
when calling Get
then it compiles ok. But within Get
, I can't make what looks like an equivalent assignment - despite T
being constrained to IItem
.
It says...
Cannot implicitly convert type 'System.Func<MyNamespace.A>' to 'System.Func<MyNamespace.IA<MyNamespace.IItem>>'. An explicit conversion exists (are you missing a cast?)
Why is this?
using System;
using System.Collections.Generic;
using System.Linq;
namespace MyNamespace
{
public interface IA<out T>
{
IEnumerable<T> f();
}
public class A<T> : IA<T>
{
public IEnumerable<T> f()
{
return Enumerable.Empty<T>();
}
}
public interface IItem {}
public class Item : IItem {}
public static class Program
{
public static void Main(string[] args)
{
Func<IA<IItem>> a = Get<Item>();
}
public static Func<IA<T>> Get<T>() where T : IItem
{
var x = () => new A<T>();
//Doesn't compile
Func<IA<IItem>> a = x;
return x;
}
}
}
Covariance only works for reference types - which would cause a problem for your code if T
were a value type implementing IItem
.
All you need to do in order to make your code compile is constrain T
to be a reference type:
public static Func<IA<T>> Get<T>() where T : class, IItem
As a slightly simpler example (with fewer generics), we can use IConvertible
which is implemented by both string
and int
:
Func<string> x = () => "";
Func<int> y = () => 0;
// This is fine, as string is a
// reference type implementing IConvertible
Func<IConvertible> x2 = x;
// This doesn't compile, because the
// covariant conversion isn't available:
// int is a value type (even though it
// implements IConvertible)
Func<IConvertible> y2 = y;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With