Можно ли использовать LINQ в объекте, который предоставляет только объекты Add(), Remove(), Count(), Item() и GetEnumerator() из System.Collections.IEnumerator?
Использование LINQ для объекта, у которого есть только GetEnumerator()
Ответ 1
Существующие методы расширения Linq работают с объектами, которые реализуют IEnumerable<T>
. Я предполагаю, что ваш объект реализует не общий интерфейс IEnumerable
. В этом случае вы можете использовать метод расширения Cast<T>
, чтобы получить общую обертку IEnumerable<T>
. Например, если элементы имеют тип int
:
var wrapper = myObject.Cast<int>();
Теперь вы можете использовать Linq на обертке
Ответ 2
Не напрямую. Вы могли бы довольно легко написать SingleShotEnumerable<T>
, хотя:
public sealed class SingleShotEnumerable<T> : IEnumerable<T>
{
private IEnumerator<T> enumerator;
public SingleShotEnumerable(IEnumerator<T> enumerator)
{
if (enumerator == null)
{
throw new ArgumentNullException("enumerator");
}
this.enumerator = enumerator;
}
public IEnumerator<T> GetEnumerator()
{
if (enumerator == null)
{
throw new InvalidOperationException
("GetEnumerator can only be called once");
}
var ret = enumerator;
enumerator = null;
return ret;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Предполагается, что у вас есть IEnumerator<T>
. Если у вас есть только IEnumerator
, вы можете написать что-то подобное, только реализуя IEnumerable
, затем используйте Cast
или OfType
, чтобы перейти к IEnumerable<T>
.
(Примечание: это не потокобезопасно. Вы можете сделать это с помощью блокировок, если хотите.)
Затем вы можете:
var filtered = from person in new SingleShotEnumerable<Person>(personEnumerator)
where person.Age > 18
select person.Name;
... но вы не можете использовать запрос дважды.
Как вы попали в странную ситуацию, имея только IEnumerator<T>
? Это довольно редко. Посмотрите, можете ли вы создать свой путь вокруг этого, чтобы избежать необходимости делать что-то вроде выше, что довольно хрупко.
(Альтернативой было бы "слить" IEnumerator<T>
в List<T>
или что-то подобное, но у этого есть проблемы, связанные с большими или потенциально бесконечными последовательностями.)
Ответ 3
Нет, вы не можете. Все методы LINQ - это методы расширения для интерфейса IEnumerable<T>
.
Итак, вам нужно реализовать IEnumerable<T>
, чтобы использовать LINQ с вашими собственными коллекциями.