为什么foreach(HttpCookie cookie in Request.Cookies)会出错

第一次使用foreach(HttpCookie cookie in Request.Cookies)的时候, 我怎么也没想到它会出错,错误信息竟然是“指定的转换无效。”。Request.Cookies的类型是HttpCookieCollection,怎么会出错呢?HttpCookieCollection难道有与众不同的地方?
    既然不能转换,那cookie究竟是什么类型?我们用代码测试一下:

原来cookie全变成了System.String类型, 上面的cookie变量的值就是Request.Cookies中每个Cookie的Name。下面的两段代码,结果是一样的:

那我们如何枚举Request.Cookies?通过索引,我也不用多说了,大家都知道。

而Syste.Net.CookieCollection不存在这个问题,那HttpCookieCollection与CookieCollection有什么区别呢?我们比较一下它们的基类与接口:
HttpCookieCollection 继承了NameObjectCollectionBase,NameObjectCollectionBase实现了ICollection, IEnumerable, ISerializable, IDeserializationCallback接口
CookieCollection实现了ICollection, IEnumerable接口

我想应该在NameObjectCollectionBase中可以找到答案。
首先我们复习一下foreach的工作原理,先看下面的代码:

对于foreach(HttpCookie cookie in Request.Cookies), 转换的结果应该是这样:

因为上面的enumerator.Current返回的是System.String类型,所以会出现“指定的转换无效”的错误。
用Reflector查看NameObjectCollectionBase的源代码,可以发现 HttpCookieCollection.GetEnumerator()调用的是NameObjectCollectionBase中的GetEnumerator(),而GetEnumerator()返回的是NameObjectCollectionBase内部的一个类NameObjectKeysEnumerator的实例,这个类实现了IEnumerator。 
上面的enumerator.Current实际上是调用的NameObjectKeysEnumerator的Current属性,而Current属性中又调用了NameObjectCollectionBase的BaseGetKey。头都昏了! 为了找到问题的真正原因,只能继续。BaseGetKey的代码是这样的:

答案终于找到,NameObjectCollectionBase返回的是NameObjectEntry(这也是NameObjectCollectionBase的一个内部类)的一个成员Key, 这个Key就是string类型的。
问题的原因虽然找到,但为什么要这样设计?

为什么HttpCookieCollection的Enumerator只对Key进行遍历,我想这主要是出于性能的考虑。返回一个Key比返回一个Cookie对象效率高。

你期望在对Cookies做遍历操作(Enumerate)时返回Cookie对象, 但Enumerator如果返回Cookie是需要做一个 new Cookie()操作,这意味着会来一个对象拷贝。有些Cookie对象是比较大, 拷贝效率非常低。

遍历Cookies可以这样:
foreach(string key in Request.Cookies)
{
Cookie cookie = Request.Cookies[key]; //没有产生新Cookie对象, 效率比较高。

// your code
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值