Disregarding any sane reason to do this, and simply out of curiosity
Is it possible to take any given IEnumerable(T) and overwrite the contained items? For example, given an IEnuemrable(String) is it possible to comp开发者_运维问答letely replace all strings within the IEnumerable?As other people have said, if the IEnumerable is something concrete like a List or a Collection, Set, etc, then you can do this without reflection - just cast it to that type and mess with it.
What if the IEnumerable is generated using an iterator, eg:
public IEnumerable<int> EvenNumbers
{
get
{
int i = 2;
while (true)
{
yield return i;
i += 2;
}
}
}
How could you reach into this and replace some value? There are no values to replace - the next value comes from the next evaluation of the loop. There's no full evaluation of this Enumerable in memory anywhere, you have to keep asking for the next value until you get what you were looking for.
So no, you can't guarantee that for all IEnumerables you can dig in and modify the underlying values because sometimes there are no underlying values.
Theoretically I would imagine yes; however...
- the only way to reliably look through the objects in an
IEnumerable
is through enumeration (else you have to hard-code for specific classes) - by convention, changing any value within an
IEnumerable
invalidates the enumeration. This isn't necessarily enforced; however, it's certainly enforced by the framework classes (and should be enforced for user-createdIEnumberable
s, too.
From MSDN's page on IEnumerator:
An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the next call to MoveNext or Reset throws an InvalidOperationException. If the collection is modified between MoveNext and Current, Current returns the element that it is set to, even if the enumerator is already invalidated.
Therefore... unlikely!
Reflection gives you access to methods defined on the object which are not exposed in the type that the object is currently casted to.
IEnumerable<T>
does not expose any method for replacing items. But remember that IEnumerable<T>
is just an interface while your object will be of a concrete implementation.
So if underlying object is a List<T>
, you can easily say without reflection:
IEnumerable<MyType> list = ... // getting the enumerable
List<MyType> realList = (List<MyType>) list;
realList[0] = somethingElse;
So it depends on the underlying type, IEnumerable<T>
is just an interface.
I doubt you could for 'any IEnumerable' becuase some might be lazy-evaluated and there isn't a T to overwrite until you ask for it.
But you could probably check for the special cases of collections that implement IEnumerable - List, Collection, etc. - and make changes that way.
精彩评论