Automatically implemented property in struct can not be assigned - c#

I have a next code:
struct T
{
public T(int u)
{
this.U = 10; //Errors are here
}
public int U { get; private set; }
}
C# compiler give me a pair of errors in stated line:
1) Backing field for automatically implemented property 'TestConsoleApp.Program.T.U' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
2) The 'this' object cannot be used before all of its fields are assigned to
What I do wrong? Help me understand.

From the C# Specification:
10.7.3 Automatically implemented properties
When a property is specified as an automatically implemented property,
a hidden backing field is automatically available for the property,
and the accessors are implemented to read from and write to that
backing field.
[Deleted]
Because the backing field is inaccessible, it can be read and written
only through the property accessors, even within the containing type.
[Deleted]
This restriction also means that definite assignment of struct types
with auto-implemented properties can only be achieved using the
standard constructor of the struct, since assigning to the property
itself requires the struct to be definitely assigned. This means that
user-defined constructors must call the default constructor.
So you need this:
struct T
{
public T(int u)
: this()
{
this.U = u;
}
public int U { get; private set; }
}

Well, for a start you're creating a mutable struct - that's almost always a really bad idea. Mutable structs can sometimes behave in ways you don't expect. Okay, it's only privately mutable, but the fact that you've written code to mutate it is a bad sign.
The reason for the second error is that you can't use any properties or methods of the struct until all fields have been assigned, so you need to chain to the implicit parameterless constructor:
public T(int u) : this()
{
this.U = 10;
}
The compiler requires that any constructor leaves all the fields definitely assigned (which is why you were getting the first error before; the compiler doesn't "know" that the property assigns the field a value) - by chaining to this(), you're making sure that by the time you get to your constructor body, all the fields are already definitely assigned, and you don't need to worry about it any more.
However, unless you actually want to allow mutation, I suggest you just make it a genuinely read-only property:
struct T
{
private readonly int u;
public T(int u)
{
this.u = 10;
}
public int U { get { return u; } }
}
Now it's more obvious that you don't want to mutate it even within the struct itself.

Add a call to the default constructor:
public T(int u) : this()
{
this.U = 10;
}

you have to use the default constructor here:
struct T
{
public int U { get; private set; }
public T(int u) : this()
{
U = 10;
}
}

From C# 6 this is not an issue anymore and it compiles correctly. Look here

Related

Why do I need to call the default constructor for `struct` with auto properties [duplicate]

I have a next code:
struct T
{
public T(int u)
{
this.U = 10; //Errors are here
}
public int U { get; private set; }
}
C# compiler give me a pair of errors in stated line:
1) Backing field for automatically implemented property 'TestConsoleApp.Program.T.U' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
2) The 'this' object cannot be used before all of its fields are assigned to
What I do wrong? Help me understand.
From the C# Specification:
10.7.3 Automatically implemented properties
When a property is specified as an automatically implemented property,
a hidden backing field is automatically available for the property,
and the accessors are implemented to read from and write to that
backing field.
[Deleted]
Because the backing field is inaccessible, it can be read and written
only through the property accessors, even within the containing type.
[Deleted]
This restriction also means that definite assignment of struct types
with auto-implemented properties can only be achieved using the
standard constructor of the struct, since assigning to the property
itself requires the struct to be definitely assigned. This means that
user-defined constructors must call the default constructor.
So you need this:
struct T
{
public T(int u)
: this()
{
this.U = u;
}
public int U { get; private set; }
}
Well, for a start you're creating a mutable struct - that's almost always a really bad idea. Mutable structs can sometimes behave in ways you don't expect. Okay, it's only privately mutable, but the fact that you've written code to mutate it is a bad sign.
The reason for the second error is that you can't use any properties or methods of the struct until all fields have been assigned, so you need to chain to the implicit parameterless constructor:
public T(int u) : this()
{
this.U = 10;
}
The compiler requires that any constructor leaves all the fields definitely assigned (which is why you were getting the first error before; the compiler doesn't "know" that the property assigns the field a value) - by chaining to this(), you're making sure that by the time you get to your constructor body, all the fields are already definitely assigned, and you don't need to worry about it any more.
However, unless you actually want to allow mutation, I suggest you just make it a genuinely read-only property:
struct T
{
private readonly int u;
public T(int u)
{
this.u = 10;
}
public int U { get { return u; } }
}
Now it's more obvious that you don't want to mutate it even within the struct itself.
Add a call to the default constructor:
public T(int u) : this()
{
this.U = 10;
}
you have to use the default constructor here:
struct T
{
public int U { get; private set; }
public T(int u) : this()
{
U = 10;
}
}
From C# 6 this is not an issue anymore and it compiles correctly. Look here

Struct with auto-implemented properties and constructor initializer

Recently a compiler warning and (very useful) hint prompted me to write the code below.
I had no idea you could do this, but it is perfectly legal, and also convenient in that I can declare a managed struct with public properties similar to public fields of an unmanaged struct, and also initialize it with an object instead of having to pass all the fields as parameters.
What confuses me is that this appears to call the explicit parameterless constructor, which would of course be illegal for this struct.
What's going on here, and has this syntax always been supported?
internal struct IconEntry
{
public byte Width { get; set; }
public byte Height { get; set; }
public byte ColorCount { get; set; }
public byte Reserved { get; set; }
public short Planes { get; set; }
public short BitCount { get; set; }
public int BytesInRes { get; set; }
public int ImageOffset { get; set; }
public IconEntry(BinaryReader reader)
: this()
{
Width = reader.ReadByte();
Height = reader.ReadByte();
ColorCount = reader.ReadByte();
Reserved = reader.ReadByte();
Planes = reader.ReadInt16();
BitCount = reader.ReadInt16();
BytesInRes = reader.ReadInt32();
ImageOffset = reader.ReadInt32();
}
}
A struct always has a public parameterless constructor which can't be overriden: http://msdn.microsoft.com/en-us/library/aa288208%28v=vs.71%29.aspx
This means that a user still would be able to create an instance of this struct that is not initialized according to your logic but with default values for all properties:
var s = new IconEntry();
All structs have a parameterless constructor - it's just implicit (e.g. it always exists with a default routine - one that sets all values to 0) - you just can't have an explicit one (e.g. one that you define yourself in code).
Is there any reason you're exposing properties rather than fields for your struct? If the semantics of your data type imply that
The entire state of an instance will be fully defined by the values exposed by some public members, such that two instances for whom all those report or contain identical values will be considered identical.
Instances of the struct with any combination of values for the aforementioned members may be created easily, given the desired values in question.
that sounds like a perfect fit for a PODS (Plain Old Data Struct). Exposed fields are more efficient and less quirky than struct properties. Given that all struct types always expose all fields for mutation or capture by struct assignment, the encapsulation offered by struct properties is of extremely limited value.
The way you have your constructor written, your struct will have all fields set to all-bits-zero, and then be passed repeatedly to methods which will update one field at a time with the desired value. The fact that the struct is specified as initialized to all-bits-zero by the this will make the compiler happy, but using many individual properties to set up fields piecemeal is inefficient.
Incidentally, even better than a constructor in many cases would be a static method which simply takes your struct as a ref parameter. In many cases, using a constructor with a struct will result in an unnecessary copy operation which could be avoided by using a static method with a ref parameter.
Since structs are value types, it's data members should be initialized if you are explicitly invoke the constructor. And mention "this()" to intimate compiler to complete the assignment of auto implemented properties if anything you mentioned.
struct Student
{
string _sname;
public int ID
{
get; set;
}
internal Student(string sname):this()
{
_sname = sname;
}
internal void PrintDetails()
{
Console.WriteLine("ID : {0} Name: {1}", ID, _sname);
}
}
Main method:
class Program
{
static void Main()
{
Student st = new Student("John")
{
ID=101
};
st.PrintDetails();
}
}
Output:
ID : 101 Name: John
If you are not mention "this()", compiler forcefully ask you to complete the full assignment of ID property.
If you are not explicitly invoke the constructor, compiler implicitly set default values for the struct data members.

can we access properties from constructor

I am working on a CSharp code where in constructor i need to access properties of that class. Logically it looks troublesome to me since i will be accessing properties of the object that hasn't is still under construction.
Its an old code using c# version 4.0 and i am kind of refactoring it so that's why can't redesign everything from scratch.
Thanks
class employee
{
employee()
{
int square = count * count;
}
private int count {get;set;}
}
There is nothing wrong with that, except that count will always be 0.
There is (almost) no such thing as a "partially-constructed" object in .Net, except for an object that hasn't set all of its state in the constructor.
If you're constructing the class, and none of the properties have been set previously in the constructor and none of the properties are static and set elsewhere, the values will be default or null, so there's no point getting what they contain. Otherwise, the constructor is the perfect place to set your properties to something.
At construction time you may set a property, but unless it has a static member backing the getting or is a value type, you will get a null value until you set it.
public class WhatClass
{
public WhatClass()
{
int theCount = Count; // This will set theCount to 0 because int is a value type
AProperty = new SomeOtherClass; // This is fine because the setter is totally usable
SomeOtherClass thisProperty = AProperty; // This is completely acceptable because you just gave AProperty a value;
thisProperty = AnotherProperty; // Sets thisProperty to null because you didn't first set the "AnotherProperty" to have a value
}
public int Count { get; set; }
public SomeOtherClass AProperty { get; set; }
public SomeOtherClass AnotherProperty { get; set; }
}
Yes, C# allow this, but sometime better to have private field which is wrapped by public property and in class method work only with field. In your case I would recommend to remove private property and use class field variable instead. If consumers of your class potentially may want to access a property - make it public with a private setter, this kind of autmatic property is an other alternative for privatr field wrapped by a property.

Why does setting the property in the constructor of a struct not work?

I have following code which is not allowed (error below), why?
struct A
{
private int b;
public A(int x)
{
B = x;
}
public int B
{
get { return b; }
set { b=value; }
}
}
I receive the following error:
The 'this' object cannot be used before all of its fields are assigned
to Field 'Test.x' must be fully assigned before control is returned
to the caller
A struct's variables all have to be definitely assigned before you can use any methods or properties. There are two possible fixes here:
1) You can explicitly call the parameterless constructor:
public A(int x) : this()
{
B = x;
}
2) You can use the field instead of the property:
public A(int x)
{
b = x;
}
Of course the second option only works in your current form - you have to use the first option if you want to change your struct to use an automatic property.
However, importantly, you now have a mutable struct. This is almost always a very bad idea. I would strongly urge you to use something like this instead:
struct A
{
private readonly int b;
public A(int x)
{
b = x;
}
public int B { get { return b; } }
}
EDIT: More details of why the original code doesn't work...
From section 11.3.8 of the C# spec:
If the struct instance constructor doesn't specify a constructor initializer, the this variable corresponds to an out parameter of the struct type
Now initially that won't be definitely assigned, which means you can't execute any member function (including property setters) until all the firsts of the struct being constructed have been definitely assigned. The compiler doesn't know or try to take account of the fact that the property setter doesn't try to read from another field. It's all in aid of avoiding reading from fields which haven't been definitely assigned.
Change your constructor to:
public A(int x) :
this()
{
B = x;
}
As to "why", refer to 11.3.8 Constructors and 5.3 Definite assignment.

Get-Set Accessor functionality differs on existence of get-set keyword

I'm currently implementing a poor-man's version of the RSA Algorithm and I wanted the prime numbers d, e, m, and n to be read-only as they will be automatically generated within ithe constructor body. However, I get two different results when I type:
class RSA
{
public RSA()
{
n = 4;
}
private long n { get; private set; }
}
or
class RSA
{
public RSA()
{
n = 4;
}
private long n { get; }
}
Reading the book Accelarated C#, I got the impression that a private set function can be implemented with auto-implemented properties. Turns out I can do it in the constructor itself too, but only for the first version.
Reading the C# 3.0 standard it says:
A property that has both a get accessor and a set accessor is a read-write property, a property that has only a get accessor is a read-only property, and a property that has only a set accessor is a write-only property.
Yet they don't behave equally.
Simple question: Why can I initialize the value in my constructor when I explicitly declare private set, but not if I do it implicitly? What are the differences here?
In the first case the setter is private. This means that you can set the value of this property everywhere from inside this class not only in the constructor. In the second example there's no setter won't be able to set the value. Using readonly field is probably most correct semantically in your case as it will allow you to set its value either in the constructor or directly when declaring the field (if this field shouldn't be visible from outside of this class):
class RSA
{
public RSA()
{
n = 4;
}
private readonly long n;
}
There's no such thing as an implicit autogenerated private setter. If you omit set;, you cannot assign it a value, which will not compile because it can never be assigned.
Additionally, by making n private you cannot access it from outside that class. If that is your intention, there's no point in using a property at all. You can simply declare it as a field: private readonly long n;
If you really want a property with a readonly value, you could use a Property with the explicit backing field IE:
public class RSA {
private readonly long _n;
public long n {
get { return _n; }
}
public RSA()
{
_n = 4;
}
}

Categories

Resources