我正在尝试为自定义类型进行扩展。这是我的密码。我不知道我的源代码在这段代码中是如何变成零的。即使在调试部分,hashsettemp也给了我一个10个日志事件的列表。但最终,来源变成了零。
public static void UnionSpecialWith(this HashSet<LogEvent> source, List<LogEvent> given,IEqualityComparer<LogEvent> comparer)
{
List<LogEvent> original = new List<LogEvent>(source);
List<LogEvent> second = given.Condense(comparer);
source = new HashSet<LogEvent>(original.Condense(comparer),comparer);
foreach (LogEvent logEvent in second)
{
if (original.Contains(logEvent, comparer))
{
int index = original.FindIndex(x => comparer.Equals(x, logEvent));
original[index].filesAndLineNos.MergeFilesAndLineNos(logEvent.filesAndLineNos);
}
else
original.Add(logEvent);
}
#if DEBUG
String content = String.Join(Environment.NewLine, original.Select(x => x.GetContentAsEventsOnly()));
HashSet<LogEvent> temp = new HashSet<LogEvent>(original, comparer);
#endif
source = new HashSet<LogEvent>(original, comparer);
}
有人能告诉我出了什么问题吗?
编辑:这是我的自定义类型。每当我发现一个重复的,我想把它的"filesAndLineNos"和原来的合并。这就是我试图通过上面的代码来实现的。
public class LogEvent
{
public String mainEventOriginal;
public String subEventOriginal;
public String mainEvent;
public String subEvent;
public int level;
public Dictionary<String,HashSet<int>> filesAndLineNos;
}
用法有点像
HashSet<LogEvent> required = new HashSet<LogEvent>(initialUniqueSet);
required.UnionSpecialWith(givenListOfLogEvents);
这只是默认情况下.NET中按值传递参数的问题。您正在更改source
的值以引用不同的HashSet
,这根本不会更改调用者的变量。假设Condense
不修改列表(我不知道这个方法),那么你的方法就像一样毫无意义
public void TrimString(string text)
{
// This changes the value of the *parameter*, but doesn't affect the original
// *object* (strings are immutable). The caller won't see any effect!
text = text.Trim();
}
如果你用打电话给上面的人
string foo = " hello ";
TrimString(foo);
则CCD_ 4仍将引用内容为"hello"的字符串。显然,你的方法更复杂,但问题的原因是一样的。
您的扩展方法需要修改通过source
参数传入的原始HashSet
的内容,或者它应该返回新的集合。返回新集合更像LINQ,但HashSet.UnionWith
确实修改了原始集合-这取决于您想要更接近哪个模型。
编辑:如果您想在适当的位置修改集合,但由于逻辑原因,实际上需要完全替换内容,那么您可能需要考虑创建新集合,然后清除旧集合并将所有内容添加回:
public static void UnionSpecialWith(this HashSet<LogEvent> source,
List<LogEvent> given,
IEqualityComparer<LogEvent> comparer)
{
List<LogEvent> original = new List<LogEvent>(source);
List<LogEvent> second = given.Condense(comparer);
foreach (LogEvent logEvent in second)
{
if (original.Contains(logEvent, comparer))
{
int index = original.FindIndex(x => comparer.Equals(x, logEvent));
original[index].filesAndLineNos
.MergeFilesAndLineNos(logEvent.filesAndLineNos);
}
else
{
original.Add(logEvent);
}
}
source.Clear();
foreach (var item in original)
{
source.Add(item);
}
}
但是,请注意:
- 这不会替换现有集合中的比较器。你不能那样做
- 总的来说效率很低。老实说,感觉
Dictionary
更适合