【问题标题】:C#: Using LINQ on a derived iterator class when both the derived class and its base implement IEnumerableC#:当派生类及其基类都实现 IEnumerable 时,在派生迭代器类上使用 LINQ
【发布时间】:2018-02-22 05:34:26
【问题描述】:

我有一种情况,我有我要派生的迭代器类。基迭代器迭代基对象,派生迭代器迭代派生对象。我可以在基迭代器上使用 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());
        }
    }
}

【问题讨论】:

  • “不起作用...” 以哪种方式?能不能给出编译错误?

标签: c# linq inheritance ienumerable


【解决方案1】:

这是因为DerivedEnumerator 实现了IEnumerable&lt;BaseThingy&gt;IEnumerable&lt;DerivedThingy&gt;(间接通过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());

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

【讨论】:

  • 您好 Evk,感谢您的反馈。我当然愿意改进设计,您的任何建议将不胜感激。为简单起见,问题的抽象是:假设您有“Vehicle”和“Vehicles”类,“Vehicles”显然是枚举器类。假设您想派生“Car”和“Cars”类。 (稍后您可能想要派生类“摩托车”和“摩托车”)。在继承基类及其枚举器的设计中,您是否仍然看到缺陷?再次感谢瑞恩。
  • @RyanHartstein 我还没有遇到这样做的实际案例。我的意思是-为什么要从 Vehicles 继承 Cars?甚至有人可以争辩说 Cars 集合不是 Vehicles 集合,因为您可以将任何车辆(摩托车)添加到 Vehicles 集合中,但您不能将摩托车添加到 Cars 集合中。大多数集合的东西都可以由泛型集合(List&lt;Car&gt;List&lt;Vehicle&gt;)或泛型接口(@98​​7654333@)完美处理。我不记得我曾经以这种方式继承过集合类(或者即使这样做)。
  • 感谢您的回复。
【解决方案2】:

歧义问题

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

【讨论】:

    猜你喜欢
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多