在C#中更改结构的属性值

时间:2014-08-06 23:29:34

标签: c# struct immutability setter

我正在读一本书,发现结构实际上是不可变的对象。但他们有吸气剂和制定者。我想知道结构的属性是否可以在创建后更改。

public struct Test 
{
    public string str {get; set; }
    public int int1 {get; set; }
}

' str'的值是否可以和' int1'一旦他们被分配了价值,就会被改变吗?

4 个答案:

答案 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本身并不是不可变的。

但它被认为是一种不可改变的好设计。

来自Struct Design

  

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不是。