在c#中更改结构体的属性值
本文关键字:属性 结构体 | 更新日期: 2023-09-27 18:16:47
我读了一本书,发现结构体实际上是不可变对象。但是它们有getter和setter。我想知道结构体的属性是否可以在创建后更改。
public struct Test
{
public string str {get; set; }
public int int1 {get; set; }
}
'str'和'int1'的值一旦被赋值就可以改变吗?
结构可以是可变的也可以是不可变的,但是根据很多人的看法,它们应该是不可变的。
你的例子是一个可变结构体。
使用示例:
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
根据请求,这里有一种方法使struct
不可变:
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
还有一个
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;
}
}
'str'和'int1'的值一旦被赋值就可以改变吗?
是的,struct
的性质可以改变。struct
本身不是不可变的
但是使它们不可改变被认为是一个好的设计。
From Struct Design:
X不要定义可变值类型。
可变值类型有几个问题。例如,当属性getter返回值类型时,调用者将收到一个副本。因为副本是隐式创建的,所以开发人员可能不会意识到他们正在改变副本,而不是原始值。此外,一些语言(尤其是动态语言)在使用可变值类型时也存在问题,因为即使是局部变量,在解引用时也会导致生成副本。
struct
s不是自动不可变的,但是由于某些问题,强烈建议您自己使它们不可变。您可能会想到类似的问题,如果结构本身作为属性被访问,则无法更改结构的属性(这是建议将其设置为不可变的原因之一)。使用Test
示例:
public struct Test {
public string str { get; set; }
public int int1 { get; set; }
}
// This works:
Test value = new Test();
value.str = "asdf";
value.int1 = 5;
// But this does NOT work.
Test TestProperty { get; set; }
TestProperty.str = "asdf";
TestProperty.int1 = 5;
第二部分不起作用的原因是,你只通过说TestProperty
来获得一个值副本,然后你设置了副本的属性值,而不是对象中的值。
要使你的结构不可变,你可以这样做:
public struct Test {
readonly string mStr;
readonly int mInt1;
public string str { get { return mStr; } }
public int int1 { get { return mInt1; } }
public Test(string pStr, int pInt1) {
mStr = pStr;
mInt1 = pInt1;
}
}
你可以创建Test
的实例,你可以读取它们的属性,但是你不能改变它们的属性,除非创建一个新的实例
可以明确地将新的实例值重新赋值给结构体。不变性意味着当你认为你在改变值时,在内存中创建一个新的实例,并且上一个副本将被垃圾收集。
注意,结构体作为一个整体是不可变的。反过来,结构字段可以是可变的,也可以是不可变的。对于您的示例,字符串字段是不可变的,而int不是。