Существуют ли какие-либо инструменты, которые могут помочь нам реорганизовать свойства IEnumerator в IList<T> или аналогичный?
У нас очень старая кодовая база (это на самом деле не ужасное качество). Это восходит к тому времени, когда.Net был предварительным выпуском, который, я подозреваю, является причиной некоторых из этих странных соглашений.
Как бы то ни было, мы только начали отказываться от поддержки.Net 1.1, и у нас наступил веселый день с преобразованием вещей в дженерики, использованием Linq и всего такого интересного. Один из самых раздражающих шаблонов в нашей кодовой базе, хотя у нас будет что-то вроде
private ArrayList mylist;
public IEnumerator MyList
{
get
{
if(mylist==null)
return new EmptyEnumerator.Enumerator;
return mylist.GetEnumerator();
}
}
Эта модель особенно ужасна, потому что она мешает нам просто делать foreach(var item in MyList)
потому что IEnumerator не реализует IEnumerable. Вместо этого мы должны сделать что-то вроде этого:
IEnumerator enumerator=MyList;
while(enumerator.MoveNext())
{
object item=enumerator.Current;
}
Итак, для рефакторинга мы, конечно, хотим использовать что-то вроде ReadOnlyCollection<T>
или же IList<T>
или похожие. Чтобы сделать это, однако, мы должны обновить каждую ссылку на MyList
сделать:
IEnumerator enumerator=MyList;
в
IEnumerator enumerator=MyList.GetEnumerator();
В некоторых случаях мы можем иметь более ста ссылок на одно свойство. Существуют ли какие-либо инструменты, которые могут сделать это проще? Недавно мы получили Resharper (не для этой проблемы, а только для общего использования), но, похоже, он не охватывает этот тип сценария.
1 ответ
Похоже, вам нужно вернуть класс, который реализует оба IEnumerator
а также IEnumerable<T>
На самом деле не так уж сложно просто создать свой собственный тип, который делает это:
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();
}
}
Теперь вместо возврата либо IEnumerator
или IEnumerable<T>
Вы можете вернуть то, что делает оба.
Обратите внимание, что IEnumerator
реализован явно в то время как IEnumerable<T>
реализован неявно, поэтому он будет поощрять использование его в качестве IEnumerable
, в то время как все еще использую это как IEnumerator
возможно
Да, это некрасиво, но, конечно, могло быть и хуже.