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);
}