覆盖IEnumerable< T>在哪里

本文关键字:在哪里 IEnumerable 覆盖 | 更新日期: 2023-09-27 18:09:50

我写了一个实现IEnumerable的类:

public class MyEnumerable : IEnumerable<MyClass>
{ 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
    public IEnumerator<MyClass> GetEnumerator()
    {
        //Enumerate
    }
}

我想"重写"Where方法。我想做的是:

MyEnumerable myEnumerable = new MyEnumerable();
MyEnumerable myEnumerable2 = myEnumerable.Where(/*some predicate*/);

目前这是不可能的,因为myEnumerable.Where()返回一个IEnumerable。我想要的是MyEnumerable. where()返回一个MyEnumerable。

这是可能的吗?

谢谢

覆盖IEnumerable< T>在哪里

当然-只需在MyEnumerable中添加Where方法即可。Linq Where方法是一个扩展方法,所以它在技术上不是覆盖。你正在"隐藏"linq方法。

public class MyEnumerable : IEnumerable<MyClass>
{ 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
    public IEnumerator<MyClass> GetEnumerator()
    {
        //Enumerate
    }
    public MyEnumerable Where()
    {
       // implement `Where`
    }
}

但是有一些注意事项:

  • Where方法将只在声明类型为MyEnumerable时被调用-它不会在IEnumerable<MyClass>类型的变量(或任何实现它的集合,如List<MyClass>
  • )上被调用
  • 如果你想与Linq保持一致,Where的几个过载也需要实现。

更新

从你的注释中,你的枚举器是一个惰性文件枚举器,你希望能够根据谓词从它中选择项目,并且仍然具有惰性。

你可以创建另一个继承这个类的类或者一个接口来帮助实现这个。

下面是一个例子

public class FileItem
{
    //Some properties
}
public interface IFileEnumerator : IEnumerable<FileItem>
{
    IFileEnumerator Where(Func<FileItem, bool> predicate);
}
public class FileEnumerator : IFileEnumerator
{
    private readonly string fileName;
    public FileEnumerator(string fileName)
    {
        this.fileName = fileName;
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
    public IEnumerator<FileItem> GetEnumerator()
    {
        var items = new List<FileItem>();
        //Read from file and add lines to items
        return items.GetEnumerator();
    }
    public IFileEnumerator Where(Func<FileItem, bool> predicate)
    {
        return new MemoryEnumerator(ToEnumerable(GetEnumerator()).Where(predicate));
    }
    private static IEnumerable<T> ToEnumerable<T>(IEnumerator<T> enumerator) 
    {
        while (enumerator.MoveNext()) 
        {
            yield return enumerator.Current;
        }
    }
}
public class MemoryEnumerator : IFileEnumerator
{
    private readonly IEnumerable<FileItem> items;
    public MemoryEnumerator(IEnumerable<FileItem> items)
    {
        this.items = items;
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
    public IEnumerator<FileItem> GetEnumerator()
    {
        return items.GetEnumerator();
    }
    public IFileEnumerator Where(Func<FileItem, bool> predicate)
    {
        return new MemoryEnumerator(items.Where(predicate));
    }
}