【发布时间】:2014-10-31 22:31:46
【问题描述】:
我有一小段代码比较 2 个变量的类型,然后如果它们相等或不相等则返回某个输出。代码如下:
public new bool Equals(object x, object y)
{
var xType = x.GetType();
var yType = y.GetType();
if (xType != yType) return false;
return GetPropertiesWithoutKey(xType).All(pd => Comparer.IsPropertyChanged(pd, x, y));
}
在调试时,我在'return GetPropertiesWithoutKey(...)' 上设置了一个断点,但是在它到达该行之后它不会越过它。即使在多次击中 F10 和 F5 之后。删除断点并按 F10 或 F5 后,我得到了 StackOverflow 异常。
有人知道为什么会这样吗?
欢迎提出问题、评论和建议。
亲切的问候
编辑 1:GetPropertiesWithoutKey(...) 的代码
private IList<PropertyDescriptor> GetPropertiesWithoutKey(Type entityType)
{
return _syncProperties ??
(_syncProperties = GetEntityTypeDescriptor(entityType).Properties.Where(el => !el.IsKey).ToList());
}
编辑 2:Comparer.IsPropertyChanged(...) 的代码
public static bool IsPropertyChanged(PropertyDescriptor pd, object entity1, object entity2)
{
object val1 = null;
object val2 = null;
if ((typeof(ICollection).IsAssignableFrom(pd.PropertyInfo.PropertyType)
&& entity1 != null
&& ((ICollection)entity1).Count != 0)
|| (!typeof(ICollection).IsAssignableFrom(pd.PropertyInfo.PropertyType)
&& entity1 != null))
{
val1 = entity1;
//val1 = pd.PropertyInfo.GetValue(entity1);
}
if ((typeof(ICollection).IsAssignableFrom(pd.PropertyInfo.PropertyType)
&& entity2 != null
&& ((ICollection)entity2).Count != 0)
|| (!typeof(ICollection).IsAssignableFrom(pd.PropertyInfo.PropertyType)
&& entity2 != null))
{
val2 = entity2;
//val2 = pd.PropertyInfo.GetValue(entity2);
}
if (val1 == null && val2 == null)
{
return false;
}
if (val1 == null || val2 == null)
{
return true;
}
if (typeof(ICollection).IsAssignableFrom(pd.PropertyInfo.PropertyType))
{
return IsCollectionChanged(pd, val1, val2);
}
if (!pd.PropertyInfo.PropertyType.IsPrimitive || !(pd.PropertyInfo.PropertyType == typeof(String)))
{
return IsComplexChanged(pd, val1, val2); //<-- Debugger gets here (EDIT 3)
}
if (val1 != null)
{
return !val1.Equals(val2);
}
else if (val2 != null)
{
return !val2.Equals(val1);
}
return false;
}
编辑 3:IsComplexChanged 的代码
private static bool IsComplexChanged(PropertyDescriptor pd, object val1, object val2)
{
var comparer = new EqualityComparer();
return !comparer.Equals(val1, val2); //<-- This line refers back to Equals function
}
正如您在上次编辑中看到的那样,我发现了循环的制作位置。
首先,函数 GetChangedProperties() 调用 Comparer.IsPropertyChanged,在 IsPropertyChanged 调试器中始终会到达 Comparer.IsComplexChanged,这指的是 Equals。 在 GetPropertiesWithoutKey(...) 中 Equals 的 lambda 表达式中,调用了 Comparer.IsPropertyChanged,然后创建循环。我已经写下了所采取步骤的时间表。
如果有人想看这个,尽管问,我会给它拍照。
我希望有人知道解决方案或可以帮助我开始解决问题,非常感谢您的帮助,因为我现在正在画一个空白。
欢迎任何进一步的问题
【问题讨论】:
-
发布
GetPropertiesWithoutKey的代码,它可能正在进行某种无限递归。 -
或 Comparer.IsPropertyChanged 使用调用它的 Equals 方法。
-
在许多编码语言中,Equals() 是一种现有方法。所以也许你覆盖了那个方法并继续调用它。尝试更改方法的名称。
-
它似乎不是它不会越过“GetPropertiesWithoutKey”行,而是你一次又一次地回到那里,可能是因为某些东西正在回调你的 equals 方法。使用断点按 F5 几次后,您应该能够查看堆栈跟踪并查看正在发生的循环。它可能是一个大循环或一个小循环。一旦你有了它,你就有希望找出什么是回调到你的 equals 并修复该代码。或者未能发布堆栈跟踪以供我们帮助调试。
-
嘿@Chris,我发现了循环的创建位置,我已将代码作为编辑放入问题中,以便每个人都可以清楚地看到。但是我的工作日快结束了,所以你可能要到早上才能再次收到我的消息:p