c# – 向IEnumerator投射IEnumerable做什么
我正在培训初学者一些C#的核心概念.在为随机数创建IEnumerable时,他的代码中的错误建议投射IEnumerable< T>.到IEnumerator< T>
我知道这些接口都没有相互实现,所以令我印象深刻的是ReSharper,编译器和运行时都没有引发异常. 这是一些示例代码: public class SomeEnumerable : IEnumerable<int> { private readonly IEnumerable<int> _numbers; public SomeEnumerable() { _numbers = Enumerable.Range(0,10); } public IEnumerator<int> GetEnumerator() { return (IEnumerator<int>) _numbers; } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 出乎意料的是,GetEnumerator-Method编译得非常好.当初学者错误地将私人字段“_numbers”放入时,ReSharper甚至建议添加我已包含的显式演员. 现在考虑以下测试代码: var someEnumerable = new SomeEnumerable(); Console.WriteLine($"Number of elements: {someEnumerable.Count()}"); Count() – Method调用枚举器,输出如下:
奇怪的是,如果你改变类的构造函数,使它使用IList< T>对于私人领域 public SomeEnumerable() { _numbers = Enumerable.Range(0,10).ToArray(); } 代码抛出正确的InvalidCastException. 我知道Enumerable.Range()在其实现中使用yield语句,并且只要实现了GetEnumerator方法,编译器就可以做一些魔术,所以也许这是一个提示. 因此,我的问题是: >为什么演员合法,为什么没有警告? (编译时间/ Resharper) 一些澄清: 解决方法
演员的全部意义在于你告诉编译器,“我知道你不认为这种类型实际上是另一种类型,但我比你知道更多,让我把它看作是这个其他类型如果我错了,在运行时抛出异常.
你不能投出任何IEnumerable< T>到IEnumerator< T>.这个特定对象恰好实现了两个接口.其他对象,例如你编写的SomeEnumerable,只会实现其中一个,而像这样的强制转换对它们来说会失败(在运行时).
该对象不期望您将其转换为另一种类型并开始在其上调用方法.你违反了合同类型.如果你想让它正常工作,请调用GetEnumerator,它会为你提供一个合适的枚举器.实际上,由于您破坏了初始化其数据的方法,因此您将获得一个未正确初始化的枚举器.
它只是一个看起来像这样的类型: public class SomeClass: IEnumerable<int>,IEnumerator<int> { //... } 如果你愿意,你可以写一个这样的类. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |