《Effective C#》中讲 foreach不可以处理自定义类型转换,但是代码写出来却可以呀,请各位帮助看一下哪儿错了,谢谢

崔鹏飞 2009-05-31 09:17:54
定义有类ClassOne,其中有
//自定义的类型转换
public static explicit operator ClassTwo(ClassOne co);

然后创建一个ClassOne的数组:
ClassOne[] arr = { new ClassOne{FiledOne=10},new ClassOne{FiledOne=20}};

再然后使用Foreach:
 foreach (ClassTwo item in arr)
{
Console.WriteLine(item.FiledTwo.ToString());
}

但是按照《Effective C#》中的说法,上面的foreach和下面的代码一样:
IEnumerator it = arr.GetEnumerator();
while (it.MoveNext())
{
ClassTwo temp = (ClassTwo)it.Current;
}

都用该是会出现InvalidCastException的
但是执行之后的结果是,foreach正确,而自己使用IEnumerator.MoveNext()的那一段代码确实是有异常
这是怎么回事?
《Effective C#》文章地址:http://book.csdn.net/bookfiles/295/10029512570.shtml
...全文
153 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
崔鹏飞 2009-05-31
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 qldsrx 的回复:]
我想知道你那本书是谁写的?我看权威的《C# 高级编程》上面可是明确指出可以用foreach遍历数组的。而我查看MSDN上的例子又有Array使用IEnumerator遍历输出的代码样例,所以我才要测试你那段代码,看看为什么不成功。所以你那“权威”的书有错误。
[/Quote]http://book.csdn.net/bookfiles/295/10029512570.shtml
qldsrx 2009-05-31
  • 打赏
  • 举报
回复
我想知道你那本书是谁写的?我看权威的《C# 高级编程》上面可是明确指出可以用foreach遍历数组的。而我查看MSDN上的例子又有Array使用IEnumerator遍历输出的代码样例,所以我才要测试你那段代码,看看为什么不成功。所以你那“权威”的书有错误。
崔鹏飞 2009-05-31
  • 打赏
  • 举报
回复
确实是这样,不过,书上讲foreach也会有一样的问题,但是我写的foreach却可以…这么权威的书应该没有错误啊…
qldsrx 2009-05-31
  • 打赏
  • 举报
回复
测试的结果是,如果不用ClassTwo转换ClassOne而直接使用ClassOne进行遍历,结果是正确的。那么问题应该是执行自定义转换时的问题了。
楼主试着把这段改下看看,因为你没有给我转换的详细代码,我没法测试。

IEnumerator it = arr.GetEnumerator();
while (it.MoveNext())
{
ClassTwo temp = (ClassTwo)(it.Current as ClassOne);
}
qldsrx 2009-05-31
  • 打赏
  • 举报
回复
楼主先等等,让我测试一段代码看看
qldsrx 2009-05-31
  • 打赏
  • 举报
回复
那个MoveNext()方法是IEnumerator<T>的方法哦,Array只继承了IEnumerable<T>,并没有继承IEnumerator<T>,故而无法使用MoveNext()方法。
崔鹏飞 2009-05-31
  • 打赏
  • 举报
回复
public abstract class Array : ICloneable, IList, ICollection, IEnumerable

Array是这样定义的,实现了ICollection, IEnumerable
qldsrx 2009-05-31
  • 打赏
  • 举报
回复
foreach支持迭代数组和System.Collections下的集合类,数组本身不是类,是个特例,可以用foreach迭代但不属于System.Collections,无法使用泛型方法。
qldsrx 2009-05-31
  • 打赏
  • 举报
回复
我个人的理解是,数组不是泛行对象,只有继承System.Collections下那些接口的类才能使用MoveNext等方法。
崔鹏飞 2009-05-31
  • 打赏
  • 举报
回复
补充:书上讲的原因就是foreach中需要用到IEnumerator.MoveNext(),而这个方法返回Object类型,Object中不存在到ClassTwo的转换,所以出错。这个描述确实符合
IEnumerator it = arr.GetEnumerator();
while (it.MoveNext())
{
ClassTwo temp = (ClassTwo)it.Current;
}

这一段的问题。

但是书上讲 foreach (ClassTwo item in arr){......}
也会出一样的问题,但是我运行的结果是对的。

怎么回事?是我没有理解书上哪一部分的意思啊?
lr21shiji 2009-05-31
  • 打赏
  • 举报
回复
学习一下
崔鹏飞 2009-05-31
  • 打赏
  • 举报
回复
确实是我理解错了,不好意思...
原文意思大概是这样:
这一段:
 ClassOne[] arr = { new ClassOne{FiledOne=1},new ClassOne{FiledOne=2}};

foreach (ClassTwo item in arr as IEnumerable)
{
Console.WriteLine(item.FiledTwo.ToString());
}

和这一段:
IEnumerator it = arr.GetEnumerator();
while (it.MoveNext())
{
ClassTwo temp = (ClassTwo)it.Current;
}

的结果应该是一样的,运行了一下,确实是一样,都报出了InvalidCastException

而我原来理解错误就在于写了foreach (ClassTwo item in arr)而原文写的是public void UseCollection( IEnumerable theCollection )

{

foreach ( MyType t in theCollection )

t.DoStuff( );

}


理解错了,不好意思

同时也谢谢两位
崔鹏飞 2009-05-31
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 vrhero 的回复:]
但是按照《Effective C#》中的说法,上面的foreach和下面的代码一样:
--------------------
一样的根据在哪儿?你凭什么说两段代码是一样的?

似乎LZ不久前问过一个foreach和IEnumerable的关系的问题,建议你再找出来好好看看...遇到这种问题要想想底层的实现是怎么回事,不要在表皮上钻牛角尖...
[/Quote]
原文中提到了这么一句:
事实上,下面的代码和上面foreach语句编译后的结果是一样的

不过我理解有些偏差.......
崔鹏飞 2009-05-31
  • 打赏
  • 举报
回复
自定义转换类在那原文内提到了的

cast和as操作符之间最大的区别就在于如何处理用户自定义的转换。
......
public class SecondType

{

private MyType _value;

//......

public static implicit operator

MyType( SecondType t )

{

return t._value;

}

}
vrhero 2009-05-31
  • 打赏
  • 举报
回复
但是按照《Effective C#》中的说法,上面的foreach和下面的代码一样:
--------------------
一样的根据在哪儿?你凭什么说两段代码是一样的?

似乎LZ不久前问过一个foreach和IEnumerable的关系的问题,建议你再找出来好好看看...遇到这种问题要想想底层的实现是怎么回事,不要在表皮上钻牛角尖...
qldsrx 2009-05-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 cuipengfei1 的回复:]
但是书上讲 foreach (ClassTwo item in arr){......}
也会出一样的问题,但是我运行的结果是对的。

怎么回事?是我没有理解书上哪一部分的意思啊?[/Quote]

我没有看到原文有那么一段说明,而且ClassTwo这样的自定义转换类在那原文内也没有提到,所以我才会问你是哪本书,怎么看你的问题和你给的链接有很大的出入,那文章里压根没有提到你这样的写法,更不用说你这样写行不行了。

如果一定要追究,可能这段有点类似:
既然我们已经明白了is操作符、as操作符和强制转型之间的差别,那么大家猜猜看foreach循环语句中使用的是哪个操作符来执行类型转换呢?

public void UseCollection( IEnumerable theCollection )

{

foreach ( MyType t in theCollection )

t.DoStuff( );

}

答案是强制转型。事实上,下面的代码和上面foreach语句编译后的结果是一样的:

[Quote]public void UseCollection( IEnumerable theCollection )

{

IEnumerator it = theCollection.GetEnumerator( );

while ( it.MoveNext( ) )

{

MyType t = ( MyType ) it.Current;

t.DoStuff( );

}

}[/Quote]
注意了,这里面之所以说一样的,那是因为传递了接口IEnumerable的对象,所以Foreach需要强制转换,而你的数组已经明确组内对象类型了——ClassOne,所以本身不需要强制类型转换,在那个基础上在调用ClassTwo进行自定义转换就不会出错。
颤菊大师 2009-05-31
  • 打赏
  • 举报
回复
从理论上讲,这样的转换是正确的。
考虑到匿名类型,var
课程总体目标:     本级篇面向的学员不再是完全的编程“小白”,而是具备一定C#编程经验,需要进一步查漏补缺、或者需要进一步全面完善自己C#编程知识体系的广大Unity学员。相信通过本级篇的学习,可以使得Unity初级开发人员对于编程语言的掌握更进一步;对于开发大型游戏项目,在编程语言这一层级进一步打下坚实的语言基础。 “级篇”课程解特点:       本级篇面向初级游戏研发人员,以及Unity高级学习者。为了更加深入的刨析各个语法的本质,我们采用反编译解读IL间语言的方式,来解构语法难点,使得学员最短时间掌握语法本质。 本课程解内容:       C#(for Unity)级篇 在“C#入门”、“基础篇”的基础之上,从以下四个方面着重研究我们游戏开发(包含软件开发)过程C#最重要、最实用的技能模块,使得广大游戏研发人员,对于C#这门Unity脚本有进一步更加完善的认识。一:.Net 框架解。    A) .Net 发展历史。    B)  IL  间语言。 CLR  公共语言运行时。    C) 多维数据(常用二维数组)与交数组。    D) 可变参数 Params    E) 进一步解释“实参”,“形参”。    F) 类的实例化内存分配机制。二:深入学习对象类型    A)  里氏替换原则(LSP)    B)  类的属性极其本质特性    C)  IS ,AS 关键字    D)  深入学习字符串理论        1] 字符串的“驻留性” 原理。        2] 字符串==与Equals() 的本质区别        3] 更多字符串常用方法学习。    E)  枚举类型以及适用场合。三:深入学习集合特性    A)  什么是索引器,以及索引器的适用范围。    B)  学习自定义集合类,以及深入了解Foreach 语句的原理。    C)  深入学习 ArrayList,了解内部存储机制以及原理。    D)  深入学习 HashTable,了解内部存储机制以及原理。    E)  为什么学习泛型集合?    F)  泛型集合与普通集合的性能测试对比实验。    G)  学习“泛型约束”,以及“泛型约束”的适用条件。四:委托与事件        A)  什么是委托,先从故事学习起:“老板来啦”!    B)  反编译掌握委托的本质。    C)  委托的四大开发步骤。    D)  什么是事件,以及委托与事件的区别。    E)  事件的常用使用方式。 温馨提示:       本C# for Unity 使用Virtual Studio2012,进行开发与解。(学员使用更高版本,对学习没有任何影响) 一、热更新系列(技术含量:高级):A:《lua热更新技术级篇》https://edu.csdn.net/course/detail/27087B:《热更新框架设计之Xlua基础视频课程》https://edu.csdn.net/course/detail/27110C:《热更新框架设计之热更流程与热补丁技术》https://edu.csdn.net/course/detail/27118D:《热更新框架设计之客户端热更框架(上)》https://edu.csdn.net/course/detail/27132E:《热更新框架设计之客户端热更框架()》https://edu.csdn.net/course/detail/27135F:《热更新框架设计之客户端热更框架(下)》https://edu.csdn.net/course/detail/27136二:框架设计系列(技术含量:级): A:《游戏UI界面框架设计系列视频课程》https://edu.csdn.net/course/detail/27142B:《Unity客户端框架设计PureMVC篇视频课程(上)》https://edu.csdn.net/course/detail/27172C:《Unity客户端框架设计PureMVC篇视频课程(下)》https://edu.csdn.net/course/detail/27173D:《AssetBundle框架设计_框架篇视频课程》https://edu.csdn.net/course/detail/27169三、Unity脚本从入门到精通(技术含量:初级)A:《C# For Unity系列之入门篇》https://edu.csdn.net/course/detail/4560B:《C# For Unity系列之基础篇》https://edu.csdn.net/course/detail/4595C: 《C# For Unity系列之级篇》https://edu.csdn.net/course/detail/24422D:《C# For Unity系列之进阶篇》https://edu.csdn.net/course/detail/24465四、虚拟现实(VR)与增强现实(AR):(技术含量:初级)A:《虚拟现实之汽车仿真模拟系统 》https://edu.csdn.net/course/detail/26618五、Unity基础课程系列(技术含量:初级) A:《台球游戏与FlappyBirds—Unity快速入门系列视频课程(第1部)》 https://edu.csdn.net/course/detail/24643B:《太空射击与移动端发布技术-Unity快速入门系列视频课程(第2部)》https://edu.csdn.net/course/detail/24645 C:《Unity ECS(二) 小试牛刀》https://edu.csdn.net/course/detail/27096六、Unity ARPG课程(技术含量:初级):A:《MMOARPG地下守护神_单机版实战视频课程(上部)》https://edu.csdn.net/course/detail/24965B:《MMOARPG地下守护神_单机版实战视频课程(部)》https://edu.csdn.net/course/detail/24968C:《MMOARPG地下守护神_单机版实战视频课程(下部)》https://edu.csdn.net/course/detail/24979

110,566

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧