19

为什么在 C# 中我的两个变量指向不同的 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 Case 中,a1 和 a2 指向同一个对象。我在这里真的很困惑,任何人都可以解释一下吗?

4

4 回答 4

40

DateTime是一个值类型 - 一个结构。

对于值类型,当您执行以下操作时:

DateTime a2 = a1;

a2获取的值的副本a1。它不是对同一个内存位置的同一个引用,而是一个完整的、单独的副本。

另一方面,Person是一个引用类型——一个类。

当你这样做时:

Person p2 = p1;

对于引用类型,指向的引用与p2指向的引用相同p1。所以一个的变化就是两个的变化。

请参阅MSDN 上的值类型和引用类型

于 2012-10-09T19:26:52.440 回答
8

正如其他人已经指出的那样,DateTime它是一个结构,而不是一个类,因此是一个值类型。如果更改用于显示结构的文本颜色,则可以在 Visual Studio 编辑器中对此进行可视化。Tools在菜单>中打开对话框Options并导航到Environment>Fonts and Colors

在此处输入图像描述

更改委托、枚举、接口和结构(值类型)的颜色很有帮助。

在此处输入图像描述

在 Visual Studio 2019 中,您还可以更改用户成员的外观,例如常量或参数。

于 2012-10-09T20:11:21.380 回答
4

这里有两个不同的概念在起作用。第一个是DateTime值类型(又名结构),而Person[大概]是引用类型(类)。因此,当您这样做时:

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

date2将导致复制值,因此两个变量不会引用同一个对象。

有了课程,当你这样做时:

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

p1实际上不包含 a Person,它只包含对 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对象。这样做之后p2p1将不再引用同一个对象;我刚刚将对象p2引用更改为该Grow方法刚刚创建的新对象。

第二个示例与正在发生的事情非常相似DateTime。你不能改变一个DateTime对象;它是不可变的。调用它的方法(在这种情况下是加号和减号运算符)返回一个全新的对象。按照惯例,值类型不应该在没有令人信服的理由的情况下是可变的,因为处理它们通常很棘手。引用类型可以是不可变的,也可以是可变的;两者都没有重大问题(在一般情况下)。

于 2012-10-09T19:56:30.307 回答
3

这里的区别在于 DateTime 是一个值类型,我假设 Person 是一个引用类型(类)。

在值类型的变量赋值的情况下,您实际上是将内存的内容从一个位置复制到另一个位置。

但是,在引用类型的情况下,您仍然指向同一块内存。

于 2012-10-09T19:26:26.327 回答