我创建了一个词典,并尝试添加一些值。这些值是我们生成的代码的输入属性:
_inputParameterMapping = new Dictionary<IVariable, IExpression>();
我必须添加三个值,但是字典给我以下错误:
“具有相同键的项目已被添加”
当我比较这些值时,它们并不相等。 (请参阅附件1和2)。在附件中,您会看到两个键的 memberNames 彼此不同。
两个键的 HashCodes 彼此相等,但是对象不相等,并且Equals函数的结果为“ true”(请参阅附件3)
这是我的功能:
public StoredProcedureCall(IStoredProcedureDeclaration storedProcedure, params IExpression[] inputValues)
{
if (storedProcedure == null)
throw new ArgumentNullException("storedProcedure");
if (inputValues.Length > storedProcedure.InputParameters.Length)
throw new ArgumentException("inputValues length does not match function.InputParameters length");
_storedProcedure = storedProcedure;
_inputValues = inputValues;
_inputParameterMapping = new Dictionary<IVariable, IExpression>();
for (var i = 0; i < _inputValues.Length; i++)
{
if (!storedProcedure.InputParameters[i].ParameterType.IsInstanceOfType(_inputValues[i]))
{
throw new ArgumentException(string.Format("inputArgument {0} type ({1}) is not same as inputParameter '{2}' type ({3}) in stored procedure '{4}'",
i,
ReflectionUtils.GetTypeNameWithoutNameSpaceQualifiers(_inputValues[i].Type.GetType()),
storedProcedure.InputParameters[i].Template.MemberName,
ReflectionUtils.GetTypeNameWithoutNameSpaceQualifiers(storedProcedure.InputParameters[i].ParameterType),
_storedProcedure.MemberName));
}
_inputParameterMapping.Add(storedProcedure.InputParameters[i].Template, _inputValues[i]);
}
}
该问题怎么发生?为什么字典认为这些属性彼此相等?
谢谢你!
亲切的问候, 耶尔
答案 0 :(得分:0)
两个键的HashCode彼此相等
这是问题所在,因为
Dictionary类被实现为哈希表。 -MSDN
,并使用GetHashCode函数作为默认的哈希算法。
解决方案1
为您的IVariable实现覆盖GetHashCode(和Equal),并向其添加MemberName:
override int GetHashCode()
{
return base.GetHashCode() | MemberName.GetHashCode();
}
这是一个基本解决方案,将忽略IVariable接口的所有其他成员
解决方案2
如果类型TKey实现System.IEquatable通用接口,则默认的相等比较器将使用该实现
实现IEquatable界面
public bool Equals(IVariable other)
{
if(this.MemberName!= other.MemberName)
return false;
//... Compare other members ...
}
答案 1 :(得分:0)
它表明您在对象比较方面存在问题。您的方向员真的不知道如何比较您的关键对象。我建议实现IEqualityComparer并将其用于字典。看一下我的样本:
public static void DoStuff()
{
var one = new SomeClass(10);
var two = new SomeClass(200);
var three = new SomeClass(10); //same value as object "one"
var myComparer = new SomeClassComparer();
var myDictionary = new Dictionary<SomeClass, object>(myComparer);
myDictionary.Add(one, "Some Data");
myDictionary.Add(two, new[] { 1, 2, 3, 4 } );
// causes exceptions even if InitializationTime differs because of SomeClass.ImportantValue comparison
myDictionary.Add( three, new List<object>() );
}
public class SomeClass
{
public int ImportantValue { get; set; }
public DateTime InitializationTime { get; set; }
public SomeClass(int value)
{
ImportantValue = value;
//every object gets its "unique" InitializationTime
InitializationTime = DateTime.Now;
}
}
public class SomeClassComparer : IEqualityComparer<SomeClass>
{
public bool Equals(SomeClass x, SomeClass y)
{
//do comparison of data that represents the identity of the objects data
return x.ImportantValue.Equals(y.ImportantValue);
}
public int GetHashCode(SomeClass obj)
{
//calculate a hash code from data that represents the identity of the objects data
return (obj.ImportantValue).GetHashCode();
}
}