首先,我是仿制药的新手,所以我提前为任何错误道歉。
我希望能够以统一的方式比较不同类型的词典。 我要比较可能有这种类型的2个词典(只是为了清楚我要比较2个具有相同类型的不同词典):
Dictionary<string, Int32>
Dictionary<Int32, Int32>
Dictionary<string, string>
Dictionary<string, List<Int32>>
Dictionary<Int32, List<Int32>>
Dictionary<Int32, List<ComplexObject>>
使用泛型,我得到了这段代码:
private static bool DictionaryEquals<TKey, TValue>(Dictionary<TKey, TValue> left, Dictionary<TKey, TValue> right)
{
var comp = EqualityComparer<TValue>.Default;
if (left.Count != right.Count)
{
return false;
}
foreach (var pair in left)
{
TValue value;
if ((typeof(TValue).Namespace == "System.Collections.Generic"))
{
TValue rightValue;
right.TryGetValue(pair.Key, out rightValue);
return ListEquals<TValue>(new List<TValue>(pair.Key), rightValue);
}
if (right.TryGetValue(pair.Key, out value) || (!comp.Equals(pair.Value, value)))
{
return false;
}
}
return true;
}
private static bool ListEquals<TValue>(List<TValue> left, List<TValue> right)
{
if (left.Count != right.Count)
{
return false;
}
return left.All(right.Contains);
}
我在调用ListEquals方法时遇到问题,我不知道如何传入pair.key和rightValue参数。
感谢您提出任何建议
答案 0 :(得分:0)
如果TValue
是rightValue的类型,则TValue是List<SomeType>
。但是使用ListEquals,而不是List<SomeValue>
答案 1 :(得分:0)
我改变了你的代码,这是有效的,但我不知道如何替换dynamic
,这不是最好的选择,但解决了所有的铸造问题。
private static bool DictionaryEquals<TKey, TValue>(Dictionary<TKey, TValue> left, Dictionary<TKey, TValue> right)
{
var comp = EqualityComparer<TValue>.Default;
if (left.Count != right.Count)
{
return false;
}
if (typeof(TValue).IsGenericType && typeof(TValue).GetGenericTypeDefinition() == typeof(List<>))
{
return left.All(pair => right.ContainsKey(pair.Key) && ListEquals((dynamic)pair.Value, (dynamic)right[pair.Key]));
}
else
{
return left.All(pair => right.ContainsKey(pair.Key) && comp.Equals(pair.Value, right[pair.Key]));
}
}
private static bool ListEquals<TValue>(List<TValue> left, List<TValue> right)
{
if (left.Count != right.Count)
{
return false;
}
return left.All(right.Contains);
}
答案 2 :(得分:0)
以下是解决问题的方法:
private static bool DictionaryEquals<TKey, TValue>(Dictionary<TKey, TValue> left, Dictionary<TKey, TValue> right)
{
var comp = EqualityComparer<TValue>.Default;
if (left.Count != right.Count)
{
return false;
}
if (left.Keys.Intersect(right.Keys).Count() != left.Count)
return false;
//there is a key in the left dictionary that's not in the right dictionary
//if there are any keys in the right dictionary not in the left then either
//there is one in the left not in the right as well, or the counts won't have
//been equal, so we know the two key sets are equal.
var defaultValueComparer = EqualityComparer<TValue>.Default;
Func<TValue, TValue, bool> valueComparer;
if (typeof(TValue) is IEnumerable)
valueComparer = (first, second) => ((IList)first).SequenceEqual((IList)second);
else
valueComparer = (first, second) => defaultValueComparer.Equals(first, second);
foreach (var key in left.Keys)
{
if (!valueComparer(left[key], right[key]))
return false;
}
return true;
}
public static bool SequenceEqual(this IList first, IList second)
{
if (first.Count != second.Count)
return false;
IEnumerator iterator1 = first.GetEnumerator(),
iterator2 = second.GetEnumerator();
while (true)
{
bool next1 = iterator1.MoveNext();
bool next2 = iterator2.MoveNext();
// Sequences aren't of same length. We don't
// care which way round.
if (next1 != next2)
{
return false;
}
// Both sequences have finished - done
if (!next1)
{
return true;
}
if (!object.Equals(iterator1.Current, iterator2.Current))
{
return false;
}
}
}
有几点需要注意:
我没有将这两个集合作为“集合比较”,而是将它们作为序列比较。如果他们真的应该进行集合比较,那么他们首先应该是列表以外的其他东西更有意义。无论如何,如果这是一个重要的更改,您可以将我的SequenceEqual
方法的名称和实现修改为以下内容:
public static bool SetEquals(this IList first, IList second)
{
if (first.Count != second.Count)
return false;
return first.OfType<object>().Intersect(second.OfType<object>())
.Count() < first.Count;
}
不是确定如何比较foreach内部的值,而是在外面做它是有意义的;值的类型在循环中不会改变。确定比较函数将成为一次,然后一遍又一遍地调用它。代表们对此非常满意。
答案 3 :(得分:0)
不应该这样吗?
public class DictionaryEqualityComparer<TKey,TValue> : IEqualityComparer<Dictionary<TKey,TValue>>
{
public bool Equals( Dictionary<TKey , TValue> x , Dictionary<TKey , TValue> y )
{
bool unequal = x.Count != y.Count
|| x.Except( y ).Any() // this is probably redundant
|| y.Except( x ).Any() // but my caffiene titration is off this AM
;
return !unequal ;
}
public int GetHashCode( Dictionary<TKey , TValue> obj )
{
return obj.GetHashCode() ;
}
有几个原因。最大的一个是两个相同类型的词典,比如Dictionary<string,Widget>
可以使用不同的等式比较器来表示键。在字符串键的实例中,它可能是库存StringComparer
实现中的任何一个。这使“平等”的概念复杂化。