Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you have default parameters on a readonly struct in c#?

Tags:

c#

.net

It appears that default parameters do not work on a readonly struct in c#. Am I misunderstanding something?

   public readonly struct ReadonlyStruct
   {
      public ReadonlyStruct(int p1 = 1, byte p2 = 2, bool p3 = true)
      {
         P1 = p1;
         P2 = p2;
         P3 = p3;
      }

      public int P1 { get; }
      public byte P2 { get; }
      public bool P3 { get; }
   }

Instantiating an instance of this struct using var test = new ReadonlyStruct(); does not appear to honor the default values. What am I doing wrong?

like image 467
AlexUT Avatar asked Jun 23 '20 05:06

AlexUT


People also ask

What is a readonly struct?

The readonly keyword is a C# modifier used to limit access to all the data members of a struct. If the readonly modifier is used in the declaration of a struct, then: The members of the struct are read-only. None of the members can have setters. A parameterized constructor is used to initialize the data members.

What is the default value of struct in C#?

For variables of class types and other reference types, this default value is null . However, since structs are value types that cannot be null , the default value of a struct is the value produced by setting all value type fields to their default value and all reference type fields to null .

Can class inherit from struct C#?

It is not possible to inherit from a struct and a struct can't derive from any class. Similar to other types in . NET, struct is also derived from the class System.

What does readonly do in C#?

The readonly keyword can be used to define a variable or an object as readable only. This means that the variable or object can be assigned a value at the class scope or in a constructor only. You cannot change the value or reassign a value to a readonly variable or object in any other method except the constructor.


Video Answer


1 Answers

Counter-intuitively you can't have all default parameters or an explicit parameterless constructor on a struct, this is not limited to readonly struct.

Unlike a class, a struct is value-type and is not required to have a constructor, so in your case you aren't providing any parameters at all, hence the constructor never gets called.

As noted in the documentation

Limitations with the design of a structure type

When you design a structure type, you have the same capabilities as with a class type, with the following exceptions:

You can't declare a parameterless constructor. Every structure type already provides an implicit parameterless constructor that produces the default value of the type.

When you don't supply parameters, the generated IL will call

OpCodes.Initobj Field

Initializes each field of the value type at a specified address to a null reference or a 0 of the appropriate primitive type.

Furthermore

Unlike Newobj, initobj does not call the constructor method. Initobj is intended for initializing value types, while newobj is used to allocate and initialize objects.

In contrast, in the following case it will. Defaults will be initalized the way you expect.

var asd = new ReadonlyStruct(2);

The following generated IL will be

newobj instance void ReadonlyStruct::.ctor(int32, uint8, bool)

OpCodes.Newobj Field

The newobj instruction allocates a new instance of the class associated with ctor and initializes all the fields in the new instance to 0 (of the proper type) or null references as appropriate. It then calls the constructor ctor with the given arguments along with the newly created instance. After the constructor has been called, the now initialized object reference (type O) is pushed on the stack.

In short, you may need to rethink your problem or use a static create method.

like image 167
TheGeneral Avatar answered Oct 18 '22 13:10

TheGeneral