Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# complex type initializer compiles without new keyword

Tags:

c#

I was recently working on some code, that has changed from using decimal to use a complex type that has the decimal number and a type to represent a fraction. I had to update some tests, and while typing I forgot to add the new keyword. The code compiled but the test kept failing, throwing a NullReferenceException. There I realized the missing new and that the property was not initialized. Has anybody an idea why this happening? I could not find anything in the C# lang specification that would explain this.

Here is the code sample:

public class Fraction 
{
    public int Numerator { get; set; }
    public int Denominator { get; set; }
}

public class MyDecimal
{
    public decimal? Decimal { get; set; }     
    public Fraction Fractional { get; set; }
}

public class ClassA 
{
    public MyDecimal Value { get; set; }
}

//...

var instance = new ClassA
{
     Value = // new MyDecimal is missing here
     {
         Decimal = 2.0m,
         Fractional = new Fraction 
         { 
               Numerator = 3,   
               Denominator = 4 
         }
     }
}

Please note that I'm using C# 6 and VS 2015, but I get the same result also in LINQPad.

If somebody could explain this (I'm looking in your direction Jon Skeet :) ) I would be glad.

like image 785
Slaven Vukovic Avatar asked Mar 06 '17 08:03

Slaven Vukovic


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr. Stroustroupe.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


1 Answers

The C# Specification 5.0 defines object initializer as (7.6.10.2 Object initializers):

An object initializer specifies values for zero or more fields or properties of an object.

object-initializer:
{   member-initializer-listopt   }
{   member-initializer-list   ,   }

And after the detailed explanation there is an example given which is very similar to your code:

If Rectangle’s constructor allocates the two embedded Point instances

public class Rectangle
{
  Point p1 = new Point();
  Point p2 = new Point();
  public Point P1 { get { return p1; } }
  public Point P2 { get { return p2; } }
}

the following construct can be used to initialize the embedded Point instances instead of assigning new instances:

Rectangle r = new Rectangle {
  P1 = { X = 0, Y = 1 },
  P2 = { X = 2, Y = 3 }
};

which has the same effect as

Rectangle __r = new Rectangle();
__r.P1.X = 0;
__r.P1.Y = 1;
__r.P2.X = 2;
__r.P2.Y = 3;
Rectangle r = __r;

But there is only one difference, the Point instances here are initialized inside of the Rectangle class which occurs in the constructor of Rectangle.

So the syntax is valid by the specification, but you need to make sure Value is initialized before using the object initializer to initialize its properties in order to avoid NRE.

like image 190
Selman Genç Avatar answered Oct 27 '22 16:10

Selman Genç