我正在读一本书,发现结构实际上是不可变的对象。但他们有吸气剂和制定者。我想知道结构的属性是否可以在创建后更改。
public struct Test
{
public string str {get; set; }
public int int1 {get; set; }
}
' str'的值是否可以和' int1'一旦他们被分配了价值,就会被改变吗?
答案 0 :(得分:6)
结构可以是可变的也可以是不可变的,但是根据很多人的说法,它们 应该是不可变的。
您的示例是一个可变结构。
使用示例:
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;
}
}
答案 1 :(得分:4)
'str'和'int1'的值一旦被分配了值就可以改变吗?
是的,struct
的属性可以更改。 struct
本身并不是不可变的。
但它被认为是一种不可改变的好设计。
X不要定义可变值类型。
可变值类型有几个问题。例如,当属性getter返回值类型时,调用者会收到一个副本。由于副本是隐式创建的,因此开发人员可能不会意识到他们正在改变副本,而不是原始值。此外,某些语言(特别是动态语言)在使用可变值类型时遇到问题,因为即使局部变量在解除引用时也会导致复制。
答案 2 :(得分:2)
struct
不是自动不可变的,但由于某些问题,强烈建议您自己使它们不可变。您可能会想到一个类似的问题,如果结构本身作为属性进行访问,则无法更改结构的属性(建议使其成为不可变的原因之一)。使用{{1}例子:
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;
}
}
的实例,您可以阅读其属性,但除了创建新实例外,您无法更改其属性。
答案 3 :(得分:1)
绝对可以将新实例值重新分配给结构体。不可变性意味着当您认为您正在更改该值时,将在内存中创建一个新实例,并将之前的副本用于垃圾回收。
请注意,结构体整体上是不可变的。反过来,结构字段可以是原子可变的或不可变的。对于您的示例,字符串字段是不可变的,int不是。