2

On pg 185/186 of CLR Via C# 4th Edition, it has this code example:

class Program
{
    static void Main(string[] args)
    {
        Rectangle r = new Rectangle();
    }
}

internal struct Point
{
    public Int32 m_x, m_y;
    public Point()
    {
        m_x = m_y = 5;
    }
}

internal sealed class Rectangle
{
    public Point m_topLeft, m_bottomRight;
    public Rectangle()
    {

    }
}

This won't compile because you can't define a parameterless constructor for a struct.

Jeff goes on to say:

C# purposely disallows value types from defining parameterless constructors to remove any confusion a developer might have about when that constructor gets called.

However if you replace struct with class, the code compiles, and when run, the Point constructor doesn't get called, which could be unexpected for people new to programming.

EDIT: Maybe I've understood it incorrectly, but I think Jeff is trying to say that some people may think that if value types were to have a parameterless constructor, it would be called for every instance in Point array = new Point[100];, which is not what would happen. If so, then you've got the same potential confusion with reference types right?

I know Jon Skeet wrote an answer here, however all those points could also be applied to reference types, yet reference types ARE allowed parameterless constructors.

Community
  • 1
  • 1
David Klempfner
  • 8,700
  • 20
  • 73
  • 153
  • But changing from struct to class you don't just allow parameterless constructor! You're changing a value type into a reference type. Null for an uninitialized reference type is a perfectly normal behavior (and no one should be surprised by that). – Adriano Repetti Jul 29 '14 at 12:27
  • 3
    No, the points *can't* all be applied to reference types. If I write `Rectangle[] array = new Rectangle[100];` I have 100 null references. If I write `Point array = new Point[100];` I have 100 `Point` values. – Jon Skeet Jul 29 '14 at 12:27
  • 1
    The arguments Jon makes about value types cannot be applied to reference types. An array of reference types will have `n` null references. An array of value types will have `n` instances, zero'd out. – dcastro Jul 29 '14 at 12:28
  • The point constructor doesn't get called because the two points `m_topLeft` and `m_bottomRight` are not initialised in the sample code. In the constructor for `Rectangle()` you would need to add `m_bottomRight = new Point(); m_topLeft = new Point();` to have the Point constructor execute. – Kevin Hogg Jul 29 '14 at 12:31
  • I've just looked through *The C# Programming Language (Covering C# 4.0), Fourth Edition*, and none of the commentary specifies a reason, beyond the implied (from the main text) guaranteeing field initialisation. – Richard Jul 29 '14 at 12:33

1 Answers1

0

In fact, the fact that Jon's arguments can't be applied to reference types only strengthens his points.

If a reference type's constructor is never called when you initialize an array of reference types (because there's nothing being instantiated), then it would only make sense to keep the behaviour consistent and not call any constructor when you initialize an array of value types.

dcastro
  • 66,540
  • 21
  • 145
  • 155