Calling constructor overload when both overload have same signature

前端 未结 4 710
傲寒
傲寒 2020-12-09 16:58

Consider the following class,

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

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


        
相关标签:
4条回答
  • 2020-12-09 17:26

    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

    0 讨论(0)
  • 2020-12-09 17:27

    Eric Lippert blogged about this recently.

    0 讨论(0)
  • 2020-12-09 17:33

    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.

    0 讨论(0)
  • 2020-12-09 17:36

    The fact is that they do not both have the same signature - one is using generics while this other is not.

    With those methods in place you could also call it using a non-int object:

    Foo<string> foo = new Foo<string>("Hello World");
    
    0 讨论(0)
提交回复
热议问题