我正在将后端转换为c#,并且发现了奇怪的行为
当我在字典中的列表中添加元素
(实际上在另一本词典中):
不久,它将值添加到字典中每个元素的每个列表中。
代码如下:
public class Validator_Counter_Model
{
public readonly Dictionary<string,Info_Model> Info;
private Dictionary<string,Dictionary<DateTime,List<int>>> _map = new Dictionary<string, Dictionary<DateTime,List<int>>>();
public Validator_Counter_Model(Dictionary<string, Info_Model> info)
{
Info = info;
}
public void Add(Validation_Element element)
{
/// #### PROBLEM IS HERE!
if (!_map.ContainsKey(element.Id))
{
Dictionary<DateTime, List<int>> newmap = new Dictionary<DateTime, List<int>>();
_map.Add(element.Id, newmap);
}
DateTime fulldate = new Custom_Time_Model(element.Time).RegularTime;
if (!_map[element.Id].ContainsKey(fulldate.Date))
{
List<int> newList = new List<int>();
_map[element.Id].Add(fulldate.Date, newList);
}
_map[element.Id][fulldate.Date].Add(element.Time);
/// #### PROBLEM IS HERE!
}
public void Del(Validation_Element element)
{
DateTime fulldate = new Custom_Time_Model(element.Time).RegularTime;
DateTime date = new DateTime(fulldate.Year, fulldate.Month, fulldate.Day);
_map[element.Id][date].Remove(element.Time);
}
public void Update(Dictionary<string, Dictionary<DateTime, List<int>>> newMap) => _map = newMap;
public Dictionary<string, Dictionary<DateTime, List<int>>> map => _map;
}
}
答案 0 :(得分:0)
鉴于字典键是string
和DateTime
之类的已知类型,我可以填写缺失类的实现,而具体细节并不重要。我不在乎它们是否包含有意义的值。我只想看看一切如何。这些都贴在最后:
现在可以编写一个单元测试,以查看您所描述的情况是否正在发生。
[TestMethod]
public void validation_elements_are_added_to_only_one_dictionary()
{
var elementOne = new Validation_Element {Id = "A", Time = 1 };
var elementTwo = new Validation_Element { Id = "B" , Time = 2};
var elementThree = new Validation_Element { Id = "A" , Time = 3};
var subject = new Validator_Counter_Model(new Dictionary<string, Info_Model>());
subject.Add(elementOne);
subject.Add(elementTwo);
subject.Add(elementThree);
var output = subject.map;
var elementsWithId_A = output["A"];
var elementsWithId_B = output["B"];
var id_a_innerList = elementsWithId_A[new DateTime(2000, 1, 1)];
var id_b_innerList = elementsWithId_B[new DateTime(2000, 1, 1)];
Assert.AreEqual(2, id_a_innerList.Count);
Assert.AreEqual(1, id_b_innerList.Count);
}
我要添加两个带有“ A”的验证元素和一个带有“ B”的验证元素。这意味着_map
应该包含两个字典。内部字典的键将始终为1/1/2000
,因此将有两个内部列表。
我期望的是A
的内部列表将包含两个项目,B
的内部列表将包含一个项目。如果每个项目都添加到每个列表中,那么它们都会有两个。
测试通过了,在这种情况下是可以预期的。仅通过查看代码,我们可以看到Add
正在创建不同的列表,并且不会将项目添加到两个列表中。但是现在测试证实了这一点。
这意味着,如果您看到项目被添加到多个列表中,那么问题就出在您想像的地方。它必须在其他地方。那是关于单元测试的很棒的事情之一。它们使我们对代码的某个区域具有一定的确定性,因此,如果某些地方不起作用,我们知道问题可能出在没有单元测试的区域。缩小搜索范围可以更快,更轻松地发现错误。
如果我们确实发现单元测试有问题,那么我们可以只调试该单元测试,而不必调试整个应用程序。然后想象一下其他类是否也有单元测试。在编写代码时,我们总是会犯错误,但是通过单元测试,我们可以更快地发现它们并更轻松地解决它们。
在这种情况下,我弄虚了您的类的实现有些混乱。尽管我认为这仅仅是数据,但我认为这没有什么不同,但确实会带来很小程度的不确定性。我会用真实的替换它们,然后相应地调整测试。您可以根据需要编写更多测试。
未提供的类的有效实现:
public class Validation_Element
{
public string Id { get; set; }
public int Time { get; set; }
}
public class Custom_Time_Model
{
public Custom_Time_Model(int time)
{
Time = time;
// This makes it possible to create classes where `Time` is different
// but fullDate.Date (in the Add method) is the same. If I want that date
// to be different I'll add 24 or more hours.
RegularTime = new DateTime(2000,1,1).AddHours(time);
}
public DateTime RegularTime { get; set; }
public int Time { get; set; }
}
public class Info_Model { }
答案 1 :(得分:0)
找到了答案HERE
基本上是第二个字典(第一个字典中的那个) 本身不是“字典”,而是另一本字典的参考 这就是为什么在列表中添加值会更改每个键的所有列表