двойная ковариация - PullRequest
       4

двойная ковариация

3 голосов
/ 23 июля 2011

у меня

public interface IFoo
{
   IEnumerable<IThingy> Thingies{get;}
}

Я хочу тогда быть в состоянии сделать

class Thing1 : IThingy
{
   ...
}
class ImplementFoo : IFoo
{
   List<Thing1> m_things;
   IEnumerable<IThingy> Thingies {get {return m_things;}}
}

ImplementFoo.Thingies возвращает IList (который является IEnumerable) Thing1s (которые являются IThings). Так что в теории этот код должен работать, но это не так. VS предлагает бросок в геттере; который компилируется, но не работает во время выполнения. Я ожидаю слишком много ковариации в c # 4?

VS 2010 -> Silverlight 4. Вот ошибка компиляции

Невозможно неявно преобразовать тип 'System.Collections.Generic.List<MyProj.Column>' в 'System.Collections.Generic.IEnumerable<MyProj.IColumn>'. Существует явное преобразование (вам не хватает приведения?)

РЕДАКТИРОВАТЬ: Люди говорят мне, что это должно работать, но это не работает в SL4

Ответы [ 3 ]

2 голосов
/ 23 июля 2011

Это прекрасно работает в C # /. NET 4. Вот полный, компилируемый и рабочий пример:

namespace Test
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public interface IThingy { }

    public interface IFoo
    {
        IEnumerable<IThingy> Thingies { get; }
    }

    internal class Thing1 : IThingy { }

    internal class ImplementFoo : IFoo
    {
        private List<Thing1> m_things = new List<Thing1>() { new Thing1() };

        public IEnumerable<IThingy> Thingies
        {
            get { return m_things; }
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var impl = new ImplementFoo();

            Console.WriteLine(impl.Thingies.Count());


            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}

Я подозреваю, что проблема в том, что вы ориентируетесь на .NET 3.5sp1 или более раннюю версию, а не.NET 4.0.Covariance будет работать правильно только при таргетинге на .NET 4, так как требует новых изменений в структуре.В этом случае IEnumerable<T> в .NET 4 фактически равно IEnumerable<out T>, что необходимо для его работы.

1 голос
/ 23 июля 2011

Вы можете использовать метод расширения Cast :

class ImplementFoo : IFoo
{
    List<Thing1> m_things;

    IEnumerable<IThingy> Thingies 
    {
        get
        {
            return m_things.Cast<IThingy>();
        }
    }
}

Это потому, что IEnumerable<Thing1> неявно не реализует IEnumerable<IThingy>.

0 голосов
/ 08 сентября 2011

Это разница между SL4 и CLR4. IEnumerable интерфейс не помечен как «out». Видимо исправлено в SL5

...