У меня есть этот очень простой пример, который я использую для изучения структур на С#:
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);
}
}
}
Я получаю эту ошибку на строках комментариев "ОШИБКА ЗДЕСЬ":
Объект 'this' не может использоваться до того, как все его поля будут присвоены
Неправильно ли вызывать метод структуры в конструкторе, отличном от стандартного, для назначения значений членам структуры?
Вы можете сделать эти методы статичными, и они будут работать, но вы не можете вызвать нестатический метод, пока не будут назначены все поля.
GBegen имеет правильную идею - ставьте методы проверки диапазона.
Это не только устранит проблему, но и сделает код более понятным: методы не полагаются на состояние структуры вообще, и они не действуют полиморфно, поэтому они не должны быть методами экземпляра.
Нельзя вызывать методы для структур, пока не будут заполнены все поля (свойства).
Я знаю его взломать, но это сработает.
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);
}
}
}
Вы можете установить каждое из полей в ноль перед проверкой входов. Это имеет смысл, потому что конструктор по умолчанию будет устанавливать их в ноль в любом случае, так что случай, который должен быть обработан в вашей программе, в любом случае. Как только значения установлены, вы можете вызывать любые методы, которые вы хотите, даже в конструкторе.
Но правильное решение - это то, что говорят все остальные: заставляйте диапазон проверять статические методы. Фактически, в этом случае они являются чистыми функциями (без побочных эффектов и работают только по параметрам, а не по статичным или по экземплярам). Чистые функции всегда могут быть статическими. А статические чистые функции покрыты шоколадом - потрясающие с точки зрения отладки, многопоточности, производительности и т.д.