Auto properties and structures do not mix?

By clicking on a few small structures while replying to this post , I unexpectedly discovered the following:

The following structure using the int field is completely legal:

struct MyStruct { public MyStruct ( int size ) { this.Size = size; // <-- Legal assignment. } public int Size; } 

However, the following structure using an automatic property does not compile:

 struct MyStruct { public MyStruct ( int size ) { this.Size = size; // <-- Compile-Time Error! } public int Size{get; set;} } 

Error returned: "Object 'this' cannot be used before all its fields have been assigned." I know that this is the standard procedure for struct: the support field for any property must be assigned directly (and not through the accessory of the property set) from the constru constructor.

The solution is to use an explicit support field:

 struct MyStruct { public MyStruct(int size) { _size = size; } private int _size; public int Size { get { return _size; } set { _size = value; } } } 

(Note that VB.NET will not have this problem because in VB.NET all fields are automatically initialized to 0 / null / false on first creation.)

This may seem like an unfortunate limitation when using automatic properties using C # structures. Thinking conceptually, I was wondering if this would be a reasonable place for an exception that allows the calling attribute of a property to be assigned in the structure constructor, at least for an automatic property?

This is a minor issue, almost extreme, but I was wondering what others thought about it ...

+62
c # struct
Jan 07 '09 at 14:14
source share
3 answers

From C # 6 onward: this is no longer a problem




Becore C # 6, you need to call the default constructor for this:

 public MyStruct(int size) : this() { Size = size; } 

The big problem here is that you have a mutable structure. This is never a good idea. I would do this:

 public int Size { get; private set; } 

Not technically unchangeable, but close enough.

In recent versions of C #, you can improve this:

 public int Size { get; } 

Now this can only be assigned in the constructor.

+81
Jan 07 '09 at 14:17
source share

You can fix this by calling the default constructor first:

 struct MyStruct { public MyStruct(int size) : this() { this.Size = size; // <-- now works } public int Size { get; set; } } 
+10
Jan 07 '09 at 14:21
source share

Another obscure issue in this issue is one of the spots in the Tuple temporary class in the Managed Extensibility Framework (via Krzysztof Koลบmic ):

 public struct TempTuple<TFirst, TSecond> { public TempTuple(TFirst first, TSecond second) { this = new TempTuple<TFirst, TSecond>(); // Kung fu! this.First = first; this.Second = second; } public TFirst First { get; private set; } public TSecond Second { get; private set; } 

(Full source code from Codeplex: Tuple.cs )

I also note that the documentation for CS0188 has been updated to add:

If you see this error when trying to initialize a property in the constructor structure, the solution is to change the constructor parameter to specify a background field instead of the property itself. Auto-implemented properties should be avoided in structures because they do not have a support field and therefore cannot be initialized in any way from the constructor.

Therefore, I believe that the official guideline is to use the old-style properties in your structures when you encounter this problem, which is probably less obscure (and more readable) than either of the other two alternatives studied so far.

+7
Feb 11 '09 at 5:50
source share



All Articles