Search code examples
c#c#-4.0contravariance

double contravariance in c# 4


I previously asked this as 'double covariance' and realized that I had things upside down

I have an interface

public interface INodeProvider
{
    void LoadNodes(INode parent, Action<IEnumerable<INode>> action);
}

I have a class derived from INode, called DeviceNode

I have a class that implements the interface

public override void LoadNodes(INode parent, Action<IEnumerable<INode>> action)
{
                List<DeviceNode> devices = new List<DeviceNode>();
                foreach (var dev in list)
                {
                    devices.Add(new DeviceNode(this, dev));
                }
                action(devices);
}

This does not compile. But this does

                List<INode> devices = new List<INode>();

It also compiles if I do

 action(devices.Cast<INode>());

And revert back to my original declaration

This surprised me. Maybe I need to read more.

But I have another question. The delegate being invoked (action), really needs to know the type of the object in the IEnumerable. ie I want to do

Type[] typeParameters = l.GetType().GetGenericArguments();

in the action method. I assume this will give me the actual type used to instantiate the IEnumerable. Except its always INode given what I can get to compile. I was surprised that the one with Cast<>() on it still said INode given that the underlying type is List{DeviceNode} (I guess this means that .Cast actually copies)

Note - I know I could inspect the objects in the collection to determine their type, but that's not what I want to do

EDIT: This seems to be a difference between Silverlight 4 and 'normal' .net 4. If I take the same code and paste it into a .net 4 project it compiles fine


Solution

  • This is a feature missing from SL4 (Ienumerable is not marked 'out'). Apparently fixed in SL5