foreach KeyValuePair в NameValueCollection?
у меня есть этот код:
NameValueCollection nv = HttpUtility.ParseQueryString(queryString);
foreach (KeyValuePair<String,String> pr in nv) {
//process KeyValuePair
}
это компилирует, но когда я пытаюсь запустить его, я получаю InvalidCastException
.
Почему это? Почему я не могу использовать KeyValuePair
для итерации по a NameValueCollection
и что я должен использовать вместо этого?
8 ответов:
прежде всего,
NameValueCollection
Не использоватьKeyValuePair<String,String>
. Кроме того,foreach
только выставляет ключ:NameValueCollection nv = HttpUtility.ParseQueryString(queryString); foreach (string key in nv) { var value = nv[key]; }
вы не можете сделать это напрямую, но вы можете создать метод расширения, как так:
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
для дальнейшего использования вы также можете использовать этот синтаксис:
foreach(string key in Request.QueryString) { var value = Request.QueryString[key]; }
другой метод расширения, для целей обучения:
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]); } }
NameValueCollection использует перечислитель old-skool:
var enu = ConfigurationManager.AppSettings.GetEnumerator(); while(enu.MoveNext()) { string key = (string)enu.Current; string value = ConfigurationManager.AppSettings[key]; }
мне это понравилось, и это работает:
foreach (string akey in request.Query.Keys.Cast<string>()) writer.WriteLine(akey + " = " + request.Query[akey]);
имейте в виду, что имя ключа может отображаться несколько раз в строке запроса и что сравнение обычно чувствительно к регистру.
Если вы хотите просто получить значение первого ключа и не беспокоится о том случае, то используйте этот: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; }
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