60

I can not understand why the constructor is executed with the parameter Double[]?

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            D myD = new D(null);
            Console.ReadLine();           
        }

    }

    public class D
    {
        public D(object o)
        {
            Console.WriteLine("Object");
        }
        public D(double[] array)
        {
            Console.WriteLine("Array");
        }
        public D(int i)
        {
            Console.WriteLine("Int");
        }
    }
}

I think because the first constructor takes a parameter of reference type. The first constructor with a reference parameter because null is the default value for reference types.

But i don't understand why not object, it's also a reference type.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
Amazing User
  • 3,473
  • 10
  • 36
  • 75
  • 12
    You are asking for trouble here. If you are going to use overloads, the including as general a type as object is going to lead to pain at some point – David Heffernan Feb 09 '14 at 20:58
  • 1
    @DavidHeffernan IDK. For the most part I think which method gets called is rather intuitive. The object one only gets called if nothing else can be called. Intuitively this makes sense because the contrary would be nonsense – Cruncher Feb 10 '14 at 21:30
  • 2
    This is a great interview question! :) – Rob H Feb 11 '14 at 18:14
  • and if you add another constructor with other reference type you will this error "The call is ambiguous" – Alaa Jabre Feb 12 '14 at 03:21
  • Just follow some good practices and you will never have such a problem. In constructor you should pass dependencies a created object can't live without. So passing null is not the best practice (and not only in constructor). – Pavel Hodek Mar 02 '14 at 08:41

3 Answers3

90

But I can not understand why no object? It's also a reference type?

Yes, both double[] and object are reference types, so null is implicitly convertible to both of them. However, member overloading generally favours more specific types, so the double[] constructor is used. See section 7.5.3 of the C# specification for more details (and boy are there a lot of details).

In particular, from section 7.5.3.5:

Given two different types T1 and T2, T1 is a better conversion target than T2 if at least one of the following holds:

  • An implicit conversion from T1 to T2 exists, and no implicit conversion from T2 to T1 exists

That's the case here, where T1 is double[] and T2 is object. There's an implicit conversion from double[] to object, but no implicit conversion from object to double[], so double[] is a better conversion target than object.

If you want force the use of the object constructor, just cast:

D myD = new D((object) null);
Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • isn't `double[]` an `object` ? – Khaled.K Feb 12 '14 at 08:52
  • 3
    @KhaledAKhunaifer: Yes, so if the overload taking `double[]` *didn't* exist, it would call the overload taking `object` - but because the overload taking `double[]` is more specific than the overload taking `object`, that's the one that is picked. – Jon Skeet Feb 12 '14 at 09:00
19

Basically, double[] is an object, but all objects are not double[]s. As double[]'s the more specific option, the compiler chooses it, as the most specific one.

It'sNotALie.
  • 22,289
  • 12
  • 68
  • 103
2

Consider this:

double[] d = new double[] {};
Console.WriteLine(d is object);//output is True

double[] d is an object.

So consider this:

object z = new object[] {};
Console.WriteLine(z is double[]);//output is False

object[] z are not double[]. There is no implicit conversion from object to double[].

Satyam
  • 9
  • 1
  • 7
  • 2
    Whilst these are true observations, this answer on its own does not answer the question of why `new D(null)` prefers the constructor it does. – doppelgreener Feb 10 '14 at 07:44