为何调用带ref的Subscribe后,外层字典中的内层字典仍为null?
嵌套Dictionary使用ref方法后外层字典值仍为null的原因分析
问题代码
var mammalIdSubscribers = new Dictionary<int, Dictionary<Guid, int>>(); var mammalId = 0; if (!mammalIdSubscribers.TryGetValue(mammalId, out var mammalSubscribers)) mammalIdSubscribers[mammalId] = mammalSubscribers; // 将null引用存入外层字典 Subscribe(ref mammalSubscribers); /* 调用Subscribe后mammalIdSubscribers[mammalId]仍为null, 但mammalSubscribers变量本身不为null,原因是什么? */ static void Subscribe(ref Dictionary<Guid, int> subscribers) { subscribers = new Dictionary<Guid, int> { { Guid.NewGuid(), 10 } }; }
核心原因
这是因为外层字典存储的是变量当时的引用值,而非变量本身的引用,具体执行流程拆解:
TryGetValue未找到对应键,mammalSubscribers被初始化为null,此时你把这个null值存入了外层字典mammalIdSubscribers,字典中键0对应的value是null。- 调用
Subscribe(ref mammalSubscribers)时,ref传递的是mammalSubscribers这个变量本身的引用,方法内给它赋值了一个新的Dictionary实例——这只会改变mammalSubscribers变量指向的对象,但外层字典里存储的还是之前的null引用,两者已经没有关联了。
简单说:字典存的是“当时的null”,之后变量指向新对象,不会回溯修改字典里已经存的旧引用。
解决方法
方法1:先创建实例,再存入字典
调整顺序,先通过Subscribe创建实例,再把有效的引用存入字典:
var mammalIdSubscribers = new Dictionary<int, Dictionary<Guid, int>>(); var mammalId = 0; if (!mammalIdSubscribers.TryGetValue(mammalId, out var mammalSubscribers)) { Subscribe(ref mammalSubscribers); mammalIdSubscribers[mammalId] = mammalSubscribers; // 存入新创建的实例引用 } Console.WriteLine(mammalIdSubscribers[mammalId].First().Value); // 正常输出10 static void Subscribe(ref Dictionary<Guid, int> subscribers) { subscribers = new Dictionary<Guid, int> { { Guid.NewGuid(), 10 } }; }
方法2:修改现有实例而非创建新实例
如果不需要创建新实例,而是直接初始化并修改现有字典,可以去掉ref,直接操作实例:
var mammalIdSubscribers = new Dictionary<int, Dictionary<Guid, int>>(); var mammalId = 0; if (!mammalIdSubscribers.TryGetValue(mammalId, out var mammalSubscribers)) { mammalSubscribers = new Dictionary<Guid, int>(); mammalIdSubscribers[mammalId] = mammalSubscribers; } Subscribe(mammalSubscribers); // 无需ref Console.WriteLine(mammalIdSubscribers[mammalId].First().Value); // 正常输出10 static void Subscribe(Dictionary<Guid, int> subscribers) { subscribers.Add(Guid.NewGuid(), 10); // 修改现有实例内容 }
内容的提问来源于stack exchange,提问作者Tea
相关产品推荐
相关产品推荐

