名称值集合中的foreach KeyValuePair?


79

我有这个代码:

NameValueCollection nv = HttpUtility.ParseQueryString(queryString);        
foreach (KeyValuePair<String,String> pr in nv) {
    //process KeyValuePair          
}

这会编译,但是当我尝试运行它时,会得到一个InvalidCastException

为什么是这样?为什么我不能使用KeyValuePair遍历NameValueCollection,而应该使用什么呢?


我之所以喜欢这样,是因为我可以初始化一个字典,而不必在foreach之外创建后备字典变量。var nv = HttpUtility.ParseQueryString(Request.Url.Query); var qsDic = nv.Cast<object>().ToDictionary<object, string, object>(key => (string) key, key => nv[(string) key]);
松饼人

Answers:


133

首先,NameValueCollection不要使用KeyValuePair<String,String>。另外,foreach仅公开密钥:

NameValueCollection nv = HttpUtility.ParseQueryString(queryString);        
foreach (string key in nv) {
    var value = nv[key];

}

3
嗯,这很奇怪。我本来希望有一种可以同时获得两者的方法。
奥利弗

27
当我们开始使用NVC时,我们都会做。
jgauffin 2011年

1
想知道如何做到这一点...谢谢!顺便说一句,您不需要指定,KeyValuePair<String,String>因为NameValueCollection仅使用string,string。无需指定。
TheGateKeeper'4

7
请注意,此代码如何对重复键起作用。当存在重复的键时,它将返回“键值1,值2,值3”,而不是“键值1”,“键值2”,“键值3”。
Doug S

3
@Nick:NameValueCollection是.NET中最早的集合类型之一。不区分大小写并合并现有值(对某些协议有用)
jgauffin

12

您不能直接这样做,但是可以创建一个扩展方法,如下所示:

public static IEnumerable<KeyValuePair<string, string>> AsKVP(
        this NameValueCollection source
)
{
    return source.AllKeys.SelectMany(
        source.GetValues,
        (k, v) => new KeyValuePair<string, string>(k, v));
}

然后,您可以执行以下操作:

NameValueCollection nv = HttpUtility.ParseQueryString(queryString);
foreach (KeyValuePair<String,String> pr in nv.AsKVP()) {
    //process KeyValuePair          
}

注:灵感来自。需要SelectMany处理重复的键。

vb.net版本:

<Extension>
Public Function AsKVP(
        source As Specialized.NameValueCollection
) As IEnumerable(Of KeyValuePair(Of String, String))
    Dim result = source.AllKeys.SelectMany(
        AddressOf source.GetValues,
        Function(k, v) New KeyValuePair(Of String, String)(k, v))
    Return result
End Function

10

为了将来参考,您还可以使用以下语法:

foreach(string key in Request.QueryString)
{
    var value = Request.QueryString[key];
}

2
好。如果您HttpRequest可以访问,则可以跳过AllKeysQueryString属性,因为该属性是NameValueCollection
jgauffin 2014年

-1,因为您不必使用AllKeys@jgauffin提及的内容
术士

@Warlock:为此设置-1有点苛刻。您可以编辑答案,不是吗?
jgauffin 2014年

是的,对此感到抱歉,我不想伤害任何人:)但是问题不仅仅在于财产。如果您查看@jgauffin的答案,他提出了相同的想法,但该想法早已发布。因此,这篇文章看起来像是重复的文章。
术士

如果您看最后的评论,它是我写的,jgauffin如果您仔细看,答案不是重复的。
jgauffin

6

另一种扩展方法,用于学习目的:

    public static IEnumerable<KeyValuePair<string, string>> ToIEnumerable(this NameValueCollection nvc)
    {
        foreach (string key in nvc.AllKeys)
        {
            yield return new KeyValuePair<string, string>(key, nvc[key]);
        }
    }

不错的解决方案!我只建议使用nvc而不是nvc.AllKeys。我想知道为什么Microsoft伙计们没有在其中添加它System.Linq。:)
术士

2

NameValueCollection使用旧式枚举器:

        var enu = ConfigurationManager.AppSettings.GetEnumerator();

        while(enu.MoveNext())
        {
            string key = (string)enu.Current;
            string value = ConfigurationManager.AppSettings[key];
        }

0

我确实喜欢这个,而且效果很好:

 foreach (string akey in request.Query.Keys.Cast<string>())
     writer.WriteLine(akey + " = " + request.Query[akey]);

0

请注意,键名可能在查询字符串中出现多次,并且比较通常区分大小写。
如果您只想获取第一个匹配键的值而不用担心大小写,请使用以下命令:

        public string GetQueryValue(string queryKey)
        {
            foreach (string key in QueryItems)
            {
                if(queryKey.Equals(key, StringComparison.OrdinalIgnoreCase))
                    return QueryItems.GetValues(key).First(); // There might be multiple keys of the same name, but just return the first match
            }
            return null;
        }

-1
public static void PrintKeysAndValues2( NameValueCollection myCol )
{
    Console.WriteLine( "   [INDEX] KEY        VALUE" );
    for ( int i = 0; i < myCol.Count; i++ )
        Console.WriteLine( "   [{0}]     {1,-10} {2}", i, myCol.GetKey(i), myCol.Get(i) );
    Console.WriteLine();
}

http://msdn.microsoft.com/zh-cn/library/system.collections.specialized.namevaluecollection.aspx


-1您表明可以使用来访问NameValueCollection数据。但问题是为什么您不能将NameValueCollection项目转换为KeyValuePair<string, string>。也许您读得不是很仔细。最好的答案是jgauffin。提出了一个有趣的解决方案Adrian Carneiro
术士
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.