Как исправить изменяемые объекты внутри копии IReadOnly копии спискаC#

Место общения программистов C#
Ответить
Anonymous
 Как исправить изменяемые объекты внутри копии IReadOnly копии списка

Сообщение Anonymous »

Код: Выделить всё

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended.Graphics;

namespace GameCore.Core;

#nullable enable
public class GameObject
{
public Guid Id { get; }
public Sprite? Sprite { get; }
public Rectangle BoundingBox { get; }
public Vector2 Position => new(BoundingBox.X, BoundingBox.Y);
public float SpriteRotation { get;}
public Vector2 Scale { get;}
private static List _gameObjects = new();
public static IReadOnlyList GameObjects => _gameObjects;
public static int Count => _gameObjects.Count;

/// 
/// A game Object class that is Observed by the program
/// 
/// 
Positon of the game object for drawing
/// Sprite of the object
/// 
/// 
/// 
/// 
/// Triggers when you set both sprite and size as null.
/// Because if size is null its determined by the sprite size.
/// 
public GameObject(Vector2 position, Sprite? sprite = null, Vector2? size = null, float rotation = 0, float scale = 1)
{
Id = Guid.NewGuid();

Vector2 finalSize;

Sprite = sprite;

if (size == null && sprite != null)
finalSize = sprite.Size.ToVector2();
else if (size != null)
finalSize = size.Value;
else
throw new ArgumentException("Either sprite or size must be provided.");

BoundingBox = new(
(int)position.X,
(int)position.Y,
(int)finalSize.X,
(int)finalSize.Y);

SpriteRotation = rotation;
Scale = new(scale, scale);
}

/// 
/// Gets a game object by its unique identifier.
/// 
/// id of an object
/// 
public static GameObject? GetById(Guid id)
{
return _gameObjects.FirstOrDefault(go => go.Id == id);
}

/// 
/// Gets the first game object of the specified type.
/// 
/// Child type of GameObject
/// 
public static T? GetByType() where T : GameObject
{
return _gameObjects.OfType().FirstOrDefault();
}

/// 
/// Gets all game objects of the specified type.
/// 
/// Child type of GameObject
/// 
public static List  GetAllByType() where T : GameObject
{
return _gameObjects.OfType().ToList();
}

/// 
/// Instantiates a new game object and adds it to the static list.
/// 
/// 
public static void Instantiate(GameObject gameObject)
{
_gameObjects.Add(gameObject);

gameObject.OnCreated();
}

/// 
/// Clears all game objects from the static list.
/// 
public static void ClearAll()
{
_gameObjects.Clear();
}

/// 
/// Called every frame to update the game object's state.
/// 
protected virtual void Update() { }

/// 
/// Called once when the game starts to initialize the game object.
/// 
protected virtual void Start() { }

/// 
/// Called once when the game object is created.
/// 
protected virtual void OnCreated() { }

private void Draw(SpriteBatch spriteBatch)
{
if (Sprite != null)
spriteBatch.Draw(Sprite, Position, SpriteRotation, Scale);
}

/// 
/// Updates all game objects in the scene.
/// For GameObjects with AnimatedSprite, it also updates the animation.
/// 
public static void UpdateAll(GameTime gameTime)
{
foreach (var gameObject in _gameObjects.ToList())
{
gameObject.Update();

//when sprite is animated, update it
if(gameObject.Sprite is AnimatedSprite animatedSprite)
animatedSprite.Update(gameTime);
}
}

/// 
/// Starts all game objects in the scene.
/// 
public static void StartAll()
{
foreach (var gameObject in _gameObjects.ToList())
gameObject.Start();
}

/// 
/// Draws all game objects in the scene.
/// 
/// 
public static void DrawAll(SpriteBatch spriteBatch)
{
foreach (var gameObject in _gameObjects.ToList())
if (gameObject != null)
gameObject.Draw(spriteBatch);
}

/// 
/// Deletes the game object from the static list.
/// 
public void Delete()
{
_gameObjects.Remove(this);
}
}
Хорошо, я создал этот класс GameObject. Идея состоит в том, что новые классы, такие как враг или игрок, будут наследовать от него и получать столкновения и тому подобное.
Проблема связана с атрибутом _gameObjects и GameObjects, потому что, когда я получаю список GameObjects, он в основном дает тот же список, но не изменяемый, но объекты внутри все еще изменяемы, поэтому, когда мне нравится получать объекты до того, как он пройдет через него в updateAll, и изменить его после этого, это может вызвать проблемы, однако я не хочу получать копию объекта, потому что мне нужно его изменить.

Я просто чувствую, что это небезопасно и могло бы быть намного безопаснее, мне нужна помощь

Подробнее здесь: https://stackoverflow.com/questions/798 ... -of-a-list
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»