Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

New-ing string types

Tags:

c#

From Pro C#

Referring to "New-ing" Intrinsic data types...

All intrinsic data types support what is known as a default constructor. It allows you to create a variable using the new keyword.

[...] Object references (including strings) are set to null.

In C#, strings do not have a public default constructor. My guess is that due to string's immutability, they have a private default constructor. But, the context here is talking about Object references and string's as a whole while using new.

Because one cannot do

String myString = new String();

So,

String a;

referencing string doesn't result in a "default value". Instead, it's a compiler error to access a.

Though

public class StringContainer
{
    public static string myString { get; set; }
}

Results in a legally accessible string (defaulted to null). This doesn't use new. It performs some kind of magical construction.

What is occurring in the StringContainer scenerio? Because there appears to be no new-able default constructor in string, is this an error in the C# book?

like image 830
P.Brian.Mackey Avatar asked Nov 29 '22 03:11

P.Brian.Mackey


1 Answers

All intrinsic data types support what is known as a default constructor. It allows you to create a variable using the new keyword.

There are an impressive number of subtle errors in that statement.

First off, there is no such thing as an "intrinsic" data type; perhaps this term is defined somewhere else in the book?

Second, it would be more accurate to say that all struct types have a public parameterless constructor called the "default" constructor. Some class types also have a public parameterless ctor; if you do not provide any ctor then the C# compiler will automatically generate a public parameterless ctor for you. If you do provide a ctor then the C# compiler will not do this for you.

Third, constructors do not create variables. The author is conflating a bunch of related but different things: the "new" operator, the memory manager, the constructor and the variable, and the created object. Variables are storage locations and are managed by the CLR; they are not created by the "new" operator.

The correct statement is that the "new" operator on a struct causes a variable to be created by the CLR on the temporary storage pool; that variable is then initialized by the memory manager, and then passed to the constructor for more initialization. The value thus created is then copied somewhere else. The "new" operator on a class causes the CLR to create an object on the long-term storage pool, and then pass a reference to that object to the CLR. No "variable" need be involved.

Confusing variables with objects is a very common error; it is valuable to understand the difference.

In C#, strings do not have a public default constructor.

Correct.

My guess is that due to string's immutability, they have a private default constructor.

Good guess, but wrong. There is no private parameterless constructor on string.

[an auto-property or field of type string] results in a legally accessible string (defaulted to null). This doesn't use new. It performs some kind of magical construction.

It does no such thing. A null reference is not a constructed object at all. It's the absence of a constructed object!

You're basically saying that my empty garage contains a "magically constructed" non-existing car. That is an exceedingly weird way to look at an empty garage; an empty garage contains no car at all, not a magically constructed non-existing car.

What is occurring in the StringContainer scenerio?

The containing type contains a compiler-generated field -- a variable -- of type string. Let's suppose the containing type is a struct or class. When the storage for the struct or class is initialized by the memory manager, the memory manager writes a null reference into the storage location associated with the variable.

Finally: I suspect your confusion is because you've gotten the "default constructor" and the "default value of a type" confused. For a struct, they are the same thing:

int x = new int();

and

int x = default(int);

both make an int initialized to zero.

For a class, they do not do the same thing:

Fruit f = new Fruit(); 

makes a new fruit reference and assigns the reference to variable f, whereas:

Fruit f = default(Fruit);

is the same as

Fruit f = null;

No constructor is called.

like image 116
Eric Lippert Avatar answered Dec 06 '22 16:12

Eric Lippert