为什么这一行代码与上面的两行代码不同

本文关键字:代码 两行 一行 为什么 | 更新日期: 2023-09-27 18:33:45

请参阅注释代码中的问题...

public struct Key
{
    public string Name;
    public object Value;
}

public class PrimaryKey
{
    Dictionary<string, Key> _keys = new Dictionary<string, Key>();
    object this[string index]
    {
        get
        {
            return _keys[index].Value;
        }
        set
        {
            if (!_keys.ContainsKey(index))
                _keys.Add(index, new Key() { Name = index, Value = value });
            else
            {
                var k = _keys[index];        // This compiles
                k.Value = value;             // just fine.
                _keys[index].Value = index;  // So why wouldn't this?
            }
        }
    }
}

我收到错误:

无法修改 Dictionary<string,Key>.this[string] 的返回值,因为它不是变量

为什么这一行代码与上面的两行代码不同

由于Key是结构体,而结构是值类型,因此当您通过方法、属性或索引器访问它时,它会返回结构实例的副本,而不是实例本身。尝试将Key声明为 class 。有关详细信息,您可以搜索结构和类或值和引用类型之间的区别。

这纯粹是因为你的Key是一个结构。该值被复制出来。.这意味着进行更改实际上除了更改新丢弃的副本外不会执行任何其他操作。编译器正在阻止这种情况发生。

将其更改为类将为您提供所需的功能,但实际上可能不是您想要的:

public class Key { }

您的前两行可以编译,但它们不起作用。要更改存储在字典中的值,您必须将更改的值放回字典中:

var k = _keys[index];
k.Value = value;
_keys [index] = k;

当您在同一语句中更改从字典中获取的值时,编译器可能会注意到您将要执行一些没有意义的操作,但是当您将其分成两个语句时,编译器无法保护您免受自己的伤害。

这种怪癖是建议不要使结构可变的原因之一。对于类,更改值的方式都有效,并且对于不可变的结构,您不会犯这样的错误。