#c# #list #unity3d #getter-setter
#c# #Список #unity3d #геттер-сеттер
Вопрос:
Я пытаюсь немного лучше разобраться в геттерах и сеттерах.
Я знаю, что могу использовать автоматически реализованные геттеры и сеттеры, например public Vector3 Position { get; set; }
, в качестве сокращения для
private Vector3 _position; public Vector3 Position { get {return _position;} set{_position = value;} }
НО чего я не могу понять, так это почему это не работает для Списков. Если я попытаюсь объявить список, как:
Listlt;Vector3gt; Positions { get; set;}
Unity выдает мне исключение нулевой ссылки.
Но если я использую длинную форму:
private Listlt;Vector3gt; _position = new Listlt;Vector3gt;(); public Listlt;Vector3gt; Position { get {return _position;} set{_position = value;} }
Это работает просто отлично. Я предполагаю, что это как-то связано с тем, как объявляются списки, но я хотел бы знать, что именно здесь происходит.
Комментарии:
1. Потому что во втором примере вы явно создаете экземпляр списка с помощью этого кода » новый списокlt;Вектор3gt;()». И в вашем первом примере список никогда не создается и, следовательно, является нулевым.
Ответ №1:
Когда вы пишете это
Listlt;Vector3gt; Positions { get; set;}
вы объявляете свойство типа Listlt;Vector3gt;
, но ничего ему не присваиваете, поэтому пытаетесь разыменовать его, например
Positions.Add(vec3);
будет кидать NullReferenceException
. Вы можете продолжить использовать автоматические свойства и инициализировать свой список следующим образом:
Listlt;Vector3gt; Positions { get; set;} = new Listlt;Vector3gt;();
Комментарии:
1. Удивительные. Очень полезно, спасибо!
Ответ №2:
В C# есть понятие типов значений и ссылочных типов. Типы значений «действуют как целые числа» — переменная типа значения фактически хранит значение, и оно имеет значение по умолчанию (обычно какое-то нулевое значение).
Ссылочные типы, с другой стороны, являются ссылками на что-то в памяти, а переменные ссылочного типа НЕ хранят фактический объект, вместо этого они хранят адрес фактического объекта. Если вы его не инициализировали, переменная ссылочного типа по умолчанию равна нулю, т. е. нулю.
Вектор3-это тип значения. Список-это ссылочный тип. Это объясняет другое поведение и то, почему ваш второй пример со списком работает — в этом случае вы явно создали и инициализировали объект списка и указали на него ссылку.
Это также является причиной того, что, в общем случае, иметь set
метод в свойстве списка-плохая идея. Вы не хотите, чтобы внешние абоненты полностью меняли список, на который он указывает, вы хотите изменить содержимое фактического списка, который у вас уже есть.
Комментарии:
1. Мне нравится ваш ответ, за исключением утверждения «переменная ссылочного типа по умолчанию равна нулю». По умолчанию для него установлено специальное значение
null
, нет0
. Утверждение, что ноль также известен какnull
в C#, неверно.2. Ну, в базовом двоичном значении, хранящемся в оперативной памяти, значение null фактически равно нулю. Спиши это на то, что в свое время я был старым Си-парнем. 🙂 Тем не менее, я понимаю вашу точку зрения. Я пытался провести корреляцию между значением по умолчанию для типа значения (которое состоит из всех нулей) и значением по умолчанию для ссылочного типа (null, моральный эквивалент нуля).