Предотвращение неоднозначной ошибки вызова с универсальными типами - PullRequest
3 голосов
/ 14 апреля 2011

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

Мой класс выглядит (частично) так:

public class DoubleDictionary<A,B>
{
    private Dictionary<A, B> _forward;
    private Dictionary<B, A> _backward;

    public A this[B b]
    {
        get { return _backward[b]; }
        set { _backward[b] = value; }
    }

    public B this[A a]
    {
        get { return _forward[a]; }
        set { _forward[a] = value; }
    }
}

В этом примере я использую оператор индексации массива, но почти каждый метод имеет две универсальные версии.Он отлично работает , за исключением в случае, когда A == B.

Если я сделаю

var foo = new DoubleDictionary<int, int>();
int x = foo[3];

Он даже не скомпилируется из-за неоднозначного индексатора.

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

Предположим, у меня действительно есть действительный вариант использования для получения DoubleDictionary<int,int>, и я произвольно выбираю, что индекс массива должен обращаться к прямому словарю.

Решение, к которому я пришел, чтобы обойти все это, состоит в том, чтобы отказаться от гладкого синтаксиса индексации для методов с уникальными именами для каждого направления.Это делает его намного менее волшебным и гораздо менее веселым.

Есть ли способ дать подсказкам компилятора разрешение неоднозначности, не прибегая к методам с уникальными именами?Мне очень нравится идея делать это с перегрузками, и я бы хотел, чтобы это продолжалось.Я бы предпочел сделать это в классе, чтобы вызывающий не беспокоился об этом, но я представляю, что вызывающий должен будет использовать магию отражения, чтобы заставить его работать.

Если это невозможноЯ был бы согласен с ограничением, что A не может быть таким же, как B. Есть ли способ кодифицировать это, чтобы объявление DoubleDictionary<int,int> не компилировалось?Я мог бы выбросить исключение в конструктор, но было бы неплохо, если бы оно было перехвачено во время компиляции.

Ответы [ 3 ]

3 голосов
/ 14 апреля 2011

Ну, если бы два указателя, если бы это было разрешено, были бы монументально плохим дизайном.

Наличие этого словаря:

var foo = new DoubleDictionary<int, int>();
foo.Add(3, 4);
foo.Add(2, 3);

и затем выполнение:

foo[3]

Вы ожидаете получить 2?или 4?и почему?

Лучше проясни API.

2 голосов
/ 14 апреля 2011

Вы всегда можете сохранить индексаторы, но добавить именованные методы в качестве вспомогательного API - возможно, даже с помощью методов расширения, чтобы вы могли ввести их в игру, добавив директиву using ...

0 голосов
/ 14 апреля 2011

Нет никакого способа разрешить неопределенность как есть, учитывая, что это индексатор, который не позволяет указывать аргументы, и что единственный способ связать параметры типа в общих ограничениях - это наследование.

Я думаю, что хорошим компромиссом было бы использование индексатора для прямого просмотра и что-то вроде GetKeyForValue(B value) метода для обратного просмотра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...