再谈NameValueCollection
本文一开始的示例中,为什么代码 ParamsValue = Request.Params["name"]; 得到的结果是:【abc,123】?
根据前面示例代码我们可以得知:abc这个值是由QueryString提供的,123这值是由Form提供的,最后由Request.Params[]合并在一起了就变成这个样子了。有没有人想过:为什么合起来就变成了这个样子了呢?
要回答这个问题,我们需要回顾一下Params的定义:
public NameValueCollection Params
注意:它的类型是NameValueCollection 。MSDN对这个集合有个简单的说明:
此集合基于 NameObjectCollectionBase 类。但与 NameObjectCollectionBase 不同,该类在一个键下存储多个字符串值。
为了便于大家更容易理解这个类的工作方式,我画了一张草图:

【name】这个key对应差一个ArrayList,而那个ArrayList中,包含了二个字符串:abc 和 123 ,这就是它的工作方式。
既然它能在一个键值下存储多个字符串,那我们就来看一下它到底是如何实现的,直接转到Add()方法:(注意我在代码中添加的注释)
public virtual void Add(string name, string value)
{
if( base.IsReadOnly ) {
throw new NotSupportedException(SR.GetString("CollectionReadOnly"));
}
this.InvalidateCachedArrays();
// 这是一个关键的调用,它调用基类,得到每个name对应的元素,
// 而每个name对应的元素是一个ArrayList
ArrayList list = (ArrayList)base.BaseGet(name);
if( list == null ) {
// 如果不存在name对应的元素,则创建ArrayList
list = new ArrayList(1);
if( value != null ) {
// 添加value到ArrayList,它将是第一个值
list.Add(value);
}
base.BaseAdd(name, list);
}
else if( value != null ) {
// 在原有的ArrayList中继续添加新的值
list.Add(value);
}
}
{
if( base.IsReadOnly ) {
throw new NotSupportedException(SR.GetString("CollectionReadOnly"));
}
this.InvalidateCachedArrays();
// 这是一个关键的调用,它调用基类,得到每个name对应的元素,
// 而每个name对应的元素是一个ArrayList
ArrayList list = (ArrayList)base.BaseGet(name);
if( list == null ) {
// 如果不存在name对应的元素,则创建ArrayList
list = new ArrayList(1);
if( value != null ) {
// 添加value到ArrayList,它将是第一个值
list.Add(value);
}
base.BaseAdd(name, list);
}
else if( value != null ) {
// 在原有的ArrayList中继续添加新的值
list.Add(value);
}
}
我们再来看一下当我们访问Params[]这个索引器时,.net framework又是如何实现的:
public string this[string name]
{
get { return this.Get(name); }
set { this.Set(name, value); }
}
public virtual string Get(string name)
{
// 根据name得到ArrayList
ArrayList list = (ArrayList) base.BaseGet(name);
// 将ArrayList变成一个字符串行
return GetAsOneString(list);
}
private static string GetAsOneString(ArrayList list)
{
int num = (list != null) ? list.Count : 0;
if( num == 1 ) {
return (string)list[0];
}
if( num <= 1 ) {
return null;
}
StringBuilder builder = new StringBuilder((string)list[0]);
for( int i = 1; i < num; i++ ) {
builder.Append(','); // 逗号就来源于此。
builder.Append((string)list[i]);
}
return builder.ToString();
}
{
get { return this.Get(name); }
set { this.Set(name, value); }
}
public virtual string Get(string name)
{
// 根据name得到ArrayList
ArrayList list = (ArrayList) base.BaseGet(name);
// 将ArrayList变成一个字符串行
return GetAsOneString(list);
}
private static string GetAsOneString(ArrayList list)
{
int num = (list != null) ? list.Count : 0;
if( num == 1 ) {
return (string)list[0];
}
if( num <= 1 ) {
return null;
}
StringBuilder builder = new StringBuilder((string)list[0]);
for( int i = 1; i < num; i++ ) {
builder.Append(','); // 逗号就来源于此。
builder.Append((string)list[i]);
}
return builder.ToString();
}