Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling constructor overload when both overload have same signature

Consider the following class,

class Foo
{
    public Foo(int count)
    {
        /* .. */
    }

    public Foo(int count)
    {
        /* .. */
    }
}

Above code is invalid and won't compile. Now consider the following code,

class Foo<T>
{
    public Foo(int count)
    {
        /* .. */
    }

    public Foo(T t)
    {
        /* .. */
    }
}

static void Main(string[] args)
{
    Foo<int> foo = new Foo<int>(1);
}

Above code is valid and compiles well. It calls Foo(int count).

My question is, if the first one is invalid, how can the second one be valid? I know class Foo<T> is valid because T and int are different types. But when it is used like Foo<int> foo = new Foo<int>(1), T is getting integer type and both constructor will have same signature right? Why don't compiler show error rather than choosing an overload to execute?

like image 768
Navaneeth K N Avatar asked Aug 18 '09 11:08

Navaneeth K N


People also ask

How do you call a constructor overload?

Invoke an Overloaded Constructor using “this” keyword We can call an overloaded constructor from another constructor using this keyword but the constructor must be belong to the same class, because this keyword is pointing the members of same class in which this is used.

Is it possible to overload the constructor?

Constructors can be overloaded in a similar way as function overloading. Overloaded constructors have the same name (name of the class) but the different number of arguments.

Can constructor be overloaded vs overridden?

Neither. Constructors are different from methods. You overload a constructor by writing multiple constructors in the same class, not in inherited classes. And constructors aren't subject to overriding.

What is the difference between constructor overloading and method overloading?

Difference between constructor and method overloading in Java. Constructor is used to initialize an object whereas a method is used to perform certain functions of a class. Constructors are invoked implicitly when an object is created whereas methods are called explicitly by the user.


2 Answers

There is no ambiguity, because the compiler will choose the most specific overload of Foo(...) that matches. Since a method with a generic type parameter is considered less specific than a corresponding non-generic method, Foo(T) is therefore less specific than Foo(int) when T == int. Accordingly, you are invoking the Foo(int) overload.

Your first case (with two Foo(int) definitions) is an error because the compiler will allow only one definition of a method with precisely the same signature, and you have two.

like image 194
John Feminella Avatar answered Sep 16 '22 12:09

John Feminella


Your question was hotly debated when C# 2.0 and the generic type system in the CLR were being designed. So hotly, in fact, that the "bound" C# 2.0 specification published by A-W actually has the wrong rule in it! There are four possibilities:

1) Make it illegal to declare a generic class that could POSSIBLY be ambiguous under SOME construction. (This is what the bound spec incorrectly says is the rule.) So your Foo<T> declaration would be illegal.

2) Make it illegal to construct a generic class in a manner which creates an ambiguity. declaring Foo<T> would be legal, constructing Foo<double> would be legal, but constructing Foo<int> would be illegal.

3) Make it all legal and use overload resolution tricks to work out whether the generic or nongeneric version is better. (This is what C# actually does.)

4) Do something else I haven't thought of.

Rule #1 is a bad idea because it makes some very common and harmless scenarios impossible. Consider for example:

class C<T>
{
  public C(T t) { ... } // construct a C that wraps a T
  public C(Stream state) { ... } // construct a C based on some serialized state from disk
}

You want that to be illegal just because C<Stream> is ambiguous? Yuck. Rule #1 is a bad idea, so we scrapped it.

Unfortunately, it is not as simple as that. IIRC the CLI rules say that an implementation is allowed to reject as illegal constructions that actually do cause signature ambiguities. That is, the CLI rules are something like Rule #2, whereas C# actually implements Rule #3. Which means that there could in theory be legal C# programs that translate into illegal code, which is deeply unfortunate.

For some more thoughts on how these sorts of ambiguities make our lives wretched, here are a couple of articles I wrote on the subject:

http://blogs.msdn.com/ericlippert/archive/2006/04/05/569085.aspx

http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx

like image 36
Eric Lippert Avatar answered Sep 19 '22 12:09

Eric Lippert