How to eliminate the ambiguity between two constructors when two type parameters are the same?
To begin with, I will not answer your question, and then I will end it with an actual answer that will allow you to get around this problem.
You do not need, because you should never get into this position in the first place . A design error to create a typical type that can lead to signature signatures being unified in this way. Never write such a class.
If you come back and read the original C # 2.0 specification, you will see that the original design had to have the compiler detect common types in which it was possible in any way to cause such a problem, and to make the class declaration forbidden. This made it into the published specification, although it was a mistake; The development team realized that this rule was too strict due to scenarios such as:
class C<T> { public C(T t) { ... } public C(Stream s) { ... deserialize from the stream ... } }
It would be strange to say that this class is illegal because you can tell C<Stream> and then you cannot unambiguously eliminate the constructors. Instead, a rule was added to allow congestion, which states that if there is a choice between (Stream) and (T where Stream is substituted for T) , then the first wins.
Thus, the rule that this type of association is illegal has been repealed, and now it is allowed. However, a very, very bad idea is to create types that combine in this way. In some cases, the CLR does a poor job of this, and this confuses the compiler and developers. For example, would you like to guess the output of this program?
using System; public interface I1<U> { void M(U i); void M(int i); } public interface I2<U> { void M(int i); void M(U i); } public class C3: I1<int>, I2<int> { void I1<int>.M(int i) { Console.WriteLine("c3 explicit I1 " + i); } void I2<int>.M(int i) { Console.WriteLine("c3 explicit I2 " + i); } public void M(int i) { Console.WriteLine("c3 class " + i); } } public class Test { public static void Main() { C3 c3 = new C3(); I1<int> i1_c3 = c3; I2<int> i2_c3 = c3; i1_c3.M(101); i2_c3.M(102); } }
If you compile this with warnings turned on, you will see a warning that I added explaining why this is a really and really bad idea.
No, really: how to eliminate the ambiguity between two constructors when two type parameters are the same?
Like this:
static Either<A, B> First<A, B>(A a) => new Either<A, B>(a); static Either<A, B> Second<A, B>(B b) => new Either<A, B>(b); ... var ess1 = First<string, string>("hello"); var ess2 = Second<string, string>("goodbye");
how the class should have been designed in the first place . Class author Either should write
class Either<A, B> { private Either(A a) { ... } private Either(B b) { ... } public static Either<A, B> First(A a) => new Either<A, B>(a); public static Either<A, B> Second(B b) => new Either<A, B>(b); ... } ... var ess = Either<string, string>.First("hello");