Список, кажется, все еще существует после завершения программы

Я обнаружил довольно странную вещь при кодировании мини-игры Asteroid Destroyer с использованием MonoGame с Visual Studio 2017. В методе LoadContent() я загружаю текстуры для своего космического корабля в список спрайтов, который создается на месте. Затем этот список передается в конструктор Spaceship, чтобы космический корабль получил свои текстуры. Код выглядит следующим образом:

protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            List<Sprite> spaceship1Sprites = new List<Sprite>
            {
                new Sprite(Content, "Spaceship1On"),
                new Sprite(Content, "Spaceship1Off"),
                new Sprite(Content, "Bullet1")
            };

            spaceship1 = new Spaceship(spaceship1Sprites, new Vector2(graphics.GraphicsDevice.DisplayMode.Width / 2, graphics.GraphicsDevice.DisplayMode.Height / 2))
            {
                Controls = new Input(Keys.W, Keys.D, Keys.A, Keys.Space)
            };
        }

Странно то, что если после однократного запуска программы я удаляю строки, в которых определен список Sprite,

            //List<Sprite> spaceship1Sprites = new List<Sprite>
            //{
            //    new Sprite(Content, "Spaceship1On"),
            //    new Sprite(Content, "Spaceship1Off"),
            //    new Sprite(Content, "Bullet1")
            //};

программа все равно будет работать, даже если список не определен где-либо еще в программе, и конструктор Spaceship должен получать несуществующий список в качестве своего первого параметра. Как это все еще может работать?

Это не то, что мешает мне заставить мою программу работать, но я все же хотел бы знать, в чем причина, чтобы я знал немного больше о том, как работает C #.

Изменить: добавление остальной части кода в класс Game1. Класс Spaceship не содержит списка spaceship1Sprites, у него есть три поля для трех спрайтов, которые загружаются в конструктор.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.IO;

namespace Asteroid_Destroyer
{
    public class Game1 : Game
    {
        public static GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        KeyboardState currentKeyboardState, previousKeyboardState;
        bool paused = false;

        Spaceship spaceship1;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            //Change screen resolution
            graphics.PreferredBackBufferWidth = graphics.GraphicsDevice.DisplayMode.Width;
            graphics.PreferredBackBufferHeight = graphics.GraphicsDevice.DisplayMode.Height;
            graphics.IsFullScreen = true;
            graphics.HardwareModeSwitch = false; //fullscreen borderless
            graphics.ApplyChanges();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            List<Sprite> spaceship1Sprites = new List<Sprite>
            {
                new Sprite(Content, "Spaceship1On"),
                new Sprite(Content, "Spaceship1Off"),
                new Sprite(Content, "Bullet1")
            };

            spaceship1 = new Spaceship(spaceship1Sprites, new Vector2(graphics.GraphicsDevice.DisplayMode.Width / 2, graphics.GraphicsDevice.DisplayMode.Height / 2))
            {
                Controls = new Input(Keys.W, Keys.D, Keys.A, Keys.Space)
            };
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            currentKeyboardState = Keyboard.GetState();

            if (currentKeyboardState.IsKeyDown(Keys.Escape))
                Exit();

            if(currentKeyboardState.IsKeyDown(Keys.P) && previousKeyboardState.IsKeyUp(Keys.P))
                paused = paused ? false : true;

            if (!paused)
                spaceship1.Update();

            base.Update(gameTime);
            previousKeyboardState = currentKeyboardState;
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            spaceship1.Draw(spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

Изменить 2: Решено! Как и ожидалось, дело было не в коде, а в том, что работало в Visual Studio. Каким-то образом моя конфигурация Visual Studio позволяла запускать предыдущую рабочую версию, если в текущей сборке есть ошибка ... Но я уже нашел настройку, чтобы изменить это, так что тайна решена!


person Nordellak    schedule 12.08.2018    source источник
comment
Учитывая, что код не будет компилироваться, если вы действительно закомментируете указанные строки, то а) spaceship1Sprites определен в более широкой области, или б) ваш пример не является тем, что вы на самом деле сделали, или является неполным. Пожалуйста, расширите размещенный вами код.   -  person Jens    schedule 12.08.2018
comment
@Jens Я добавил полный код. Я также могу добавить содержимое класса Spaceship, если необходимо, но в нем нет никаких следов списка spaceship1Sprites appart, поскольку он является параметром в конструкторе.   -  person Nordellak    schedule 12.08.2018
comment
Я обнаружил, что в Visual Studio я могу запустить код (F5) или скомпилировать решение (Ctrl + Shift + B). При компиляции он не работает, как ожидалось, но нажатие кнопки «Выполнить» работает, как если бы оно не компилировалось заранее и использовало старую версию программы. Если это так, то я не понимаю, почему большинство изменений применяется, когда я запускаю программу, но некоторые не применяются (например, удаление списка спрайтов).   -  person Nordellak    schedule 12.08.2018
comment
Я нашел причину этого! У меня есть письменное объяснение во второй редакции.   -  person Nordellak    schedule 13.08.2018
comment
Молодец. Вы также можете написать ответ на свой вопрос и отметить его как решенный.   -  person Jens    schedule 13.08.2018


Ответы (1)


По-видимому, в настройках есть параметр, который позволяет Visual Studio запускать предыдущую рабочую сборку проекта в случае ошибки, которая была включена по умолчанию в моей установке (если я случайно не включил эту опцию по ошибке).

Я нашел решение благодаря этому ответу в другом вопросе, пытаясь исследовать проблему:

Попробуйте изменить это значение:

  • Tools
    • Options
      • Projects and Solutions
        • Build and Run
          • On Run, when build or deployment errors occur: Do not Launch
person Nordellak    schedule 12.08.2018
comment
Когда вы впервые устанавливаете Visual Studio, он запрашивает этот параметр при первом возникновении ошибки сборки. Если вы случайно установите флажок, когда появится это диалоговое окно, оно больше не появится. Я сам делал это несколько раз. Супер раздражает. - person craftworkgames; 15.08.2018
comment
Я не знал об этом! Я учту это в следующий раз, когда мне придется переустанавливать Visual Studio. - person Nordellak; 16.08.2018