I was reading a book and found out that structs are actually immutable objects. But they have getters and setters. I was wondering if a property of structs can be changed after it has been created.
public struct Test
{
public string str {get; set; }
public int int1 {get; set; }
}
Can the values of 'str' and 'int1' be changed once they have been assigned a value?
Structs can be either mutable or immutable, but they should be immutable according to many people.
Your example is a mutable struct.
Example of use:
var t = new Test();
// t.str is null, and t.int1 is 0
t.str = "changed!"; // OK
var t2 = t;
t2.int1 = 42;
// t.int1 is still 0
var li = new List<Test> { t, t2, };
t.int1 = 666; // OK, but copy in li is unaffected
li[0].int1 = 911; // compile-time error, not a variable
var t3 = t2;
bool checkA = (t3 == t2); // compile-time error, you did not overload operator ==
bool checkB = t3.Equals(t2); // OK, true, ValueType class overrides Equals for you
bool checkC = t2.Equals(t); // OK, false
bool checkD = object.ReferenceEquals(t, t); // false, two distinct boxes
// same as (object)t==(object)t
By request, here is one way to make that struct
immutable:
public struct Test
{
public string str { get; private set; }
public int int1 { get; private set; }
public Test(string str, int int1) : this()
{
this.str = str;
this.int1 = int1;
}
}
// if you introduce methods (other than constructors) that use the private setters,
// the struct will no longer be immutable
and here is another one:
public struct Test
{
readonly string m_str;
readonly int m_int1;
public string str { get { return m_str; } }
public int int1 { get { return m_int1; } }
public Test(string str, int int1)
{
m_str = str;
m_int1 = int1;
}
}
Update:
Starting from 2015 (C# 6.0), you can write the latter as:
public struct Test
{
public string str { get; }
public int int1 { get; }
public Test(string str, int int1)
{
this.str = str;
this.int1 = int1;
}
}
In later versions there are many more possibilities. I shall only mention that you can write (since 2021 (C# 10)):
public readonly record struct Test(string str, int int1)
{
}
The word record
now means that the type automatically overrides or overloads stuff like Equals
, GetHashCode
, operator ==
, ToString
, Deconstruct
, etc. And the constructor is now a primary constructor.