Вам нужен только один метод расширения. Переопределите его следующим образом:
public static TValue? GetNullableKey<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> dictionary, TKey, key) where TValue : struct
{
// Your code here.
// Per @nmclean: to reap performance benefits of dictionary lookup, try to cast
// dictionary to the expected dictionary type, e.g. IDictionary<K, V> or
// IReadOnlyDictionary<K, V>. Thanks for that nmclean!
}
И IDictionary<TKey, TValue>
, и IReadOnlyDictionary<TKey, TValue>
наследуются от IEnumerable<KeyValuePair<TKey, TValue>>
.
ХТН.
ОБНОВЛЕНИЕ: чтобы ответить на ваш вопрос в комментариях
Если вам не нужно вызывать методы, которые появляются только в одном или другом интерфейсе (т. е. вы вызываете только методы, которые существуют в IEnumerable<KeyValuePair<TKey, TValue>>
), то нет, вам не нужен этот код.
Если вам нужно вызывать методы в интерфейсе IDictionary<TKey, TValue>
или IReadOnlyDictionary<TKey, TValue>
, которых нет в общем базовом интерфейсе, тогда да, вам нужно будет увидеть, является ли ваш объект одним или другим, чтобы узнать, какие методы допустимы. называется.
ОБНОВЛЕНИЕ: возможно (скорее всего) вам не следует использовать это решение
Итак, технически это решение является правильным при ответе на вопрос ОП, как указано. Однако это действительно не очень хорошая идея, как прокомментировали другие ниже, и как я признал эти комментарии правильными.
Во-первых, весь смысл словаря/карты заключается в поиске O (1) (постоянное время). Используя приведенное выше решение, вы превратили операцию O(1) в операцию O(n) (линейное время). Если в вашем словаре 1 000 000 элементов, поиск значения ключа занимает в 1 миллион раз больше времени (если вам действительно не повезло). Это может существенно повлиять на производительность.
А маленький словарь? Что ж, тогда возникает вопрос, действительно ли вам нужен словарь? Не лучше ли со списком? Или, возможно, еще лучший вопрос: когда вы начинаете замечать влияние на производительность использования поиска O(n) вместо O(1) и как часто вы ожидаете выполнять такой поиск?
Наконец, ситуация OP с объектом, который реализует оба IReadOnlyDictionary<TKey, TValue>
и IDictionary<TKey, TValue>
, довольно странная, поскольку поведение IDictionary<TKey, TValue>
является надмножеством поведения IReadOnlyDictionary<TKey, TValue>
. И стандартный класс Dictionary<TKey, TValue>
уже реализует оба этих интерфейса. Поэтому, если бы тип OP (я предполагаю, специализированный) вместо этого унаследовал от Dictionary<TKey, TValue>
, то, когда требовалась функциональность только для чтения, тип можно было бы просто преобразовать в IReadOnlyDictionary<TKey, TValue>
, возможно, вообще избегая всей этой проблемы. Даже если проблема не была неизбежной (например, где-то делается приведение к одному из интерфейсов), все равно было бы лучше реализовать два метода расширения, по одному для каждого из интерфейсов.
Я думаю, что прежде чем я закончу эту тему, необходимо сделать еще один пункт. Преобразование Dictionary<TKey, TValue>
в IReadOnlyDictionary<TKey, TValue>
гарантирует только то, что все, что получает преобразованное значение, само не сможет изменить базовую коллекцию. Однако это не означает, что другие ссылки на экземпляр словаря, из которого была создана приведенная ссылка, не изменят базовую коллекцию. Это одна из проблем, связанных с интерфейсами коллекций IReadOnly*
. Коллекции, на которые ссылаются эти интерфейсы, не могут быть действительно коллекциями «только для чтения» (или, как часто подразумевается, неизменяемыми), они просто предотвращают изменение коллекции конкретной ссылкой (несмотря на фактический экземпляр конкретного класса ReadOnly*
). Это одна из причин (среди прочих), что было создано пространство имен System.Collections.Immutable
классов коллекций. Коллекции в этом пространстве имен представляют собой действительно неизменяемые коллекции. «Мутации» этих коллекций приводят к тому, что возвращается совершенно новая коллекция, состоящая из измененного состояния, оставляя исходную коллекцию неизменной.
person
fourpastmidnight
schedule
05.09.2013
IReadOnlyDictionary<TKey, TValue>
не наследуется отIDictionary<TKey, TValue>
. Поэтому, если OP хочет использовать один и тот же метод расширения для обоих типов объектов, ему нужно написать метод, используя тип, от которого наследуются оба объекта, в данном случаеIEnumerable<KeyValuePair<TKey, TValue>>
. - person fourpastmidnight   schedule 05.09.2013IDictionry
. - person user1067514   schedule 05.09.2013