Можно ли переписать элементы в IEnumerable <T>с помощью Reflection? - PullRequest
3 голосов
/ 08 апреля 2011

Не обращая внимания на какие-либо разумные причины сделать это, и просто из любопытства

Можно ли взять какой-либо заданный IEnumerable (T) и перезаписать содержащиеся в нем элементы?Например, учитывая IEnuemrable (String), можно ли полностью заменить все строки в IEnumerable?

Ответы [ 4 ]

5 голосов
/ 08 апреля 2011

Как уже говорили другие люди, если IEnumerable является чем-то конкретным, таким как Список или Коллекция, Набор и т. Д., То вы можете сделать это без размышлений - просто приведите его к этому типу и связывайтесь с ним.

Что если IEnumerable генерируется с использованием итератора, например:

public IEnumerable<int> EvenNumbers
{
    get
    {
        int i = 2;

        while (true)
        {
            yield return i;
            i += 2;
        }
    }
}

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

Так что нет, вы не можете гарантировать, что для всех IEnumerables вы можете копатьв и изменить базовые значения, потому что иногда нет базовых значений.

1 голос
/ 08 апреля 2011

Теоретически я бы представил да;однако ...

  • единственный способ надежно просмотреть объекты в IEnumerable - это перечисление (иначе вам придется жестко программировать для определенных классов)
  • по соглашениюизменение любого значения в пределах IEnumerable делает недействительным перечисление.Это не обязательно принудительно;однако, это, безусловно, обеспечивается классами инфраструктуры (и должно * быть выполнено для пользовательских IEnumberable s.

со страницы MSDN на IEnumerator :

Перечислитель остается действительным до тех пор, пока коллекция остается неизменной.Если в коллекцию вносятся изменения, такие как добавление, изменение или удаление элементов, перечислитель безвозвратно аннулируется и следующий вызовto MoveNext или Reset генерирует исключение InvalidOperationException. Если коллекция изменена между MoveNext и Current, Current возвращает элемент, для которого она установлена, даже если перечислитель уже признан недействительным.

Следовательно ... маловероятно!

1 голос
/ 08 апреля 2011

Отражение дает вам доступ к методам, определенным для объекта, которые не отображаются в типе, к которому объект в настоящий момент приведен.

IEnumerable<T> не предоставляет никаких методов для замены элементов. Но помните, что IEnumerable<T> - это просто интерфейс, в то время как ваш объект будет иметь конкретную реализацию.

Так что если базовый объект является List<T>, вы можете легко сказать без отражения :

IEnumerable<MyType> list = ... // getting the enumerable
List<MyType> realList = (List<MyType>) list;
realList[0] = somethingElse;

Так что это зависит от базового типа, IEnumerable<T> это просто интерфейс.

0 голосов
/ 08 апреля 2011

Я сомневаюсь, что вы могли бы для 'любого IEnumerable', потому что некоторые могут быть лениво оценены, и нет T, чтобы перезаписать, пока вы не попросите его.

Но вы, возможно, могли бы проверить особые случаи коллекций, которые реализуют IEnumerable - List, Collection и т. Д. - и внести изменения таким образом.

...