我玩弄了这个ValueTuple
结构并尝试实现一个不可变的复合键。键由值类型组成。
我试图通过一些单元测试来打破以下实现,但到目前为止没有成功。我错过了什么吗?
这也只是出于好奇,我想在ValueTuple
.NET 4.7 发布之前了解 s 和它的限制。
到目前为止,我对 a 的理解ValueTuple
是,它仅作为变量是可变的,而不是作为字段或属性。不过,不确定“可变”在这里是什么意思。更改ValueTuple
实例是否实际上会创建一个新实例ValueTuple
(就像众所周知的字符串是“不可变的”但实际上是引用类型)?
从这个答案
System.ValueTuple
不仅是 astruct
,它还是一个可变的,并且在使用它们时必须小心。想想当一个类将 aSystem.ValueTuple
作为一个字段时会发生什么。
这是我的实现和测试
public interface IHaveCompositeKey
{
(Guid id, string name) Key { get; }
}
public class ImmutableKey : IHaveCompositeKey
{
public (Guid id, string name) Key { get; }
public ImmutableKey((Guid id, string name) key) => Key = key;
public override int GetHashCode() => Key.GetHashCode();
public override bool Equals(object obj)
{
var a = obj as ImmutableKey;
return a != null && Key.Equals(a.Key);
}
}
[TestFixture]
public class KeyTests
{
[Test]
public void Test1() // passes
{
var key = (Guid.NewGuid(), "Foo");
var a = new ImmutableKey(key);
var b = new ImmutableKey(key);
Assert.IsTrue(a.Equals(b));
Assert.IsTrue(a.GetHashCode().Equals(b.GetHashCode()));
}
[Test]
public void Test2() // passes
{
(Guid id, string name) key = (Guid.NewGuid(), "Foo");
var a = new ImmutableKey(key);
key.name = "Bar"; // mutable
var b = new ImmutableKey(key);
Assert.IsFalse(a.Equals(b));
Assert.IsFalse(a.GetHashCode().Equals(b.GetHashCode()));
}
[Test]
public void Test3() // does not compile
{
var key = (Guid.NewGuid(), "Foo");
var a = new ImmutableKey(key);
// compilation error
a.Key.name = "Bar"; // immutable
var b = new ImmutableKey(a.Key);
Assert.IsFalse(a.Equals(b));
Assert.IsFalse(a.GetHashCode().Equals(b.GetHashCode()));
}
}
错误:无法修改“ImmutableKey.Key”的返回值,因为它不是变量