Каков конкретный тип для этого IEnumerable<string>
?
private IEnumerable<string> GetIEnumerable()
{
yield return "a";
yield return "a";
yield return "a";
}
Каков конкретный тип для этого IEnumerable<string>
?
private IEnumerable<string> GetIEnumerable()
{
yield return "a";
yield return "a";
yield return "a";
}
Это тип, созданный компилятором. Компилятор генерирует реализацию IEnumerator<string>
, которая возвращает три значения "a", и скелетный класс IEnumerable<string>
, предоставляющий одно из них в своем методе GetEnumerator
.
Сгенерированный код выглядит примерно так*:
// No idea what the naming convention for the generated class is --
// this is really just a shot in the dark.
class GetIEnumerable_Enumerator : IEnumerator<string>
{
int _state;
string _current;
public bool MoveNext()
{
switch (_state++)
{
case 0:
_current = "a";
break;
case 1:
_current = "a";
break;
case 2:
_current = "a";
break;
default:
return false;
}
return true;
}
public string Current
{
get { return _current; }
}
object IEnumerator.Current
{
get { return Current; }
}
void IEnumerator.Reset()
{
// not sure about this one -- never really tried it...
// I'll just guess
_state = 0;
_current = null;
}
}
class GetIEnumerable_Enumerable : IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
return new GetIEnumerable_Enumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Или, может быть, как говорит SLaks в своем ответе, две реализации попадают в один и тот же класс. Я написал это, основываясь на моей прерывистой памяти сгенерированного кода, который я просматривал раньше; действительно, одного класса было бы достаточно, поскольку нет причин, по которым вышеуказанная функциональность требует двух.
На самом деле, если подумать, две реализации действительно должны попадать в один класс, поскольку я только что вспомнил, что функции, использующие операторы yield
, должны иметь возвращаемый тип любой IEnumerable<T>
или IEnumerator<T>
.
В любом случае, я позволю вам мысленно внести исправления в код того, что я опубликовал.
*Это чисто для иллюстрации; Я не претендую на его реальную точность. Это только для того, чтобы в общих чертах продемонстрировать, как компилятор делает то, что он делает, основываясь на доказательствах, которые я видел в своих собственных исследованиях.
<GetIEnumerable>d__0
. (Да, <
и >
являются частью имени типа. Вы не можете написать такое имя типа в C#, но оно допустимо в CLR.) Тип вложен внутри типа, который объявляет метод GetIEnumerable()
.
- person Timwi; 11.08.2010
Компилятор автоматически сгенерирует класс, реализующий как IEnumerable<T>
, так и IEnumerator<T>
(в одном классе).
У Джона Скита есть подробное объяснение.
Конкретная реализация IEnumerable<string>
, возвращаемая методом, представляет собой анонимный тип, сгенерированный компилятором.
Console.WriteLine(GetIEnumerable().GetType());
Отпечатки:
YourClass+<GetIEnumerable>d__0
GetNext()
или что-то в этом роде. - person Hamish Grubijan   schedule 11.08.2010