C# - сбросить значение структуры на класс или структуру

Я пытаюсь написать сценарий с Unity, и у меня есть проблема, чтобы понять, как работает struct.

Начните с базы кода:

 public class Engine : MonoBehaviour {

   public Hero selectedHero;
   public List<Hero> heroes;

   public struct Hero {
     public string name;
     public Hero(string n) {
       name = n;
     }
   }
 } 

Сначала я пытаюсь сделать какую-то функцию для выбора / отмены выбора..

/* ... */
public Hero getSelected(Hero h) {
  return selectedHero;
}
public void setSelected(Hero h) {
  selectedHero = h;
}
public bool hasSelected(Hero h) {
  return (selectedHero != null);
}
public void clearSelected() {
  selectedHero = null; //  This is not working ! :'(
}
/* ... */

И я получил эту ошибку:

Невозможно преобразовать ноль в Hero потому что это тип значения

Я много читал о C# и Unity Scripting, и ответ таков:

Структура не может быть нулевой, так же как int не может быть нулевой, а float не может быть нулевым - все они являются типами значений

Но? Какое реальное решение!? Я использовал два уродливых решения, чтобы избежать этого:

Решение № 1 я могу поставить public bool hasSelected и всегда проверяйте это перед использованием selected приписывать.

Решение № 2 заключается в создании List<Hero> selected вместо простого Hero и обрабатывать, если длина равна 0 или 1.

Существует ли лучшее решение, более чистое?!

Бонусный вопрос: как создать функцию, которая будет возвращать одного Героя на основе теста, мое лучшее (безобразное) решение:

public Hero GetHero(string name) {
    foreach (Hero hero in heroes) {
        if (hero.name == name) {
            return hero;
        }
    }
    return null; // Not working ?! What can I return ?!
 }

3 ответа

Решение

Если вам нужно, чтобы ваш тип был обнуляемым, похоже, что вы должны сделать Hero класс (ссылочный тип) вместо struct (тип значения). Изменения в вашем коде будут минимальными, просто поменяйте местами ключевое слово:

public class Hero {
    public string name;
    public Hero(string n) {
        name = n;
    }
}

О главном вопросе:

Типы значений (int, struct и т. Д.) Не могут выражать нуль в своем двоичном представлении, поэтому.NET не допускает. Но.NET это имеет Nullable<T> структура, которая добавляет дополнительные байты для нулевого представления.

О функциях выбора / отмены выбора

Я реорганизовал ваш код для работы со структурой:

public Hero GetSelected()
{
    return selectedHero;
}

public void SetSelected(Hero h)
{
    selectedHero = h;
}

public bool HasSelected()
{
    return !(selectedHero.Equals(default(Hero)));
}

public void ClearSelected()
{
    selectedHero = default(Hero);
}

О бонусном вопросе:

Все просто, используйте LinQ =)

public Hero GetHero(string name)
{
    return heroes.Where(w => w.name.Equals(name)).FirstOrDefault();
}

PS: "Значение по умолчанию" Это не "Нулевое значение".

Рекомендации:

Надеюсь, это поможет

Если есть причина, по которой вы должны использовать Struct вместо класса, используйте default для проверки своих структур.

Иногда ваша программа может вести себя (или неправильно) по-разному, когда она ожидает структуру и вы передаете класс.

Итак, вот изменения для двух ваших методов:

       public bool hasSelected(Hero h)
        {
            return !(h.Equals(default(Hero)));
        }
        public void clearSelected()
        {
            selectedHero = default(Hero); 
        }
Другие вопросы по тегам