Is there a clause that I can put along the lines of "where : TypeOf(T1) != TypeOf(T2)"
Puede hacer que su constructor genere una excepción en el tiempo de ejecución. Pero no hay forma de evitar esta situación en tiempo de compilación.
Any way to make this unambiguous?
Debe cambiar los nombres de sus métodos para que no colisionen. Esa es la forma más segura y fácil de hacer.
De hecho, IIRC la CLR se reserva el derecho de no crear un tipo que produzca una ambigüedad en las firmas de métodos como esa. (Obviamente, nuestra implementación realmente tiene éxito, pero estás pisando hielo muy delgado cuando sacas este tipo de travesuras.)
Hacer este tipo de cosas es una muy, muy mala idea porque te puede llevar a todo tipo de problema. Aquí está un ejemplo de cómo van mal las cosas:
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
También tenga en cuenta que el compilador se le impida la creación de un tipo tal que implementa dos interfaces de que podrían ser idénticos en construcción. Esto es ilegal:
class C<T, U> : IFoo<T>, IFoo<U> { ... }
porque entonces podría construir C<int, int>
y el CLR no tendría forma de saber qué métodos que se correspondían con ranuras de interfaz.
Pero parece que me he desviado un poco. De vuelta al tema.
Como usted es el creador de esta clase, puede optar por cambiar el nombre de sus métodos de "Barra" para que sean diferentes en cualquier construcción posible. Supongamos que obstinadamente eliges no hacerlo. ¿Hay algo que el usuario de su desafortunada clase pueda hacer si quiere hacer Widget<int, int>
? Sí, en realidad, hay, como señala kvb. Pueden definir métodos de extensión que hagan lo correcto.
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);
}
resolución de sobrecarga se realiza en tiempo de compilación, y en tiempo de compilación todo lo que sabemos es que el primero llama a la barra que tiene una "A", y la segunda llama la barra que tiene un " SEGUNDO". No volver a hacer resolución de sobrecarga en tiempo de ejecución, por lo que ahora podemos decir
Widget<int, int> w = whatever;
w.BarTheFirst(5);
w.BarTheSecond(10);
y va a hacer lo correcto.
Me pregunto cuál es el caso del mundo real para que ... – user76035
en realidad se convierta en un método no válido sobre la carga – Perpetualcoder
@wwosik: Un diccionario con 2 teclas. –