Home » c# » foreach KeyValuePair in NameValueCollection?

foreach KeyValuePair in NameValueCollection?

Posted by: admin November 29, 2017 Leave a comment

Questions:

I have this code:

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

This compiles, but when I try to run it I get an InvalidCastException.

Why is this? Why can’t I use KeyValuePair to iterate over a NameValueCollection, and what should I use instead?

Answers:

First of all, NameValueCollection doesn’t use KeyValuePair<String,String>. Also, foreach only exposes the key:

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

}

Questions:
Answers:

You can’t do that directly, but you can create an extension method like so:

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

Then you can do:

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

Note: inspired by this. SelectMany is required to handle duplicate keys.

vb.net version:

<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

Questions:
Answers:

For future reference, you could also use this syntax:

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

Questions:
Answers:

ANother extension method, for learning purposes:

    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]);
        }
    }

Questions:
Answers:

NameValueCollection uses the old-skool enumerator:

        var enu = ConfigurationManager.AppSettings.GetEnumerator();

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

Questions:
Answers:

I did like this and it works:

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

Questions:
Answers:
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/en-us/library/system.collections.specialized.namevaluecollection.aspx