首页 新闻 会员 周边 捐助

C# foreach枚举对象只读的问题

0
悬赏园豆:20 [已解决问题] 解决于 2012-12-04 13:53

最近操作DataTable的时候遇到的问题,下面的写法:

foreach(DataRow dr in dt.Rows)

{

    if(...)

    dr.delete();

}

发现并不会把满足条件的dr置为已删除状态。问了别人加查了下资料后发现使用foreach迭代的时候枚举对象是只读的。现在我的问题是,既然这个对象是只读的,那么dr["name"]=“Lin”这种写法为什么可以呢,即迭代对象的子对象为什么可以操作。

林J的主页 林J | 菜鸟二级 | 园豆:202
提问于:2012-12-04 12:34
< >
分享
最佳答案
1

foreach本来就是提供了一种简洁遍历的手段,它被规定为遍历的每一项是只读的,这里的只读指的是你能读取其中的每一项元素,但是不能改变当前元素在集合中的状态,如果允许的话,集合岂不是动态改变了?比如长度等。

你说的dr["name"]=“Lin”这种写法为什么可以呢,是因为你取到了dr,此时你当然可以操作它自身的状态了。

你更改dr["name"]=“Lin”,不会对dr在dt.Rows中的状态造成任何影响。

收获园豆:10
叶小党 | 菜鸟二级 |园豆:481 | 2012-12-04 12:48

我的理解是这个枚举出来的dr只是指向dt表中DataRow集合对象在堆中储存的地址而已。既然它是只读的,就不该拥有修改这个地址内数据的能力。

林J | 园豆:202 (菜鸟二级) | 2012-12-04 13:00

@林J: 这个枚举出来的dr只是指向dt表中DataRow集合对象在堆中储存的地址而已。正确。

既然它是只读的,就不该拥有修改这个地址内数据的能力。 错误。

你把这里的只读理解错了。这里的只读,意思是:你只能从DataRow集合对象中读取到每一个DR,Rows.GetCurrentRow();取到之后你随便怎么改DR自身的状态。但是,你不能Rows.RemoveCurrentRow();这样你就改变集合的状态了。如果你改变了集合的状态,下一个Rows.GetCurrentRow()可能就会出错,因为内部可能维护了一个类似i的变量在计数。

叶小党 | 园豆:481 (菜鸟二级) | 2012-12-04 13:05
其他回答(2)
0

应该是指dt.Rows.Length只读

RyanCheng | 园豆:474 (菜鸟二级) | 2012-12-04 12:43
0

只读是指集合只读,你的Add, Remove方法修改了这个集合。但是集合的成员不是只读的,你dr["name"] 修改的是集合的成员。这很好理解,比如这样:

readonly Person p = new Person();

//然后你在你的方法里去修改p变量
p = new Person();   //错误,因为p是只读的

//但是你可以修改p的成员
p.Name = "another";   //修改了p的成员
收获园豆:10
水牛刀刀 | 园豆:6350 (大侠五级) | 2012-12-04 13:41

是的,我刚看到这部分,通过foreach返回的枚举对象是个object类型的只读属性。我想了下为什么会出现这种情况呢?我自己的想法是这样的。比方说例子中的p,假设是个类,它是在栈上的,指向堆上的一个new Person()的地址,这个地址内存着个name字段。现在p是只读的,就是说不能修改这个地址,而地址内的东西可以修改。我的想法有错误吗?

支持(0) 反对(0) 林J | 园豆:202 (菜鸟二级) | 2012-12-04 13:48

@林J: 你的想法是正确的,我本来想给你解释这些的,怕讲不清楚反而误导你。

支持(0) 反对(0) 水牛刀刀 | 园豆:6350 (大侠五级) | 2012-12-04 13:49

@水牛刀刀: 哈哈,看来我还是有一点理解能力的。每次我问问题你都帮忙回答啊,真是太谢谢你了!终于搞明白这个问题了。我得去记录一下。

支持(0) 反对(0) 林J | 园豆:202 (菜鸟二级) | 2012-12-04 13:52
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册