-1

I am looking at this in C#:

namespace R3.Geometry
{
    public class Tile
    {
        public Tile()
        {
            Isometry = new Isometry();
            EdgeIncidences = new List<Tile>();
            VertexIndicences = new List<Tile>();
        }

        public Tile( Polygon boundary, Polygon drawn, Geometry geometry )
            : this()
        {
            Boundary = boundary;
            Drawn = drawn;
            Geometry = geometry;
            VertexCircle = boundary.CircumCircle;
        }

        public Isometry Isometry { get; set; }
        public Polygon Boundary { get; set; }
        public Polygon Drawn { get; set; }
        public CircleNE VertexCircle { get; set; }
        public Geometry Geometry { get; set; }

        public Tile Clone()
        {
            Tile newTile = new Tile();
            newTile.Boundary = Boundary.Clone();
            newTile.Drawn = Drawn.Clone();
            newTile.VertexCircle = VertexCircle.Clone();
            newTile.Geometry = Geometry;
            return newTile;
        }

        // ...rest...
    }
}

I am porting this C# to TypeScript (I am new to C#). From my reading/understanding so far, the get; set "properties" don't have any defaults. The : this() on the second constructor means that the second constructor calls into the first before it calls into itself, I'm pretty sure.

My question now is, are there any other defaults that get created or hidden/magical things that might happen? For example, in the Clone function, it calls Boundary.Clone(), but Boundary is never initialized if you just do let tile = new Tile(). Am I correct? Or what am I missing? Won't that cause an error?

If you call a constructor without any arguments, I feel like I might have read somewhere that it calls one of the constructors later in the chain with "default arguments" passed in. Is this the case somehow? That is, does Boundary, Draw, etc. always get created in this situation? What is the general flow if so?

If not, it seems there are two definitions of the Tile here, each with a different set of properties...

I also see this, with 2 constructors, both with : this, what does that mean?

    public struct TilingConfig
    {
        public TilingConfig( int p, int q, int maxTiles ) : this() 
        {
            SetupConfig( p, q, maxTiles );
        }

        public TilingConfig( int p, int q ) : this()
        {
            if( Geometry2D.GetGeometry( p, q ) != Geometry.Spherical )
                throw new System.ArgumentException();

            SetupConfig( p, q, PlatonicSolids.NumFacets( p, q ) );
        }

        // no more constructors.
    }

For complex object classes/structs, if they are defined in parameters, do they get defaulted, like Polygon boundary in the Tile definition?

Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
Lance
  • 75,200
  • 93
  • 289
  • 503

2 Answers2

2

In your code public Tile() sets default values for the properties Isometry, EdgeIncidences, and VertexIndicences, and not for the properties Boundary, Drawn, VertexCircle and Geometry. these will not have any default values. new Tile() calls the default constructor that is public Tile(). Inside the Clone method also you are calling the default constructor only.

using the default constructor will not give any error but you won't be able to use Boundary, Drawn, VertexCircle, and Geometry, as these are not as you have not assigned them any value. and if you try to access you may get null reference exception.

To answer your second question.

<YourConstructor> : this() means that the constructor calls the default constructor before executing its own code. if any default value or initialization should happen that will be done before this constructor code is executed. Its called the Constructor chaining.

Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
  • Hmm, that makes me wonder if the reason there is no error handling for null `Boundary` is because the order the code executes. The `Tile` is always created and then immediately after the boundary is set, but in TypeScript that is not enough to get rid of the "this value could be null" error. Maybe in C# it is different? https://github.com/roice3/Honeycombs/blob/bdc60f6057920d338f4bb59c87041350fefe08cf/code/R3/R3.Core/Geometry/Tiling.cs#L164 – Lance Jan 19 '23 at 04:33
  • @Lance sorry I am not a typescript expert, I would suggest you add a typescript tag to the question in that case for better reach. – Vivek Nuna Jan 19 '23 at 04:38
  • Well, they will have a default value: `null`. Trying to call any method on those will raise an exception. – Etienne de Martel Jan 19 '23 at 04:42
  • 1
    @Lance In C# that validation is not done unless you enable [nullable reference types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-reference-types) for your project. I highly suggest you enable it, it will prevent a lot of headaches. – Etienne de Martel Jan 19 '23 at 04:44
  • Ok, and what about my last example I added, with every constructor calling `: this` without any empty constructor defined? – Lance Jan 19 '23 at 04:44
  • That's an error: there is no default constructor for that type, as defining one means the compiler doesn't generate one for you, so `this()` will refer to a non existing constructor, which does not compile. – Etienne de Martel Jan 19 '23 at 04:47
0

You are on the right track -- but may need to analyze the flow carefully. The use of the : this() keyword here is called "constructor chaining" as discussed here.

As per that answer, it is a shorthand way to say:

Run the specified constructor before the current constructor

And here is another good answer discussing constructor chaining.

In addition, in your second example, you are dealing with a struct, while in your first example you are dealing with a class. This can get confusing as to how default values are handled with respect to the chaining. As per the MS article you linked, structs are value types versus classes which are reference types.

wopr_xl
  • 150
  • 1
  • 9