如何正确初始化List<KeyValuePair<string,HashSet<string>>>?添加元素时值异常变更排查
问题根源:复用了同一个引用类型实例
你遇到的问题核心在于引用类型的特性:HashSet<string>是引用类型,而你在整个循环中一直复用同一个txtFiles实例。
当你把txtFiles添加到KeyValuePair并加入列表时,并没有复制一份新的HashSet,只是把这个集合的内存地址(引用)存进了列表的元素里。所以列表里所有的KeyValuePair<string, HashSet<string>>的值,其实都指向同一个HashSet对象——每次循环里的txtFiles.Clear()和后续添加操作,都是在修改这个唯一的集合,自然会导致之前列表元素里的值跟着变化。
解决方案:每次循环创建新的HashSet实例
把HashSet<string>的初始化移到foreach循环内部,这样每次处理一个文件时,都会创建一个全新的HashSet,避免引用复用:
List<KeyValuePair<string, HashSet<string>>> logTxtFilesList = new List<KeyValuePair<string, HashSet<string>>>(); DirectoryInfo dirInfo = new DirectoryInfo(directoryPath); recentFiles = dirInfo.EnumerateFiles(); string pattern = @"^.*\|END_OF_PARAM\|([A-Za-z0-9_-]+\.txt)$"; // 补充:原代码的正则需要加@转义,否则会编译报错 foreach (FileInfo file in recentFiles) { // 每次循环都新建一个HashSet,不再复用旧实例 HashSet<string> txtFiles = new HashSet<string>(); using (FileStream fs = File.Open(file.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (BufferedStream bs = new BufferedStream(fs)) using (StreamReader sr = new StreamReader(bs)) { string line; while ((line = sr.ReadLine()) != null) { Match match = Regex.Match(line, pattern); if (match.Success) { string FileName = match.Groups[1].ToString(); if (txtFiles.Add(FileName)) { // 数据库插入操作 } } } } logTxtFilesList.Add(new KeyValuePair<string, HashSet<string>>(file.Name, txtFiles)); }
补充说明:KeyValuePair<TKey, TValue>本身是值类型,但它的TValue如果是引用类型(比如HashSet),存储的还是引用。所以只要多个KeyValuePair的TValue指向同一个引用类型实例,修改这个实例就会影响所有对应的KeyValuePair。通过每次循环新建HashSet,就能保证每个列表元素都持有独立的集合实例,不会互相干扰。
内容的提问来源于stack exchange,提问作者m_beta
相关产品推荐
相关产品推荐

