vendredi 18 avril 2014

C# refuse d'accepter le type générique sous-classe - Stack Overflow


I keep seeing this error, over and over again:



Cannot convert from Item<Foo> to Item<IFoo>.



This is clearly nonsense; an object of type Item<Foo> is statically guaranteed to be able to do absolutely everything that an Item<IFoo> can do (and possibly more), so why is the compiler refusing to accept my perfectly valid code?


I have a method that accepts an Item<IFoo> as an argument. For some reason, it refuses to accept an Item<Foo> as input, even though Foo implements IFoo. This makes no sense at all. I can pass a Foo in place of an IFoo, but I can't pass an Item<Foo> in place of an Item<IFoo>. Why?


public class Item<T>
{
public readonly int ID;
public readonly T Data;
...
}

public void ProcessItem(Item<IFoo> item)
{
Console.WriteLine(item.ID);
}

ProcessItem(new Item<Foo>());



Classes in C# are invariant, so depending on your requirements you'll have to create an interface and implment that:


public interface IItem<out T> { ... }
public class Item<T> : IItem<T> { ... }

IItem<IFoo> item = new Item<Foo>();

Note that it is not necessarily safe to assign a Class<Subtype> to a Class<Basetype>. A common example is List<T>:


List<object> l = new List<string>();   //won't compile
l.Add(3);

C# only allows variance annotations on interfaces and delegates, and only when it is safe to do so.



I keep seeing this error, over and over again:



Cannot convert from Item<Foo> to Item<IFoo>.



This is clearly nonsense; an object of type Item<Foo> is statically guaranteed to be able to do absolutely everything that an Item<IFoo> can do (and possibly more), so why is the compiler refusing to accept my perfectly valid code?


I have a method that accepts an Item<IFoo> as an argument. For some reason, it refuses to accept an Item<Foo> as input, even though Foo implements IFoo. This makes no sense at all. I can pass a Foo in place of an IFoo, but I can't pass an Item<Foo> in place of an Item<IFoo>. Why?


public class Item<T>
{
public readonly int ID;
public readonly T Data;
...
}

public void ProcessItem(Item<IFoo> item)
{
Console.WriteLine(item.ID);
}

ProcessItem(new Item<Foo>());


Classes in C# are invariant, so depending on your requirements you'll have to create an interface and implment that:


public interface IItem<out T> { ... }
public class Item<T> : IItem<T> { ... }

IItem<IFoo> item = new Item<Foo>();

Note that it is not necessarily safe to assign a Class<Subtype> to a Class<Basetype>. A common example is List<T>:


List<object> l = new List<string>();   //won't compile
l.Add(3);

C# only allows variance annotations on interfaces and delegates, and only when it is safe to do so.


0 commentaires:

Enregistrer un commentaire