无法实习为可空的DateTime

时间:2018-08-21 20:47:33

标签: c# nullable string-interning

我正在尝试实习传递的某些对象值在内存中保留很长时间。其中一些对象是可空值类型。我无法正确地实习Nullable值,我认为可能发生某种我不理解的“有用”自动装箱。这是我应该通过的单元测试(假设Nullalbes的行为类似于对象),但不是:

[Test]
public void InternNullableType()
{
    DateTime? one = new DateTime(2010, 2, 3, 4, 5, 6, DateTimeKind.Utc);
    DateTime? two = new DateTime(2010, 2, 3, 4, 5, 6, DateTimeKind.Utc);

    // should be equal, but not reference equal
    Assert.False(ReferenceEquals(one, two));
    Assert.True(one.Equals(two));

    // create an interning dictionary
    Dictionary<DateTime?, DateTime?> intern = new Dictionary<DateTime?, DateTime?>();
    intern[one] = one; // add 'one', this will be the value we hand out
    two = intern[two]; // intern the value of two

    // values should be equal, and reference qual
    Assert.True(one.Equals(two));     

    // this fails when it passes for objects       
    Assert.True(ReferenceEquals(one, two));
}

这是怎么回事?

4 个答案:

答案 0 :(得分:4)

可空类型是结构,它们不是对象。它们是可以分配为null的特殊结构。由于string是一种引用类型,因此interning不能像使用字符串那样起作用。

检索可为空的对象的值时,装箱的值将被取消装箱,并使用该值创建新的可为空的实例。这就是ReferenceEquals返回false的原因。

来自docs

  

当装箱可空类型时,公共语言运行库会自动装箱Nullable对象的基础值,而不是Nullable<T>对象本身。也就是说,如果HasValue属性为true,则将Value属性的内容装箱。将可为空类型的基础值拆箱时,公共语言运行库将创建一个 Nullable<T>结构,该结构初始化为基础值。

答案 1 :(得分:1)

reg.exe ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f one对象是不同的对象。

two值类型仍然是值类型。

Nullable方法比较它们的指针值,因为它们的指针值不同,它们将为ReferenceEquals

答案 2 :(得分:1)

DateTime?仍然是不可变的值类型。可以将其视为整数。

int a = 1;
int b = 1;

//a == b <--- true
//ReferenceEquals(a, b) <--- false

int c = b;
//c == b <--- true
//ReferenceEquals(c, b) <---- false

因此,实际上您的two = intern[two];不是将one的地址存储到two中,而是创建一个新对象并从one复制值。

DateTime? one = new DateTime(2010, 2, 3, 4, 5, 6, DateTimeKind.Utc);

Dictionary<DateTime?, DateTime?> intern = new Dictionary<DateTime?, DateTime?>();
intern[one] = one;
Console.WriteLine(ReferenceEquals(intern[one], intern[one])); <---false
Console.WriteLine(ReferenceEquals(one, intern[one])); <---false

答案 3 :(得分:0)

Nullable<>是一个值类型。

调用ReferenceEquals是没有意义的,它将两个值放入不同的对象中,因此总是返回false。

您打算通过这种“实习”来实现什么?