这可能是一个非常简单的愚蠢问题,但我只需要一些帮助来理解它。我将一个结构存储在字典中,我想抓住该结构更改一些值,然后让它在字典中自动更新,但行为很奇怪。
public struct Test
{
public int a;
}
public class Tester
{
public static Dictionary<int, Test> d = new Dictionary<int, Test>();
public static bool GetTest(int position, out Test test)
{
if (d.ContainsKey(position)) {
test = d[position];
return true;
} else {
test = new Test();
return false;
}
}
}
当我尝试从字典中获取结构并更改值时,它不会更新。
Test n = new Test();
n.a = 10;
Tester.d.Add(n.a, n);
Tester.GetTest(10, out Test t1);
Debug.Log(t1.a);
t1.a = 20;
Tester.GetTest(10, out Test t2);
Debug.Log(t2.a);
一直显示 10。所以当我使用该out
参数时,它会复制字典中的结构并返回该结构?所以我需要再写一行来再次更新字典,对吗?
有什么简单的方法可以抓取结构并只在字典中更新其值而不添加额外的行?
编辑:
我可以做到这一点...
Tester.d[position].a = 20;
但是有没有办法用一种方法来实现这一点?在哪里我可以获取整个结构,编辑一个值,然后它会自动在字典中更新?抱歉问了个愚蠢的问题,我只是不明白这种行为。
你不能,除非
d
是一个数组。Dictionary
(像List
)没有引用返回索引器,因此您将始终拥有索引器返回的结构体的副本,而不是存储在字典中的实际结构体。因此,您的修改不会被反映回来。简短示例:
您可以查看
ref return
声明(从 C# 7.0 开始支持),以及以下 API:CollectionsMarshal.GetValueRefOrNullRef
(.NET 6)CollectionsMarshal.GetValueRefOrAddDefault
(.NET 6)Unsafe.IsNullRef
(.NET 5)Unsafe.NullRef
(.NET 5)你可以像这样使用它们:
bool
注意,我交换了和返回值的位置Test
。ref
魔法只对返回值起作用,对out
参数不起作用。用法:
输出:
在线演示。
你不应该这样做。虽然可以更改结构体内部的值,即使该值嵌套在字典中(例如在你的示例中),你也应该尽量避免这种情况,并将结构体视为只读。如果你想更新字典的值,请用新实例替换整个值,而不是操作其内容。否则,行为很可能不是你所期望的。
执行替换对性能的影响也应该是最小的。因此你可以这样做