키가 없으면 Dictionary의 인덱서에서 예외가 발생합니다. 대신 default (T)를 반환하는 IDictionary의 구현이 있습니까?
“TryGetValue”메소드에 대해 알고 있지만 linq와 함께 사용할 수 없습니다.
이것이 내가 필요한 것을 효율적으로 수행 할 것인가? :
myDict.FirstOrDefault(a => a.Key == someKeyKalue);
해시 조회를 사용하는 대신 키를 반복한다고 생각하므로 그렇게 생각하지 않습니다.
답변
실제로, 그것은 전혀 효율적이지 않을 것입니다.
항상 확장 방법을 작성할 수 있습니다.
public static TValue GetValueOrDefault<TKey,TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key)
{
TValue ret;
// Ignore return value
dictionary.TryGetValue(key, out ret);
return ret;
}
또는 C # 7.1의 경우 :
public static TValue GetValueOrDefault<TKey,TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key) =>
dictionary.TryGetValue(key, out var ret) ? ret : default;
그것은 다음을 사용합니다.
- 식 본문 방법 (C # 6)
- 아웃 변수 (C # 7.0)
- 기본 리터럴 (C # 7.1)
답변
이러한 확장 방법을 수행하면 도움이 될 수 있습니다.
public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key)
{
return dict.GetValueOrDefault(key, default(V));
}
public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key, V defVal)
{
return dict.GetValueOrDefault(key, () => defVal);
}
public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dict, K key, Func<V> defValSelector)
{
V value;
return dict.TryGetValue(key, out value) ? value : defValSelector();
}
답변
.net 코어 2 이상 (C # 7.X)을 사용하는 사람이 있으면 CollectionExtensions 클래스가 도입되고 키가 사전에없는 경우 GetValueOrDefault 메서드를 사용 하여 기본값을 가져올 수 있습니다 .
Dictionary<string, string> colorData = new Dictionary<string, string>();
string color = colorData.GetValueOrDefault("colorId", string.Empty);
답변
Collections.Specialized.StringDictionary
누락 된 키 값을 찾을 때 예외가 아닌 결과를 제공합니다. 기본적으로 대소 문자를 구분하지 않습니다.
경고
그것은 특수 용도로만 유효하며 제네릭보다 먼저 설계되었으므로 전체 컬렉션을 검토 해야하는 경우 매우 좋은 열거자가 없습니다.
답변
.Net Core를 사용하는 경우 CollectionExtensions.GetValueOrDefault 메서드를 사용할 수 있습니다 . 이것은 허용 된 답변에 제공된 구현과 동일합니다.
public static TValue GetValueOrDefault<TKey,TValue> (
this System.Collections.Generic.IReadOnlyDictionary<TKey,TValue> dictionary,
TKey key);
답변
public class DefaultIndexerDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private IDictionary<TKey, TValue> _dict = new Dictionary<TKey, TValue>();
public TValue this[TKey key]
{
get
{
TValue val;
if (!TryGetValue(key, out val))
return default(TValue);
return val;
}
set { _dict[key] = value; }
}
public ICollection<TKey> Keys => _dict.Keys;
public ICollection<TValue> Values => _dict.Values;
public int Count => _dict.Count;
public bool IsReadOnly => _dict.IsReadOnly;
public void Add(TKey key, TValue value)
{
_dict.Add(key, value);
}
public void Add(KeyValuePair<TKey, TValue> item)
{
_dict.Add(item);
}
public void Clear()
{
_dict.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return _dict.Contains(item);
}
public bool ContainsKey(TKey key)
{
return _dict.ContainsKey(key);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
_dict.CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _dict.GetEnumerator();
}
public bool Remove(TKey key)
{
return _dict.Remove(key);
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return _dict.Remove(item);
}
public bool TryGetValue(TKey key, out TValue value)
{
return _dict.TryGetValue(key, out value);
}
IEnumerator IEnumerable.GetEnumerator()
{
return _dict.GetEnumerator();
}
}
답변
사전의 키 조회 기능에 대한 인터페이스를 정의 할 수 있습니다. 아마 그것을 다음과 같이 정의 할 것입니다 :
Interface IKeyLookup(Of Out TValue)
Function Contains(Key As Object)
Function GetValueIfExists(Key As Object) As TValue
Function GetValueIfExists(Key As Object, ByRef Succeeded As Boolean) As TValue
End Interface
Interface IKeyLookup(Of In TKey, Out TValue)
Inherits IKeyLookup(Of Out TValue)
Function Contains(Key As TKey)
Function GetValue(Key As TKey) As TValue
Function GetValueIfExists(Key As TKey) As TValue
Function GetValueIfExists(Key As TKey, ByRef Succeeded As Boolean) As TValue
End Interface
제네릭이 아닌 키가있는 버전을 사용하면 비 구조 키 유형을 사용하는 코드를 사용하는 코드에서 임의의 키 분산을 허용 할 수 있으며, 일반 유형 매개 변수로는 불가능합니다. 후자는 허용하기 때문에 가변을 가변 Dictionary(Of Cat, String)
으로 사용할 수 없습니다 . 그러나 mutable 을 immutable로 사용하는 데 아무런 문제가 없습니다 . 완벽하게 잘 구성된 표현으로 간주되어야하기 때문에 ( 사전을 검색하지 않고도 유형이 아닌 모든 것을 반환해야 합니다 ).Dictionary(Of Animal, String)
SomeDictionaryOfCat.Add(FionaTheFish, "Fiona")
Dictionary(Of Cat, String)
Dictionary(Of Animal, String)
SomeDictionaryOfCat.Contains(FionaTheFish)
false
Cat
불행히도 실제로 이러한 인터페이스를 사용할 수있는 유일한 방법은 인터페이스 Dictionary
를 구현하는 클래스에서 객체를 래핑하는 것입니다. 그러나 수행중인 작업에 따라 그러한 인터페이스와 허용되는 차이로 인해 노력할 가치가 있습니다.