假设我有一个带有public int的x和y的struct Point。我想改变一个值,我可以。但是一旦我将它存储在字典中,我就不能再这样做了。为什么呢?
MWE:
using System;
using System.Collections.Generic;
public class Program
{
public struct Point
{
public int x, y;
public Point(int p1, int p2)
{
x = p1;
y = p2;
}
}
public static void PrintPoint(Point p)
{
Console.WriteLine(String.Format("{{x: {0}, y: {1}}}", p.x, p.y));
}
public static void Main()
{
var c = new Point(5, 6);
PrintPoint(c); // {x: 5, y: 6}
c.x = 4; // this works
PrintPoint(c); // {x: 4, y: 6}
var d = new Dictionary<string, Point>()
{
{ "a", new Point(10, 20) },
{ "b", new Point(30, 40) }
};
foreach (Point p in d.Values)
{
PrintPoint(p); // this works
}
PrintPoint(d["a"]); // this works // {x: 10, y: 20}
Console.WriteLine(d["a"].x.ToString()); // this works // 10
// d["a"].x = 2; // why doesn't this work?
}
}
为什么我可以在字典中访问结构变量但不能再更改它们?我该如何改变它们?
答案 0 :(得分:2)
您尝试做的事情有几个问题。
在99.999999999%的情况下,结构应该是只读的。请参阅Microsoft设计指南https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/struct
X不要定义可变值类型。
可变值类型有几个问题。例如,当一个 property getter返回一个值类型,调用者接收一个副本。 由于副本是隐式创建的,因此开发人员可能不知道 他们正在改变副本,而不是原始值。也, 某些语言(特别是动态语言)使用时遇到问题 可变值类型,因为即使是局部变量,当取消引用时, 导致复制。
您也不应该改变正在用作字典键的对象。字典基于哈希值,如果更改键的字段,则将更改其哈希值。请参阅:https://stackoverflow.com/a/3007334/4415493
字典类型不会尝试防范 用户修改使用的密钥。它纯粹由开发人员负责 负责不改变密钥。
如果你想到这一点,这真的是唯一理智的路线 字典可以采取。考虑做一个的含义 像对象上的成员克隆一样操作。为了 彻底的你需要做一个深刻的克隆,因为它是可能的 密钥中引用的对象也会发生变异,从而影响 哈希码。所以现在表中使用的每个键都有它的完整对象 克隆图以防止突变。这将是两者 越野车,可能是非常昂贵的操作。
答案 1 :(得分:1)
您的字典值是Point对象。因此,您可以使用新的Point对象更新密钥。
Right Way (Update):
d["a"]= new Point(5, 20);
PrintPoint(d["a"]);
Console.WriteLine(d["a"].x.ToString());
Round About: (Remove and Add)
d.Remove("a");
d.Add("a", new Point(2, 20));
PrintPoint(d["a"]);
Console.WriteLine(d["a"].x.ToString());