不考虑任何合理的理由,只是出于好奇
是否有可能采用任何给定的IEnumerable(T)并覆盖包含的项?例如,给定一个IEnumerable (String)是否有可能完全替换IEnumerable中的所有字符串?
正如其他人所说,如果IEnumerable是具体的东西,如List或Collection, Set等,那么您可以不需要反射就可以做到这一点-只需将其强制转换为该类型并乱搞它。
如果IEnumerable是使用迭代器生成的,例如:
public IEnumerable<int> EvenNumbers
{
get
{
int i = 2;
while (true)
{
yield return i;
i += 2;
}
}
}
你怎么能进入这个并替换一些值呢?没有要替换的值——下一个值来自循环的下一次求值。这个Enumerable在内存中没有完整的求值,你必须不断地请求下一个值,直到你得到你想要的。
所以,不,你不能保证所有IEnumerables都可以挖掘和修改底层值,因为有时根本没有底层值
理论上我想是的;然而…
- 在
IEnumerable
中可靠地查看对象的唯一方法是通过枚举(否则你必须为特定的类硬编码) - 按照约定,更改
IEnumerable
中的任何值都会使枚举失效。这并不一定是强制的;但是,它肯定是由框架类强制执行的(并且也应该对用户创建的IEnumberable
强制执行)。
从MSDN的IEnumerator页面:
因此,只要集合保持不变,枚举数就保持有效。如果对集合进行了更改,例如添加、修改或删除元素,则枚举数将不可恢复地失效,并且下次调用MoveNext或Reset时会抛出InvalidOperationException。如果集合在MoveNext和Current之间被修改,Current返回它被设置为的元素,即使枚举数已经无效。
…不太可能!
反射使您可以访问对象上定义的方法,这些方法在对象当前强制转换为的类型中未公开。
IEnumerable<T>
没有公开任何替换项的方法。但是请记住,IEnumerable<T>
只是一个接口,而你的对象将是一个具体的实现。
所以如果底层对象是List<T>
,你可以很容易地说而不反射:
IEnumerable<MyType> list = ... // getting the enumerable
List<MyType> realList = (List<MyType>) list;
realList[0] = somethingElse;
所以它取决于底层类型,IEnumerable<T>
只是一个接口
我怀疑你可以为'any IEnumerable',因为有些可能是惰性求值,没有T覆盖,直到你要求它。
但是你可能会检查实现IEnumerable的集合的特殊情况- List, Collection等-并以这种方式进行更改