В настоящее время в любом случае, тип Возвращается:
Enumerable/'<RepeatIterator>d__b5`1'<string>.
Вы не можете определить переменную как то Tpye, потому что это анонимный тип. Анонимные типы реализуются путем компиляции типа с именем, в то время как действительный .NET недействителен C#, поэтому вы не можете случайно создать другой тип с тем же именем.
Этот особый анонимный тип - это сортировка, используемая для реализации yield
. Опять же, когда вы код yield
в C#, это скомпилировано путем создания классов .NET, которые реализуют IEnumerable
и IEnumerator
.
Ваш код не заботится ни о чем из этого, он просто заботится о том, чтобы он получил что-то, реализующее интерфейс.
Для этой точки рассмотреть действительность:
public IEnumerable<string> SomeStrings()
{
if(new Random().Next(0, 2) == 0)
return new HashSet<string>{"a", "b", "c"};
else
return new List<string>{"a", "b", "c"};
}
телефонный код не будет знать, если он получил HashSet<string>
или ее List<string>
и не будет заботиться. Не волнует, вернет ли версия 2.0 string[]
или использует yield
.
Вы можете создать свой собственный Repeat
следующим образом:
public static IEnumerable<T> Repeat<T>(T element, int count)
{
while(count-- > 0)
yield return element;
}
У нас есть осложнения, хотя в том, что мы хотим, брошенной исключение, если count
меньше нуля.Мы не можем просто сделать:
public static IEnumerable<T> Repeat<T>(T element, int count)
{
if(count < 0)
throw new ArgumentOutOfRangeException("count");
while(count-- != 0)
yield return element;
}
Это не работает, потому что бросок не будет, пока мы фактически не перечислить его (если мы когда-нибудь сделать), как yield
-определенных перечисления не запускать любой код, пока не найдешь первое перечисление. Поэтому нам нужно;
public static IEnumerable<T> Repeat<T>(T element, int count)
{
if(count < 0)
throw new ArgumentOutOfRangeException("count");
return RepeatImpl<T>(element, count);
}
private static IEnumerable<T> RepeatImpl<T>(T element, int count)
{
while(count-- != 0)
yield return element;
}
Просто найдите источник: http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,e2850cfe2b0cc87f –
Внутренняя работа любого перечислимы намеренно скрыты от конечного пользователя. Как правило, будет какая-то внутренняя коллекция (например, список), но вы не должны точно знать. В этом случае достаточно цикла с выражениями 'yield' и использовать меньше памяти. – ja72