ValueTuple 结构是否只能作为变量可变?

is the ValueTuple structure only mutable as variable?

我尝试使用 ValueTuple 结构并尝试实现一个不可变的组合键。键由值类型组成。

我试图通过一些单元测试来破坏以下实现,但到目前为止没有成功。我错过了什么吗?

此外,这只是出于好奇,我想在 .NET 4.7 发布之前了解 ValueTuples 和它的局限性。

到目前为止,我对 ValueTuple 的理解是它仅作为变量可变,而不是作为字段或 属性。虽然不确定这里的“可变”是什么意思。改变 ValueTuple 实例 实际上 创建一个新的 ValueTuple (就像众所周知字符串是“不可变的”但 实际上 引用类型)?

from

System.ValueTuple isn't only a struct, it's a mutable one, and one has to be careful when using them as such. Think what happens when a class holds a System.ValueTuple as a field.

这里是我的实现和测试

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()));
    }
}

error: Cannot modify the return value of 'ImmutableKey.Key' because it is not a variable

可以在三种情况下更改可变结构并查看结果:

  • 局部变量:MyStruct s = new MyStruct(); s.Prop = 4;
  • 字段 另一种类型:class MyType { public MyStruct S;} ... myType.S.Prop = 4;
  • 数组的元素:MyStruct[] myArray =...; myArray[3].Prop = 4;

为什么 post 中的代码未检测到更改 - 使用的代码 属性 而不是字段。

请注意,List<MyStruct> 不允许修改,因为索引器 (this[..]) returns 项目的副本(因为不支持像 C++ 那样返回引用)。