简体   繁体   中英

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

I have a situation where I have iterator classes that I'm deriving. The base iterators iterate over base objects and the derived iterators iterator over derived objects. I can use LINQ on the base iterators but not on the derived iterators. It would be quite helpful if I could iterate over either using LINQ.

Thanks in advance for any guidance!

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());
        }
    }
}

That's because DerivedEnumerator implements both IEnumerable<BaseThingy> and IEnumerable<DerivedThingy> (indirectly via IReadOnlyColleciton ). So when you do

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

Compiler cannot figure out what is the type of s in lamdba. Is that DerivedThingy ? Is that BaseThingy ? Both are possible. So you need to tell it explicitly what that is:

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

or

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

That said, it's quite unusual design and you might reconsider it. How exactly depends on what you are trying to do (so, why do you need to inherit enumerators this way).

Ambiguity issue

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());
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM