c# - Disambiguate between two constructors, when two type parameters are the same -
given
class either<a, b> { public either(a x) {} public either(b x) {} }
how disambiguate between 2 constructors when 2 type parameters same?
for example, line:
var e = new either<string, string>("");
fails with:
the call ambiguous between following methods or properties: 'program.either.either(a)' , 'program.either.either(b)'
i know if had given parameters different names (e.g. a a
, b b
instead of x
), use named parameters disambiguate (e.g. new either<string, string>(a: "")
). i'm interested in knowing how solve without changing definition of either
.
edit:
you can write couple of smart constructors, i'm interested in knowing if either
's constructors can called directly without ambiguity. (or if there other "tricks" besides one).
static either<a, b> left<a, b>(a x) { return new either<a, b>(x); } static either<a, b> right<a, b>(b x) { return new either<a, b>(x); } var e1 = left<string, string>(""); var e2 = right<string, string>("");
how disambiguate between 2 constructors when 2 type parameters same?
i'll start not answering question, , finish actual answer lets work around problem.
you don't have because you should never position in first place. design error create generic type can cause member signatures unified in manner. never write class that.
if go , read original c# 2.0 specification you'll see original design have compiler detect generic types in in way possible sort of problem arise, , make class declaration illegal. made published specification, though error; design team realized rule strict because of scenarios like:
class c<t> { public c(t t) { ... } public c(stream s) { ... deserialize stream ... } }
it bizarre class illegal because might c<stream>
, unable disambiguate constructors. instead, rule added overload resolution says if there's choice between (stream)
, (t stream substituted t)
former wins.
thus rule kind of unification illegal scrapped , allowed. very, bad idea make types unify in manner. clr handles poorly in cases, , confusing compiler , developers alike. example, care guess @ output of 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 compile warnings turned on see warning added explaining why really, bad idea.
no, really: how disambiguate between 2 constructors when 2 type parameters 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");
which how class should have been designed in first place. author of either
class should have written
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");
Comments
Post a Comment