foreach KeyValuePair in NameValueCollection?

C#

C# Problem Overview


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?

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

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

Solution 3 - C#

For future reference, you could also use this syntax:

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

Solution 4 - C#

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

Solution 5 - C#

NameValueCollection uses the old-skool enumerator:

        var enu = ConfigurationManager.AppSettings.GetEnumerator();

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

Solution 6 - C#

I did like this and it works:

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

Solution 7 - C#

Be aware that the key name might appear more than once in the query string and that the comparison is usually case sensitive.
If you want to just get the value of the first matching key and not bothered about case then use this:

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

Solution 8 - C#

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOliverView Question on Stackoverflow
Solution 1 - C#jgauffinView Answer on Stackoverflow
Solution 2 - C#Endy TjahjonoView Answer on Stackoverflow
Solution 3 - C#Sebastien MorinView Answer on Stackoverflow
Solution 4 - C#Adriano CarneiroView Answer on Stackoverflow
Solution 5 - C#DavidWainwrightView Answer on Stackoverflow
Solution 6 - C#NamuresView Answer on Stackoverflow
Solution 7 - C#userSteveView Answer on Stackoverflow
Solution 8 - C#whistlezlView Answer on Stackoverflow