Страницы

Поиск по вопросам

суббота, 14 декабря 2019 г.

В чем суть отличия между ссылочными и значимыми типами данных в C#?

#c_sharp #c_sharp_faq


В чем суть отличия между ссылочными и значимыми типами данных в C#?    


Ответы

Ответ 1



Значимые типы хранят значение, а ссылочные - ссылку на значение. class ByRef { public byte Value { get; set; } } struct ByVal { public byte Value { get; set; } } class Program { static void Main(string[] args) { ByRef byRef = new ByRef { Value = 0 }; ByVal byVal = new ByVal { Value = 0 }; } } В этом коде и byRef, и byVal создаются как локальные переменные метода Main на стеке. Переменная byVal содержит значение Value, а переменная byRef содержит ссылку на значение Value, хранящееся на куче.

Ответ 2



Основное различие между ссылочными и значимыми типами данных — смысл равенства и копирования. Для значимых типов при копировании вы получаете новый экземпляр, содержащий копии значений исходного экземпляра. Иными словами, экземпляры ведут себя как значения, например, как числа. Если вы скопировали значение, и изменили исходное значение, то эти изменения никак не отразятся на копии: Point p1 = new Point(1, 2); Point p2 = p1; // (1, 2) p1.X = 100; // p2.X всё ещё равно 1 Для ссылочных типов, копирование даёт вам новую ссылку на те же данные. Соответственно, если вы меняете объект ссылочного типа, то эти изменения становятся доступны по любой из ссылок на объект: XElement e1 = new XElement("test") { Value = "hello" }; XElement e2 = e1; e1.Value = "goodbye"; // e2.Value стало равно "goodbye" Теперь, равенство. Одинаковые экземпляры типов-значений, не зависимо от того, являются ли они копиями одного общего объекта или нет, являются равными. Экземпляры ссылочных типов, даже если они содержат одинаковые данные, являются разными. Point p1 = new Point(1, 2), p2 = new Point(1, 2); // p1 == p2 XElement e1 = new XElement("test") { Value = "hello" }, e2 = new XElement("test") { Value = "hello" }; // e1 != e2 Можно сказать, что объекты ссылочных типов обладают индивидуальностью, а объекты значимых типов — нет. Разумеется, семантику сравнения можно кастомизировать, перегрузив оператор сравнения (и/или реализовав интерфейс IEquatable). При этом можно, например, заставить ссылочный тип вести себя так, как будто бы он является значимым типом. И наоборот, храня данные значимого типа в неизменяемом поле ссылочного типа, можно заставить значимый тип вести себя как ссылочный. Все остальные отличия являются лишь следствиями этих, главных отличий. То, что переменные ссылочного типа в Майкрософтовской реализации хранят внутри ссылку, есть по сути деталь имплементации. То, что экземпляры значимых типов иногда попадают на стек (а именно, когда они не являются полями классов, и не лежат в замыкании, async-методе или методе-генераторе), также является деталью имплементации (и может быть не так в будущих версиях или другой имплементации платформы .NET). Если вы выбираете, использовать для вашего объекта структуру (значимый тип) или класс (ссылочный тип), задайте себе вопрос: являются ли два объекта с одинаковыми данными одним и тем же, или разными? Если это, к примеру, объекты, представляющие человека, и в данных у вас его имя, фамилия и возраст, то имеет смысл использовать класс: ведь два человека с одинаковыми именами всё ещё не являются одним и тем же человеком. А если это, например, объект, представляющий рациональную дробь, то нету смысла разделять различные экземпляры дроби 3/8, так что тут уместно воспользоваться структурой.

Ответ 3



Например, если присвоить переменной объект ссылочного типа, то в этой переменной будет только ссылка указывающая на обьект, а не само значение. А если присвоить объект значимого типа, то он скопируется.

Комментариев нет:

Отправить комментарий