Используя то, Где указать различные дженерики

Я пишу bijective класс словаря, но я хочу удостовериться, что два универсальных типа не являются тем же типом по двум причинам.

Во-первых, я хотел бы, чтобы это реализовало IDictionary интерфейс в обоих направлениях, но

public class BijectiveDictionary
    : IDictionary, IDictionary

дает мне "'BijectiveDictionary ' не может реализовать обоих 'IDictionary ' и 'IDictionary ', потому что они могут объединить для некоторых замен параметра типа" (который понятен, но нежелателен.)

Во-вторых, я хотел бы записать оптимизированное решение, если оба типа являются тем же.

public class BijectiveDictionary
    : IDictionary where TValue : TKey
{
    // Optimized solution
}

public class BijectiveDictionary
    : IDictionary, IDictionary where TValue : !TKey
{
    // Standard solution
}

Действительно ли это возможно?

В противном случае я могу рассмотреть не реализацию IDictionary, но я не мог гарантировать TValue this[TKey key] и TKey this[TValue key] отличалось бы, который будет неудачен.


Похоже, что проблема вот состоит в том, что, когда два типа являются тем же, особые случаи возникают.

Мое исходное намерение состояло в том, чтобы создать словарь, который отображает точно один ключ точно к одному значению и стих визы, такой это для каждого KeyValuePair(X, Y), a KeyValuePair(Y, X) существует также.

Когда TKey = TValue, затем это может быть упрощено вниз до единственного словаря:

public T this[T key]
{
    get { return this[key]; }
    set
    {
        base.Add(key, value);
        base.Add(value, key);
    }
}

В этом случае Вы не можете Add(2,3); Add(3,4) потому что Add(2,3) карты 3 кому: 2 также, и [3] возвратился бы 2.

Однако решение Jaroslav Jandek предложило использовать второй словарь, чтобы сделать это для случаев когда TKey != TValue. И хотя это работает замечательно на те случаи, (и что я решил реализовать в конце), он не вполне следует за моим исходным намерением когда TKey = TValue, путем разрешения Add(2,3); Add(3,4) отобразить единственный ключ 3 к двум значениям (2 в одном направлении, и 4 в другом), хотя я верю строго говоря, все еще допустимая биективная функция.

9
задан Community 23 May 2017 в 10:24
поделиться

3 ответа

Как насчет этого (другого подхода):

public class BijectiveDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public BijectiveDictionary<TValue, TKey> Reversed { get; protected set; }

    public BijectiveDictionary()
    {
        this.Reversed = new BijectiveDictionary<TValue,TKey>(true);
        this.Reversed.Reversed = this;
    }

    protected BijectiveDictionary(bool reversedWillBeSetFromTheCallingBiji) { }

    protected void AddRaw(TKey key, TValue value)
    {
        base.Add(key, value);
    }

    // Just for demonstration - you should implement the IDictionary interface instead.
    public new void Add(TKey key, TValue value)
    {
        base.Add(key, value);
        this.Reversed.AddRaw(value, key);
    }

    public static explicit operator BijectiveDictionary<TValue, TKey>(BijectiveDictionary<TKey, TValue> biji)
    {
        return biji.Reversed;
    }
}

и в коде:

BijectiveDictionary<int, bool> a = new BijectiveDictionary<int, bool>();

a.Add(5, true);
a.Add(6, false);

Console.WriteLine(a[5]);// => True
Console.WriteLine(((BijectiveDictionary < bool, int>)a)[true]);// => 5
//or
Console.WriteLine(a.Reversed[true]);// => 5
3
ответ дан 4 December 2019 в 23:38
поделиться

Короче говоря, нет. Что касается оптимизации, то одним из вариантов может быть стратегия, основанная на статическом инициализаторе, который выбирает подходящую конкретную реализацию для однотипного случая, но иначе; т.е.

public class BijectiveDictionary<TKey, TValue>
    : IDictionary<TKey, TValue>
{
    static readonly ISomeStrategy strategy;
    static BijectiveDictionary() {
        if(typeof(TKey) == typeof(TValue)) {
            strategy = ...
        } else {
            strategy = ...
        }
    }
}

но вы почти наверняка обнаружите, что используете MakeGenericType и рефлексию для создания экземпляра (но после создания он должен быть в порядке - и вы делаете это только один раз).

2
ответ дан 4 December 2019 в 23:38
поделиться

Даже если бы вы могли, каков был бы вывод этого кода?

var dict = new BijectiveDictionary<int, int>();

dict.Add(2,3);
dict.Add(3,4);

Console.WriteLine(dict[3]); // Do I get 2 or 4?

Может быть, вы можете перестроить свой код другим способом, который не будет двусмысленным?

-1
ответ дан 4 December 2019 в 23:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: