Help please understand why I have the following error:

An unhandled exception of type 'System.StackOverflowException' occurred in ConsoleApplication2.exe "

in class Field, in a setter of property X?

class Game { static void StartGame() { Console.WriteLine("Введите спавн Х игрока"); int Player_X = Convert.ToInt32((Console.ReadLine())); Console.WriteLine("Введите спавн Y игрока"); int Player_Y = Convert.ToInt32((Console.ReadLine())); Console.Clear(); Bomb[] Bombs = new Bomb[5]; for (int i = 0; i < Bombs.Length; i++) { Random r = new Random(); Bombs[i] = new Bomb(r.Next(1, 20), r.Next(1, 20)); } Field field = new Field(20, 20, Bombs, new Player(Player_X, Player_Y, 'd'), 0, 0 ); field.MakeField(); } static void Main(string[] args) { StartGame(); Console.ReadLine(); } } class Bomb { public int X; public int Y; public Bomb(int X, int Y) { this.X = X; this.Y = Y; } } class Field { Bomb[] Bombs { get { return Bombs; } set { for (int i = 0; i < value.Length; i++) { bool acceptable = true; if (!(value[i].X > this.X && value[i].Y > this.Y && value[i].X < this.X + Width && value[i].Y < this.Y + Height)) { acceptable = false; } if (acceptable) Bombs = value; } } } int Height; int Width; Player player; int X { get { return X; } set { if (value >= 0) X = value; } } int Y { get { return Y; } set { if (value >= 0) Y = value; } } public Field(int Height, int Width, Bomb[] Bombs, Player player, int x, int y) { this.X = x; this.Y = y; this.Bombs = Bombs; this.Height = Height; // Y -- start, Y + Height -- end this.Width = Width; // X -- start, X + Width -- end this.player = player; } public void MakeField() { Console.SetCursorPosition(X, Y); for (int i = 1, j = 1; i <= Height; i++) { if (j > 9) j = 1; Console.WriteLine(j); j++; } for (int i = 1, j = 1; i <= Width; i++) { if (j > 9) j = 1; Console.Write(j); j++; } for (int i = 0; i < Bombs.Length; i++) { Console.SetCursorPosition(Bombs[i].X, Bombs[i].Y); Console.Write('B'); } Console.SetCursorPosition(player.X, player.Y); Console.Write('P'); } public void IsOver() { for (int i = 0; i < Bombs.Length; i++) { if (player.X == Bombs[i].X && player.Y == Bombs[i].Y) { Console.SetCursorPosition(Width + 50, Height + 50); Console.WriteLine("You\'ve lost!"); } } } public void PrintPlayer() { Console.SetCursorPosition(player.X, player.Y); Console.WriteLine('Y'); } } class Player_CT : Player { public Player_CT(int x, int y, char d) : base(x, y, d) { } bool DefuseKits; // defuse the bomb with defuse kits - 5 seconds, without - 10 seconds int hp { get { return hp; } set { if (hp > -1 && hp < 101) hp = value; } } // hp range = (0, 100) public void DefuseBomb(Bomb bomb) { if (this.X - bomb.X <= 2 && this.Y - bomb.Y <= 2) // находится в двух точках от бомбы { if (DefuseKits) { System.Threading.Thread.Sleep(5000); bomb = null; // bomb doesnt exist anymore } else { System.Threading.Thread.Sleep(10000); bomb = null; } } } public void TakeDefuseKit(DefuseKit[] defusekits) { for (int i = 0; i < defusekits.Length; i++) { if (this.X - defusekits[i].X <= 2 && this.Y - defusekits[i].Y <= 2) { DefuseKits = true; break; } } } } class DefuseKit { public int X; public int Y; } class Player { public int X; public int Y; public char direct { get { return direct; } set { if (value == 'w') direct = 'u'; else if (value == 'd') direct = 'r'; else if (value == 'a') direct = 'l'; else if (value == 's') direct = 'd'; } } // u - up; d - down; l - left; r - right; WASD - W - up A - left S - down D - right public Player(int x, int y, char d) { this.X = x; this.Y = y; this.direct = d; } public void Move() { //ConsoleKeyInfo a = Console.ReadKey(); //direct = a.KeyChar; int X1 = this.X; int Y1 = this.Y; if (direct == 'u') { this.Y += 1; } else if (direct == 'd') { this.Y -= 1; } else if (direct == 'r') { this.X += 1; } else if (direct == 'l') { this.Y -= 1; } Console.SetCursorPosition(X1, Y1); Console.Write(' '); } } 
  • You have a recursion. int X { get { return X; } set { if (value >= 0) X = value; } } int X { get { return X; } set { if (value >= 0) X = value; } } here is the last assignment of a short-circuiting setter. You rely on the auto-property, but writing the expression - you lose this functionality. It will have to announce _x or something similar for this purpose in the hetero and setera. - nick_n_a

1 answer 1

You can't do that

int X {get {return X; } set {if (value> = 0) X = value; }}

because return X; - causes endless recursion of a hetero, and X = value; - also causes endless recursion of seter X (StackOverflowException).

You can do it this way (as an example, it would be clear where the impression is that X can be used freely, only in the case below, it can be used freely)

 int X { get ; set ; } 

This is an "automatic" property advertisement.

To correct a mistake, you need to announce auxiliary x. You can _h what would not "mix". Can x-small. Like so

 int _x; int _y; int X { get { return _x; } set { if (value >= 0) _x = value; } } int Y { get { return _y; } set { if (value >= 0) _y = value; } } 
  • I have already added the answer. - nick_n_a
  • Can you still help me to understand why they all remain null when I create bombs in the StartGame () method of the Game class? on line 94 I got an error An unhandled exception of type 'System.NullReferenceException' occurred in ConsoleApplication4.exe, because the bombs were zero, but I’m adding random integers there. - Mark Pavlovich
  • one
    In the setter condition set: if (acceptable) Bombs = value; and if not acceptable, then Bombs will remain null. - JaponDemon
  • No, my condition is acceptable. - Mark Pavlovich
  • Think about where you made a "logical" error. Those that are acceptable = false are null. - nick_n_a