С# DateTime всегда создает новый объект?

почему в С# мои две переменные указывают на разные объекты DateTime?

DateTime a1 = DateTime.Now;
DateTime a2 = a1;

a1 = a1 + TimeSpan.FromMinutes(15);
a2 = a2 - TimeSpan.FromMinutes(16);

Я понял, что a2 фактически указывает на новый объект, который отличается от a1.

Но в другом случае. Скажем, у меня есть класс Person, а age = 1;

Person a1 = new Person();
a2 = a1;
a2 = Person.Age = 2;

В случае Person a1 и a2 указывают на один и тот же объект. Я действительно запутался здесь, каждый может объяснить?

Ответ 1

DateTime - тип значения - структура.

Со значениями типов, когда вы делаете что-то вроде:

DateTime a2 = a1;

a2 получает копию значений a1. Это не то же самое отношение к одному и тому же месту памяти, а полная отдельная копия.

С другой стороны, Person является ссылочным типом - классом.

Когда вы выполните:

Person p2 = p1;

С ссылочным типом ссылка, на которую указывает p2, является той же, что указывает p1. Таким образом, изменения в одном являются изменениями обоих.

См. Типы значений и типы ссылок в MSDN.

Ответ 2

Как уже отмечалось, DateTime - это структура, а не класс и, следовательно, тип значения. Это можно увидеть в редакторе Visual Studio, если вы измените цвет текста, используемый для отображения структур. Откройте диалоговое окно в меню Tools > Options и перейдите к Environment > Fonts and Colors

enter image description here

Полезно изменить цвет делегатов, перечислений, интерфейсов и структур (типы значений).

Ответ 3

Разница здесь в том, что DateTime - это тип значения, и я предполагаю, что Person является ссылочным типом (классом).

В случае присвоения переменной типа значения вы фактически копируете содержимое памяти из одного места в другое.

Однако в случае ссылочного типа вы все равно указываете на одну и ту же часть памяти.

Ответ 4

Здесь есть две отдельные концепции. Во-первых, DateTime - это тип значения (a.k.a. a struct), а Person - [предположительно] ссылочный тип (класс). Из-за этого, когда вы делаете:

DateTime date1 = DateTime.Now;
DateTime date2 = date1;

date2 приведет к копированию значения, поэтому две переменные не будут ссылаться на один и тот же объект.

С классами, когда вы делаете:

Person p1 = new Person();
Person p2 = p1;

p1 фактически не содержит Person, он просто содержит ссылку на человека. Затем эта ссылка копируется (по значению) на p2. Эффект копирования этой ссылки состоит в том, что обе переменные теперь "указывают" или "ссылаются" на один и тот же объект.

Далее возникает проблема изменчивости. Person, в этом случае, является изменяемым типом. Это означает, что его можно изменить. С другой стороны, неизменяемый тип нельзя изменить после его создания.

Строка:

p2.Age = 2;

фактически меняет объект, который ссылается на p2, и поскольку p2 и p1 оба ссылаются на один и тот же объект, p1.Age будет 2 после этой строки кода.

Теперь, для демонстрационных целей, позвольте сделать неизменный класс Person:

public class Person
{
    private int _age;
    public Person(int someAge)
    {
        _age = someAge;
    }

    public int Age
    {
        get { return _age; }
    }

    public Person Grow()
    {
        return new Person(_age + 1);
    }
}

Если мы сделаем что-то вроде этого:

Person p1 = new Person(1);
Person p2 = p1;
p2 = p2.Grow();

вторая строка делает то, что было раньше, гарантируя, что оба указывают на один и тот же объект, но третья строка отличается. Вместо того, чтобы изменять (или мутировать) этого человека, чтобы сделать его старше года, наш метод Grow возвращает новый объект Person, который представляет кого-то старше на год. После этого p2 и p1 больше не будут ссылаться на один и тот же объект; Я только что изменил, какой объект p2 ссылается на новый, который только что создал метод Grow.

Этот второй пример довольно похож на то, что происходит с DateTime. Вы не можете мутировать объект DateTime; он неизменен. Вызов методов (в этом случае - плюсы и минусы) возвращает и полностью новый объект. По соглашению типы значений не должны изменяться без какой-либо веской причины, так как часто бывает сложно справиться с ними. Типы ссылок могут быть неизменными или изменяемыми; не имеет существенных проблем (в общем случае).