foreach KeyValuePair in NameValueCollection?

79

Ich habe diesen Code:

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

Dies wird kompiliert, aber wenn ich versuche, es auszuführen, bekomme ich eine InvalidCastException.

Warum ist das? Warum kann ich nicht KeyValuePairüber a iterieren NameValueCollectionund was soll ich stattdessen verwenden?

Oliver
quelle
Ich mag dies, da ich ein Wörterbuch initiieren kann, ohne zusätzlich zu einem foreach eine Hintergrundwörterbuchvariable erstellen zu müssen. var nv = HttpUtility.ParseQueryString(Request.Url.Query); var qsDic = nv.Cast<object>().ToDictionary<object, string, object>(key => (string) key, key => nv[(string) key]);
Der Muffin-Mann

Antworten:

129

Erstens NameValueCollectionnicht verwendet KeyValuePair<String,String>. Außerdem wird foreachnur der Schlüssel angezeigt:

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

}
jgauffin
quelle
3
Hmm, das ist irgendwie komisch. Ich hätte erwartet, dass es einen Weg gibt, beides gleichzeitig zu bekommen.
Oliver
26
Wir alle tun dies, wenn wir einen NVC verwenden.
Jgauffin
1
Ich habe mich gefragt, wie das geht ... danke! Übrigens müssen Sie nicht angeben, KeyValuePair<String,String>da die NameValueCollection nur Zeichenfolge, Zeichenfolge verwendet. Keine Notwendigkeit, es anzugeben.
TheGateKeeper
7
Beachten Sie, wie dieser Code für doppelte Schlüssel funktioniert. Wenn doppelte Schlüssel vorhanden sind, wird "Schlüsselwert1, Wert2, Wert3" anstelle von "Schlüsselwert1", dann "Schlüsselwert2" und "Schlüsselwert3" zurückgegeben.
Doug S
3
@Nick: NameValueCollection ist einer der ersten Sammlungstypen in .NET. Es unterscheidet nicht zwischen Groß- und Kleinschreibung und führt vorhandene Werte zusammen (was für einige Protokolle nützlich ist)
jgauffin
11

Sie können das nicht direkt tun, aber Sie können eine Erweiterungsmethode wie folgt erstellen:

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

Dann können Sie tun:

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

Hinweis: inspiriert durch diese . SelectMany ist erforderlich, um doppelte Schlüssel zu verarbeiten.

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
Endy Tjahjono
quelle
10

Zum späteren Nachschlagen können Sie auch diese Syntax verwenden:

foreach(string key in Request.QueryString)
{
    var value = Request.QueryString[key];
}
Sebastien Morin
quelle
2
Gut. Wenn Sie Zugriff auf die haben HttpRequest, können Sie überspringen, AllKeysda die QueryStringEigenschaft eine ist NameValueCollection.
Jgauffin
-1, weil Sie nicht AllKeyswie @jgauffin erwähnt verwenden müssen
Warlock
@ Warlock: Eine -1 dafür zu geben ist ein bisschen hart. Sie können die Antwort bearbeiten, nicht wahr?
Jgauffin
Ja, tut mir leid, ich wollte niemanden verletzen :) Aber das Problem lag nicht nur auf dem Grundstück. Wenn Sie sich die Antwort von @ jgauffin ansehen, schlug er dieselbe Idee vor, die jedoch früher veröffentlicht wurde. Dieser Beitrag sieht also wie eine Vervielfältigung aus.
Hexenmeister
Wenn Sie sich den letzten Kommentar ansehen, der von mir geschrieben wurde, sind jgauffindie Antworten keine Duplikate, wenn Sie genauer hinschauen.
Jgauffin
6

Eine andere Erweiterungsmethode für Lernzwecke:

    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]);
        }
    }
Adriano Carneiro
quelle
Schöne Lösung! Ich würde nur vorschlagen, nvcstatt zu verwenden nvc.AllKeys. Ich frage mich, warum Microsoft-Leute dies nicht hinzugefügt haben System.Linq. :)
Hexenmeister
2

NameValueCollection verwendet den Old-Skool-Enumerator:

        var enu = ConfigurationManager.AppSettings.GetEnumerator();

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

Mir hat das gefallen und es funktioniert:

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

Beachten Sie, dass der Schlüsselname möglicherweise mehrmals in der Abfragezeichenfolge vorkommt und dass beim Vergleich normalerweise zwischen Groß- und Kleinschreibung unterschieden wird.
Wenn Sie nur den Wert des ersten passenden Schlüssels erhalten möchten und sich nicht um die Groß- und Kleinschreibung kümmern möchten, verwenden Sie Folgendes:

        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;
        }
userSteve
quelle
-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/en-us/library/system.collections.specialized.namevaluecollection.aspx

pfeifenzl
quelle
-1 Sie zeigen, dass der Zugriff auf NameValueCollectionDaten möglich ist. Die Frage ist jedoch, warum Sie keine NameValueCollectionElemente in konvertieren können KeyValuePair<string, string>. Vielleicht haben Sie die Frage nicht sehr sorgfältig gelesen. Die beste Antwort wurde von gegeben jgauffin. Eine interessante Lösung wurde von vorgeschlagen Adrian Carneiro.
Hexenmeister