Is there a clause that I can put along the lines of "where : TypeOf(T1) != TypeOf(T2)"
Вы можете заставить своего конструктора исключить исключение во время выполнения. Но нет возможности предотвратить эту ситуацию на время компиляции.
Any way to make this unambiguous?
Вы должны изменить имена своих методов, чтобы они не сталкивались. Это, безусловно, самая безопасная и простая вещь.
Фактически, IIRC CLR оставляет за собой право не создавать тип, который создает двусмысленность в сигнатурах методов, подобных этому. (Очевидно, что наша реализация на самом деле преуспевает, но вы наступаете на очень тонкий лед, когда вы вытаскиваете такие виды махинаций.)
Выполнение такого рода вещей - действительно очень плохая идея, потому что это может привести вас во всевозможные беда. Вот пример того, как идут дела ужасно неправильно:
http://blogs.msdn.com/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Также обратите внимание, что компилятор будет остановить вас от создания такого типа, что он реализует два интерфейсов, которые могут быть одинаковыми в разработке. Это незаконно:
class C<T, U> : IFoo<T>, IFoo<U> { ... }
потому, что вы могли бы построить C<int, int>
и CLR не будет иметь никакого способа знать, какие методы соответствовали каким слотам интерфейса.
Но я, кажется, несколько отвлекся. Вернемся к теме.
Поскольку вы являетесь создателем этого класса, вы можете переименовать свои методы «Бар», чтобы они были разными при любой возможной конструкции. Предположим, вы упрямо решили не делать этого. Есть ли что-нибудь, что может сделать пользователь вашего несчастного класса, если они хотят сделать Widget<int, int>
? Да, на самом деле, есть, как указывает kvb. Они могут определять методы расширения, которые делают правильную вещь.
public static void BarTheFirst<A, B>(this Widget<A, B> w, A a)
{
w.Bar(a);
}
public static void BarTheFirst<A, B>(this Widget<A, B> w, B b)
{
w.Bar(b);
}
разрешение перегрузки осуществляется во время компиляции и во время компиляции все мы знаем, что первый один называет бар, который принимает «А», а второй один называет бар, который принимает " B». Мы не повторно сделать разрешение перегрузки во время выполнения, так что теперь вы можете сказать
Widget<int, int> w = whatever;
w.BarTheFirst(5);
w.BarTheSecond(10);
и он будет делать правильные вещи.
Мне интересно, что это за реальный случай мира ... – user76035
в реальности это становится и недействительным метод при загрузке – Perpetualcoder
@wwosik: словарь с 2 ключами. –