2

I'm new to C#, just a question on default constructor and automatic properties. Based on a question on stackoverflow: How can I set the value of auto property backing fields in a struct constructor?

so we have the following struct

public struct SomeStruct
{
   public SomeStruct(String stringProperty, Int32 intProperty)
   {
      this.StringProperty = stringProperty;
      this.IntProperty = intProperty;
   }
   public String StringProperty { get; set; }
   public Int32 IntProperty { get; set; }
}

but how come it compiles fine to me without calling the default constructor by :this()? Another question is why does the same rule not apply to classes? can you have an automatic property without a default constructor?

Avi Meltser
  • 409
  • 4
  • 11
  • 3
    Structs **always** have a default constructor. – Panagiotis Kanavos Jun 03 '19 at 07:48
  • 1
    I might be wrong, but IIRC there were older versions of C# where it *wouldn't* compile unless you added `: this()`. But... since assigning to an auto-prop clearly does assign to the field, IIRC it now lets you. Trying to find when/if this changed. Citation - here's a blog talking about this where it **doesn't** work: https://techiesimon.com/2014/01/16/autoproperties-structs-and-constructors-c-wishes-part-3/ - edit, it was C# 6 - https://stackoverflow.com/a/420441/23354 – Marc Gravell Jun 03 '19 at 07:49
  • What are you trying to do? Prevent the caller from creating invalid values? Or preventing the creation of default values? Structs are value types so they always have a non-null default value and default constructor. Check [Using Structs](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-structs) in the C# Programming Guide – Panagiotis Kanavos Jun 03 '19 at 07:54
  • @Panagiotis Kanavos can you check the original question in my post to see why the original author did receive a compile error –  Jun 03 '19 at 07:55
  • 1
    as a side note: mutable structs are a terrible idea; you would be **much** better off with `public readonly struct SomeStruct { public string StringProperty {get;} public int Int32Property {get;} public SomeStruct(string stringProperty, int int32Property) { StringProperty = stringProperty; Int32Property = int32Property; }}` – Marc Gravell Jun 03 '19 at 07:55
  • @slowjams post the relevant information in *your* question. That's a 10 year old question anyway, that refers to a different problem that only occured back then. It's not about the lack of a default constructor. It's about how it was called bakc then. That's not what you asked in your question though - you asked why this code complies : Because it's valid code – Panagiotis Kanavos Jun 03 '19 at 07:58

1 Answers1

4

Ultimately, structs have strict rules on definite assignment before they can be touched as an entire value (necessary for this access); before C# 6, the compiler didn't consider auto-properties in constructors as part of definite assignment, so access to call the property setter was considered invalid. Since C# 6, it does (consider auto-properties as part of definite assignment in struct constructors), so the code as shown is now valid.

Because it is valid (with any recent compiler, even if you set the language level earlier than C# 6), it compiles.

Note, however, that this only applies inside constructors. The following remains invalid (although it would work with naked fields):

SomeStruct x;
x.StringProperty = "abc"; // CS0165 Use of unassigned local variable x
x.IntProperty = 123;
SomeMethod(x);
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900