C# 是否有任何工具可以帮助我们将IEnumerator属性重构到IList<;T>;还是类似的?

C# 是否有任何工具可以帮助我们将IEnumerator属性重构到IList<;T>;还是类似的?,c#,.net,refactoring,ienumerable,automated-refactoring,C#,.net,Refactoring,Ienumerable,Automated Refactoring,我们有一个非常古老的代码库(实际上质量并不可怕)。它可以追溯到.Net预发布的时候,我怀疑这是一些奇怪约定的原因 无论如何,我们刚刚开始放弃.NET1.1的支持,并将其转换为泛型,使用Linq和所有有趣的东西,度过了愉快的一天。不过,我们的代码库中最烦人的模式之一是 private ArrayList mylist; public IEnumerator MyList { get { if(mylist==null) return new EmptyEnumerato

我们有一个非常古老的代码库(实际上质量并不可怕)。它可以追溯到.Net预发布的时候,我怀疑这是一些奇怪约定的原因

无论如何,我们刚刚开始放弃.NET1.1的支持,并将其转换为泛型,使用Linq和所有有趣的东西,度过了愉快的一天。不过,我们的代码库中最烦人的模式之一是

private ArrayList mylist;
public IEnumerator MyList
{
  get
  {
    if(mylist==null)
      return new EmptyEnumerator.Enumerator;
    return mylist.GetEnumerator();
  }
}
这种模式特别可怕,因为它阻止我们简单地执行
foreach(MyList中的var项)
,因为IEnumerator没有实现IEnumerable。相反,我们必须这样做:

IEnumerator enumerator=MyList;
while(enumerator.MoveNext())
{
    object item=enumerator.Current;
}
因此,对于重构,我们当然希望使用类似于
ReadOnlyCollection
IList
或类似的东西。然而,要做到这一点,我们必须更新对
MyList
的每个引用,以便:

IEnumerator enumerator=MyList;


在某些情况下,一个属性可以有100多个引用。有没有什么工具可以让这更容易?我们最近得到了Resharper(不是为了这个问题,只是为了一般用途),但它似乎没有涵盖这种类型的场景

听起来您需要做的是返回一个实现
IEnumerator
IEnumerable

实际上,制作自己的类型并没有那么难:

public class MessedUpIterator<T> : IEnumerable<T>, IEnumerator
{
    private IEnumerable<T> source;
    private IEnumerator enumerator;

    private IEnumerator MyEnumerator
    {
        get
        {
            return enumerator ?? source.GetEnumerator();
        }
    }

    public MessedUpIterator(IEnumerable<T> source)
    {
        this.source = source;
    }
    public IEnumerator<T> GetEnumerator()
    {
        return source.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return source.GetEnumerator();
    }

    object IEnumerator.Current
    {
        get { return MyEnumerator.Current; }
    }

    bool IEnumerator.MoveNext()
    {
        return MyEnumerator.MoveNext();
    }

    void IEnumerator.Reset()
    {
        MyEnumerator.Reset();
    }
}
公共类迭代器:IEnumerable,IEnumerator
{
私有可数源;
私有IEnumerator枚举器;
私有分子
{
收到
{
返回枚举数??source.GetEnumerator();
}
}
公共迭代器(IEnumerable源)
{
this.source=源;
}
公共IEnumerator GetEnumerator()
{
返回source.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回source.GetEnumerator();
}
对象IEnumerator.Current
{
获取{返回MyEnumerator.Current;}
}
bool IEnumerator.MoveNext()
{
返回MyEnumerator.MoveNext();
}
void IEnumerator.Reset()
{
myelommerator.Reset();
}
}
现在,不必返回
IEnumerator
IEnumerable
,您可以返回同时执行这两项操作的内容

请注意,
IEnumerable
是显式实现的,而
IEnumerable
是隐式实现的,因此它将鼓励将其用作
IEnumerable
,同时仍然可以将其用作
IEnumerable


是的,它很难看,但肯定会更糟。

听起来您需要做的是返回一个同时实现
IEnumerator
IEnumerable

实际上,制作自己的类型并没有那么难:

public class MessedUpIterator<T> : IEnumerable<T>, IEnumerator
{
    private IEnumerable<T> source;
    private IEnumerator enumerator;

    private IEnumerator MyEnumerator
    {
        get
        {
            return enumerator ?? source.GetEnumerator();
        }
    }

    public MessedUpIterator(IEnumerable<T> source)
    {
        this.source = source;
    }
    public IEnumerator<T> GetEnumerator()
    {
        return source.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return source.GetEnumerator();
    }

    object IEnumerator.Current
    {
        get { return MyEnumerator.Current; }
    }

    bool IEnumerator.MoveNext()
    {
        return MyEnumerator.MoveNext();
    }

    void IEnumerator.Reset()
    {
        MyEnumerator.Reset();
    }
}
公共类迭代器:IEnumerable,IEnumerator
{
私有可数源;
私有IEnumerator枚举器;
私有分子
{
收到
{
返回枚举数??source.GetEnumerator();
}
}
公共迭代器(IEnumerable源)
{
this.source=源;
}
公共IEnumerator GetEnumerator()
{
返回source.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回source.GetEnumerator();
}
对象IEnumerator.Current
{
获取{返回MyEnumerator.Current;}
}
bool IEnumerator.MoveNext()
{
返回MyEnumerator.MoveNext();
}
void IEnumerator.Reset()
{
myelommerator.Reset();
}
}
现在,不必返回
IEnumerator
IEnumerable
,您可以返回同时执行这两项操作的内容

请注意,
IEnumerable
是显式实现的,而
IEnumerable
是隐式实现的,因此它将鼓励将其用作
IEnumerable
,同时仍然可以将其用作
IEnumerable


是的,这很难看,但肯定会更糟。

为什么不修复使用-而不是继续手动调用
GetEnumerator()
?我希望它们中的大多数最终都是
foreach
循环,对吗?使用是否足够一致,您可以使用regex或编写一个快速脚本来读取所有的.cs文件并查找/替换模式?@JonSkeet我们很乐意,但是我们没有一个月的时间来完成这项任务:)所以我们现在的计划是修复根本原因,这样我们就可以编写好的新代码,并在遇到它的Crew automation时修复旧代码,只要找个实习生。@Earlz你能有两个属性吗,一个是IEnumerator(现有的一个)还有一个是具有类似名称的
IEnumerable
。新用途使用新特性,旧用途使用旧特性。当你遇到旧的方法时,重构它的用法,然后尽可能完全删除它。为什么不修复这些用法呢?而不是继续手动调用
GetEnumerator()
?我希望它们中的大多数最终都是
foreach
循环,对吗?使用是否足够一致,您可以使用regex或编写一个快速脚本来读取所有的.cs文件并查找/替换模式?@JonSkeet我们很乐意,但是我们没有一个月的时间来完成这项任务:)所以我们现在的计划是修复根本原因,这样我们就可以编写好的新代码,并在遇到它的Crew automation时修复旧代码,只要找个实习生。@Earlz你能有两个属性吗,一个是IEnumerator(现有的一个)还有一个是具有类似名称的
IEnumerable
。新用途使用新特性,旧用途使用旧特性。当你遇到旧代码时,重构它的用途,然后尽可能完全删除它。我们正在努力使我们的代码更好,而不是更粗糙。另外,如果我们决定允许类似于
IList
的东西,因为一段代码