มีวิธีที่ง่ายและรวดเร็วในการตรวจสอบว่ามีคีย์อยู่ใน NameValueCollection หรือไม่โดยไม่ต้องวนซ้ำ
กำลังมองหาสิ่งที่ต้องการ Dictionary.ContainsKey () หรือคล้ายกัน
มีหลายวิธีในการแก้ปัญหานี้แน่นอน เพียงแค่สงสัยว่ามีใครสามารถช่วยเกาสมองของฉัน
มีวิธีที่ง่ายและรวดเร็วในการตรวจสอบว่ามีคีย์อยู่ใน NameValueCollection หรือไม่โดยไม่ต้องวนซ้ำ
กำลังมองหาสิ่งที่ต้องการ Dictionary.ContainsKey () หรือคล้ายกัน
มีหลายวิธีในการแก้ปัญหานี้แน่นอน เพียงแค่สงสัยว่ามีใครสามารถช่วยเกาสมองของฉัน
คำตอบ:
จากMSDN :
คุณสมบัตินี้ส่งคืน null ในกรณีต่อไปนี้:
1) หากไม่พบคีย์ที่ระบุ
ดังนั้นคุณสามารถ:
NameValueCollection collection = ...
string value = collection[key];
if (value == null) // key doesn't exist
2) ถ้าพบคีย์ที่ระบุและค่าที่เกี่ยวข้องเป็นโมฆะ
collection[key]
การโทรbase.Get()
จากนั้นbase.FindEntry()
ซึ่งใช้ภายในHashtable
กับประสิทธิภาพ O (1)
0
เท่ากับnull
... sry
ใช้วิธีนี้:
private static bool ContainsKey(this NameValueCollection collection, string key)
{
if (collection.Get(key) == null)
{
return collection.AllKeys.Contains(key);
}
return true;
}
มันมีประสิทธิภาพมากที่สุดNameValueCollection
และไม่ได้ขึ้นอยู่กับว่าการสะสมนั้นมีnull
ค่าหรือไม่
using System.Linq;
เมื่อใช้โซลูชันนี้
ฉันไม่คิดว่าคำตอบใด ๆ เหล่านี้ค่อนข้างถูก / เหมาะสมที่สุด NameValueCollection ไม่เพียง แต่ไม่แยกความแตกต่างระหว่างค่า Null และค่าที่ขาดหายไป แต่ยังคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ด้วยการคำนึงถึงคีย์ ดังนั้นฉันคิดว่าวิธีแก้ปัญหาเต็มรูปแบบจะเป็น:
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);
}
ใช่คุณสามารถใช้ Linq เพื่อตรวจสอบAllKeys
คุณสมบัติ:
using System.Linq;
...
collection.AllKeys.Contains(key);
อย่างไรก็ตาม a Dictionary<string, string[]>
จะเหมาะกว่ากับจุดประสงค์นี้มากบางทีอาจสร้างขึ้นโดยวิธีการส่วนขยาย:
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))
{
...
}
collection[key]
ใช้ภายในHashtable
ซึ่งเป็น O (1)
collection[key]
ไม่แยกความแตกต่างระหว่างคีย์ที่ไม่มีอยู่และค่า Null ถูกเก็บไว้กับคีย์นั้น
คุณสามารถใช้Get
วิธีการและตรวจสอบnull
ว่าวิธีการจะกลับมาnull
ถ้า NameValueCollection ไม่มีคีย์ที่ระบุ
index
วิธีkey
การโทร ไม่ใช่เหรอ
หากขนาดของคอลเล็กชั่นมีขนาดเล็กคุณสามารถไปกับโซลูชันที่จัดทำโดย rich.okelly อย่างไรก็ตามคอลเลกชันขนาดใหญ่หมายความว่าการสร้างพจนานุกรมอาจช้ากว่าการค้นหาคีย์คอลเลกชัน
นอกจากนี้หากสถานการณ์การใช้งานของคุณกำลังค้นหากุญแจในจุดต่าง ๆ ในเวลาที่อาจมีการปรับเปลี่ยน NameValueCollection การสร้างพจนานุกรมในแต่ละครั้งอาจช้ากว่าการค้นหาชุดกุญแจ
นี่อาจเป็นวิธีแก้ปัญหาโดยไม่ต้องแนะนำวิธีการใหม่:
item = collection["item"] != null ? collection["item"].ToString() : null;
อย่างที่คุณเห็นในแหล่งอ้างอิงNameValueCollectionสืบทอดจากNameObjectCollectionBase NameObjectCollectionBase
ดังนั้นคุณจะใช้ประเภทฐานรับ hashtable ส่วนตัวผ่านการสะท้อนและตรวจสอบว่ามันมีคีย์เฉพาะ
เพื่อให้สามารถทำงานใน Mono ได้เช่นกันคุณต้องดูว่าชื่อของ hashtable เป็นอะไรใน mono ซึ่งเป็นสิ่งที่คุณเห็นได้ที่นี่ (m_ItemsContainer) และรับ mono-field ถ้า FieldInfo เริ่มต้นเป็นโมฆะ (mono- รันไทม์)
แบบนี้
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);
}
}
สำหรับรหัส. NET 2.0 ที่ไม่สะท้อนแสงแบบ ultra-pure คุณสามารถวนลูปผ่านคีย์แทนการใช้ตารางแฮช แต่นั่นช้า
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;
}
ใน VB มันคือ:
if not MyNameValueCollection(Key) is Nothing then
.......
end if
ใน C # ควรจะเป็น:
if (MyNameValueCollection(Key) != null) { }
ไม่แน่ใจว่าควรจะเป็นnull
หรือ""
แต่สิ่งนี้จะช่วย
Dictionary
โครงสร้างข้อมูลในขณะที่MyNameValueCollection[Key]
มากกว่าMyNameValueCollection(Key)
ซึ่งคาดว่าจะมีวิธีการเรียก
ฉันใช้คอลเลกชันนี้เมื่อฉันทำงานในคอลเลกชันองค์ประกอบขนาดเล็ก
ฉันคิดว่าจำเป็นต้องใช้ "พจนานุกรม" ในที่ที่มีองค์ประกอบมากมาย รหัสของฉัน:
NameValueCollection ProdIdes;
string prodId = _cfg.ProdIdes[key];
if (string.IsNullOrEmpty(prodId))
{
......
}
หรืออาจจะใช้สิ่งนี้:
string prodId = _cfg.ProdIdes[key] !=null ? "found" : "not found";
queryItems.AllKeys.Contains(key)
โปรดทราบว่ารหัสอาจไม่ซ้ำกันและโดยทั่วไปการเปรียบเทียบจะคำนึงถึงตัวพิมพ์ หากคุณต้องการเพียงรับค่าของคีย์การจับคู่แรกและไม่สนใจเกี่ยวกับตัวพิมพ์เล็กให้ใช้สิ่งนี้:
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;
}
NameValueCollection n = Request.QueryString;
if (n.HasKeys())
{
//something
}
ประเภทค่าตอบแทน: System.Boolean จริงถ้า NameValueCollection มีกุญแจที่ไม่เป็นโมฆะ; มิฉะนั้นเป็นเท็จ LINK