valid - method summary c#
Compruebe si la clave existe en NameValueCollection (11)
¿Existe una forma rápida y sencilla de verificar si existe una clave en NameValueCollection sin recorrerla?
Buscando algo así como Dictionary.ContainsKey () o similar.
Hay muchas formas de resolver esto, por supuesto. Me pregunto si alguien puede ayudar a rascarme la comezón en el cerebro.
Como puede ver en las fuentes de referencia, NameValueCollection hereda de NameObjectCollectionBase .
Así que tomas el tipo base, obtienes la tabla hash privada a través de la reflexión y compruebas si contiene una clave específica.
Para que también funcione en Mono, necesitas ver cuál es el nombre de la tabla hash en mono, que es algo que puedes ver here (m_ItemsContainer), y obtener el mono campo, si la FieldInfo inicial es nula (mono- tiempo de ejecución).
Me gusta esto
public static class ParameterExtensions
{
private static System.Reflection.FieldInfo InitFieldInfo()
{
System.Type t = typeof(System.Collections.Specialized.NameObjectCollectionBase);
System.Reflection.FieldInfo fi = t.GetField("_entriesTable", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if(fi == null) // Mono
fi = t.GetField("m_ItemsContainer", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
return fi;
}
private static System.Reflection.FieldInfo m_fi = InitFieldInfo();
public static bool Contains(this System.Collections.Specialized.NameValueCollection nvc, string key)
{
//System.Collections.Specialized.NameValueCollection nvc = new System.Collections.Specialized.NameValueCollection();
//nvc.Add("hello", "world");
//nvc.Add("test", "case");
// The Hashtable is case-INsensitive
System.Collections.Hashtable ent = (System.Collections.Hashtable)m_fi.GetValue(nvc);
return ent.ContainsKey(key);
}
}
para el código .NET 2.0 no reflectante ultrapuro, puede recorrer las teclas en lugar de usar la tabla hash, pero eso es lento.
private static bool ContainsKey(System.Collections.Specialized.NameValueCollection nvc, string key)
{
foreach (string str in nvc.AllKeys)
{
if (System.StringComparer.InvariantCultureIgnoreCase.Equals(str, key))
return true;
}
return false;
}
Desde MSDN :
Esta propiedad devuelve nulo en los siguientes casos:
1) si la clave especificada no se encuentra;
Entonces puedes simplemente:
NameValueCollection collection = ...
string value = collection[key];
if (value == null) // key doesn''t exist
2) si se encuentra la clave especificada y su valor asociado es nulo.
collection[key]
llama a base.Get()
luego base.FindEntry()
que internamente usa Hashtable
con rendimiento O (1).
En VB es:
if not MyNameValueCollection(Key) is Nothing then
.......
end if
En C # solo debería ser:
if (MyNameValueCollection(Key) != null) { }
No estoy seguro si debería ser null
o ""
pero esto debería ayudar.
Esto también podría ser una solución sin tener que introducir un nuevo método:
item = collection["item"] != null ? collection["item"].ToString() : null;
Estoy usando esta colección, cuando trabajé en la colección de elementos pequeños.
Donde los elementos están mucho, creo que necesito usar "Diccionario". Mi código:
NameValueCollection ProdIdes;
string prodId = _cfg.ProdIdes[key];
if (string.IsNullOrEmpty(prodId))
{
......
}
O puede usar esto:
string prodId = _cfg.ProdIdes[key] !=null ? "found" : "not found";
No creo que ninguna de estas respuestas sea correcta / óptima. NameValueCollection no solo no distingue entre valores nulos y valores perdidos, sino que también distingue entre mayúsculas y minúsculas con respecto a sus claves. Por lo tanto, creo que una solución completa sería:
public static bool ContainsKey(this NameValueCollection @this, string key)
{
return @this.Get(key) != null
// I''m using Keys instead of AllKeys because AllKeys, being a mutable array,
// can get out-of-sync if mutated (it weirdly re-syncs when you modify the collection).
// I''m also not 100% sure that OrdinalIgnoreCase is the right comparer to use here.
// The MSDN docs only say that the "default" case-insensitive comparer is used
// but it could be current culture or invariant culture
|| @this.Keys.Cast<string>().Contains(key, StringComparer.OrdinalIgnoreCase);
}
Puede usar el método Get
y verificar null
ya que el método devolverá null
si NameValueCollection no contiene la clave especificada.
Ver MSDN .
Sí, puede usar Linq para verificar la propiedad AllKeys
:
using System.Linq;
...
collection.AllKeys.Contains(key);
Sin embargo, un Dictionary<string, string[]>
sería mucho más adecuado para este propósito, tal vez creado a través de un método de extensión:
public static void Dictionary<string, string[]> ToDictionary(this NameValueCollection collection)
{
return collection.Cast<string>().ToDictionary(key => key, key => collection.GetValues(key));
}
var dictionary = collection.ToDictionary();
if (dictionary.ContainsKey(key))
{
...
}
Si el tamaño de la colección es pequeño, puede ir con la solución proporcionada por rich.okelly. Sin embargo, una gran colección significa que la generación del diccionario puede ser notablemente más lenta que solo buscar en la colección de claves.
Además, si su escenario de uso está buscando claves en diferentes puntos en el tiempo, donde puede haber sido modificado NameValueCollection, generar el diccionario cada vez puede, de nuevo, ser más lento que simplemente buscar en la colección de claves.
Usa este método:
private static bool ContainsKey(NameValueCollection collection, string key)
{
if (collection.Get(key) == null)
{
return collection.AllKeys.Contains(key);
}
return true;
}
Es el más eficiente para NameValueCollection
y no depende de que la colección contenga valores null
o no.
NameValueCollection n = Request.QueryString;
if (n.HasKeys())
{
//something
}
Tipo de valor devuelto: System.Boolean true si NameValueCollection contiene claves que no son nulas; de lo contrario, falso. LINK