Почему я не могу использовать автоматически реализованные методы получения и настройки со списком? (Unity, C#)

#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, моральный эквивалент нуля).