2010-06-28 4 views
2

У меня есть два класса: GenericList и SpecificList, где SpecificList наследуется от GenericList. GenericList орудия IEnumerable<GenericItem> и SpecificList орудия IEnumerable<SpecificItem>. SpecificItem наследуется от GenericItem. Я должен реализовать GetEnumerator как в GenericList, так и в SpecificList, так как они реализуют IEnumerable<T>. В GenericList, это достаточно легко, я просто вернуть перечислитель для базового List<T>:Доступ к базовому классу C# в итераторе вызывает предупреждение ReSharper

public IEnumerator<GenericItem> GetEnumerator() 
{ 
    return genericItemsList.GetEnumerator(); 
} 

Однако в SpecificList, кажется, сложнее. Представляется рискованным бросить IEnumerator<GenericItem> на IEnumerator<SpecificItem>, и я не знаю, будет ли это работать. Вместо этого я сделал следующее:

public new IEnumerator<SpecificItem> GetEnumerator() 
{ 
    IEnumerator<GenericItem> enumerator = base.GetEnumerator(); 
    while (enumerator.MoveNext()) 
    { 
     yield return (SpecificItem)enumerator.Current; 
    } 
} 

Это нормально компилируется и простой тест блок MSTest вызова SpecificList.GetEnumerator() кажется, чтобы показать это работает. Тем не менее, ReSharper подчеркивает base в указанном выше способ со следующим предупреждением:

Доступ к GenericList.GetEnumerator через «базовое» ключевое слово из анонимного метода, лямбда-выражения, выражения запроса или результатов итераторов в непроверяемом коде

Это что-то, о чем я должен беспокоиться? Должен ли я что-то делать по-другому?

Редактировать: Я использую ReSharper 5.1 Full Edition Pre-Release Build 5.1.1715.35.

Кроме того, я должен сделать перерыв от работы модульных тестов MSTest: Я просто ударил Ctrl +R, Ctrl +T в Chrome, чтобы перезагрузить страницу ...

ответ

6

R # правильно, что доступ к ключевому слову base внутри итератора/лямбда в версии 3.0 компилятора C# может привести к неконтролируемому коду. Когда это происходит или нет, это немного сложно, и я не буду пытаться его покрыть.

Самый простой способ обойти это - обернуть вызов base.GetEnumerator в другом нестационарном приватном методе и указать, что из вашего итератора.

private IEnumerator<GenericItem> GetBaseEnumerator() { 
    return base.GetEnumerator(); 
} 

public new IEnumerator<SpecificItem> GetEnumerator() 
{ 
    IEnumerator<GenericItem> enumerator = GetBaseEnumerator(); 
    while (enumerator.MoveNext()) 
    { 
     yield return (SpecificItem)enumerator.Current; 
    } 
} 

Я уверен, что эта ошибка была исправлена ​​в версии 4.0 компилятора C#.

+0

Спасибо. Возможно, тупой вопрос, но использует ли версия компилятора C#, которую я использую, в зависимости от версии.NET Я использую? Это проект .NET 3.5 - это гарантирует мне определенную версию компилятора C#? –

+0

@Sarah, он больше привязан к версии Visual Studio, которую вы используете, чем таргетинг на структуру. 2008 = C# 3.0 и 2010 = C# 4.0 – JaredPar

+0

aha! Я в 2008 SP1. Ваше предложение удаляет предупреждение ReSharper, и все, похоже, работает. :) –

0

Кажется опасным отливать IEnumerator<GenericItem> в IEnumerator<SpecificItem>, и я не знаю, будет ли это работать.

Уверен, что это будет.

return base.Cast<SpecificItem>().GetEnumerator(); 

Не более или менее опасно, чем ваша текущая реализация. На самом деле, я уверен, что это больше или меньше того же кода под капотом.

+0

Это делает Visual Studio 2008 сердитым. «Cast» выделяется красным цветом, и он говорит: «Не удается разрешить символ« Cast ». –

+0

@Sarah - Вам может потребоваться добавить 'using System.Linq;' – ChaosPandion

+0

@ChaosPandion: для 'System.Linq' уже существует директива' using'. –

Смежные вопросы