C#:当派生迭代器 class 及其基础实现 IEnumerable 时,在派生迭代器 class 上使用 LINQ

C#: Using LINQ on a derived iterator class when both the derived class and its base implement IEnumerable

我有一种情况,我有迭代器 类 我正在推导。基础迭代器迭代基础对象,派生迭代器迭代派生对象。我可以在基本迭代器上使用 LINQ,但不能在派生迭代器上使用。如果我可以使用 LINQ 迭代其中任何一个,那将非常有帮助。

在此先感谢您的指导!

namespace ClassLibrary1
{
    public class BaseThingy { }

    public class DerivedThingy : BaseThingy { }

    public class BaseEnumerator : IReadOnlyCollection<BaseThingy>
    {
        public int Count => throw new NotImplementedException();

        public IEnumerator<BaseThingy> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

    public class DerivedEnumerator : BaseEnumerator, IReadOnlyCollection<DerivedThingy>
    {
        IEnumerator<DerivedThingy> IEnumerable<DerivedThingy>.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

    public class Application
    {
        public void Main()
        {
            BaseEnumerator baseEnumerator = new BaseEnumerator();
            DerivedEnumerator derivedEnumerator = new DerivedEnumerator();

            // Works...
            var x = baseEnumerator.Where(s => s.GetHashCode() == s.GetHashCode());

            // Doesn't work...
            var y = derivedEnumerator.Where(s => s.GetHashCode() == s.GetHashCode());
        }
    }
}

那是因为 DerivedEnumerator 同时实现了 IEnumerable<BaseThingy>IEnumerable<DerivedThingy>(通过 IReadOnlyColleciton 间接实现)。所以当你做

var y = derivedEnumerator.Where(s => s.GetHashCode() == s.GetHashCode());

编译器无法确定 lamdba 中 s 的类型。是 DerivedThingy 吗?是 BaseThingy 吗?两者都是可能的。所以你需要明确地告诉它那是什么:

var y = derivedEnumerator.Where<DerivedThingy>(s => s.GetHashCode() == s.GetHashCode());

var y = derivedEnumerator.Where((DerivedThingy s) => s.GetHashCode() == s.GetHashCode());

也就是说,这是一个非常不寻常的设计,您可能会重新考虑它。具体如何取决于您要做什么(那么,为什么您需要以这种方式继承枚举器)。

歧义问题

namespace ClassLibrary1
{
    public class BaseThingy { }

    public class DerivedThingy : BaseThingy { }

    public class BaseEnumerator : IReadOnlyCollection<BaseThingy>
    {
        public int Count => throw new NotImplementedException();

        public IEnumerator<BaseThingy> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

    public class DerivedEnumerator : BaseEnumerator, IReadOnlyCollection<DerivedThingy>
    {
        IEnumerator<DerivedThingy> IEnumerable<DerivedThingy>.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

    public class Application
    {
        public void Main()
        {
            BaseEnumerator baseEnumerator = new BaseEnumerator();
            DerivedEnumerator derivedEnumerator = new DerivedEnumerator();

            // Works...
            var x = baseEnumerator.Where(s => s.GetHashCode() == s.GetHashCode());

            // Works now
            var y = derivedEnumerator.Where<DerivedThingy>(s => s.GetHashCode() == s.GetHashCode());
        }
    }
}