【问题标题】:is the ValueTuple structure only mutable as variable?ValueTuple 结构是否只能作为变量可变?
【发布时间】:2017-05-08 16:15:45
【问题描述】:

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

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

这也只是出于好奇,我想联系ValueTuples,这是 .NET 4.7 发布之前的限制。

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

来自this answer

System.ValueTuple 不仅是struct,它是一个可变,在使用它们时必须小心。想想当一个类将System.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'的返回值,因为它不是一个变量

【问题讨论】:

  • 你知道属性和字段的区别吗?
  • 哦,我做到了,但我不明白structs(并且ValueTuple 被实现为struct)在被属性公开时的行为。如果我将Key 实现为公共字段,则它“有效”。谢谢!

标签: c# immutability mutability valuetuple


【解决方案1】:

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

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

为什么帖子中的代码没有检测到更改 - 代码使用了属性而不是字段。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多