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?
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.
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 .
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With