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