Reputation: 1800
I have this very simple example that I am using to learn structs in C#:
struct ScreenPosition
{
// These are the two private members of the structure
private int x;
private int y;
private int RangeCheckedX(int xPos)
{
if (xPos < 0 || xPos > 1280)
{
throw new ArgumentOutOfRangeException("X");
}
return xPos;
}
private int RangeCheckedY(int yPos)
{
if (yPos < 0 || yPos > 1024)
{
throw new ArgumentOutOfRangeException("Y");
}
return yPos;
}
// Declaring the non-default constructor
public ScreenPosition(int X, int Y)
{
this.x = RangeCheckedX(X); // ERROR HERE
this.y = RangeCheckedY(Y); // ERROR HERE
}
// Declaring the property X - Follows a syntax. See the C# quick reference sheet
public int X
{
get
{
return this.x;
}
set
{
this.x = RangeCheckedX(value);
}
}
// Declaring the property X - Follows a syntax. See the C# quick reference sheet
public int Y
{
get
{
return this.y;
}
set
{
this.y = RangeCheckedY(value);
}
}
}
I am getting this error at the "ERROR HERE" comment lines:
The 'this' object cannot be used before all of its fields are assigned to
Is it illegal to call a structure method in the non-default constructor to assign values to the structure members?
Upvotes: 3
Views: 2182
Reputation: 6157
You can make those methods static and it will work, but you cannot call a non-static method until all the fields have been assigned.
Upvotes: 6
Reputation: 59463
You could set each of the fields to zero before validating the inputs. This makes some sense because the default constructer will set them to zero anyway, so that's a case that has to be handled in your program anyway. Once the values are set, you can call whatever methods you want, even in the constructor.
But the correct solution is what everyone else is saying: make the range checks static methods. In fact, in this case they are pure functions (no side effects and operating only on the parameters rather than static or instance fields). Pure functions can always be static. And static pure functions are chocolate-covered-awesome from the perspectives of debugging, multi-threading, performance, etc.
Upvotes: 1
Reputation: 1500495
GBegen has the right idea - make the range check methods static.
Not only will this fix the problem, but it'll make the code clearer, too: the methods don't rely on the state of the structure at all, and they're not acting polymorphically, so they shouldn't be instance methods.
Upvotes: 2
Reputation: 3358
It is not allowed to call methods on structs until all fields (properties) are populated.
I know its a hack but this would work.
struct ScreenPosition
{
// These are the two private members of the structure
private int x;
private int y;
private int RangeCheckedX(int xPos)
{
if (xPos < 0 || xPos > 1280)
{
throw new ArgumentOutOfRangeException("X");
}
return xPos;
}
private int RangeCheckedY(int yPos)
{
if (yPos < 0 || yPos > 1024)
{
throw new ArgumentOutOfRangeException("Y");
}
return yPos;
}
// Declaring the non-default constructor
public ScreenPosition(int X, int Y)
{
this.x = X;
this.y = Y;
this.x = RangeCheckedX(X);
this.y = RangeCheckedY(Y);
}
// Declaring the property X - Follows a syntax. See the C# quick reference sheet
public int X
{
get
{
return this.x;
}
set
{
this.x = RangeCheckedX(value);
}
}
// Declaring the property X - Follows a syntax. See the C# quick reference sheet
public int Y
{
get
{
return this.y;
}
set
{
this.y = RangeCheckedY(value);
}
}
}
Upvotes: 2