Elan
Elan

Reputation: 6376

Why can I not alter fields in a struct that is used as a property after instantiation?

I have a struct in C# defined as follows(simplified for demonstration purposes), which I use in interop calls to a native DLL:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct MyStruct
{
    private byte val0;
    private byte val1;
    private byte val2;
    private byte val3;

    public MyStruct(UInt32 id)
    {
        this.val0 = (byte)id;
        id >>= 8;
        this.val1 = (byte)id;
        id >>= 8;
        this.val2 = (byte)id;
        id >>= 8;
        this.val3 = (byte)id;
    }

    public void Clear()
    {
        this.val0 = this.val1 = this.val2 = this.val3 = 0;
    }

    public override string ToString()
    {
        return
            this.val3.ToString("X2") + this.val2.ToString("X2") + "-" +
            this.val1.ToString("X2") + this.val0.ToString("X2");
    }
}

Update: This struct is a property within another class. As follows:

public class MyClass
{
    MyStruct MyStruct { get; set; }
}

When I instantiate the struct with a value and follow this by a call to Clear(), the contents are not cleared. When I step into the Clear() method with the debugger I see each field getting cleared. Yet, once the call to Clear() completes, the original struct instance remains unaltered with its originally instantiated values.

MyClass class1 = new MyClass();
class1.MyStruct = new MyStruct(0x12345678);
System.Diagnostics.Debug.WriteLine("Init: " + class1.MyStruct.ToString());
class1.MyStruct.Clear();
System.Diagnostics.Debug.WriteLine("Clear: " + class1.MyStruct.ToString());

The above results in the following output:

Init: 1234-5678
Clear: 1234-5678

Why is this? Can one clear a struct after it has been instantiated?

Edit: Sample code and results can be seen here: http://ideone.com/6szn9

Edit: Revised question to more accurately reflect the problem being related to the property accessor.

Upvotes: 2

Views: 244

Answers (2)

supercat
supercat

Reputation: 81115

What you are seeing is a significant limitation in the way properties work. If you want to modify a struct that's only accessible as a property and not as a field, you will have to read the struct into a temporary variable, modify it, and store it back. Some would claim this as an argument against mutable structs. I would argue that while the limitation is unfortunate, code like:

  Rectangle tempRect = thing.Bounds;
  tempRect.X += 10;
  thing.Bounds = tempRect;

is clearer and more self-explanatory than it would be if Rectangle were anything other than a mutable struct.

Upvotes: 0

Ben Voigt
Ben Voigt

Reputation: 283614

Doesn't do that for me. http://ideone.com/PDLnt

Does your real code use a property by any chance? A property getter makes a copy when it returns.

Upvotes: 5

Related Questions