我有一小段代码可以比较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));
}
调试时我已经在断言上返回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是calles,然后创建循环。我已经写下了所采取措施的时间表。
如果有人想看到这个问题,我就会拍照。
我希望有人可能知道解决方案,或者可以帮助我开始解决问题,非常感谢您的帮助,因为我现在正在填补空白。
随时欢迎任何进一步的问题
答案 0 :(得分:1)
在
Equals
方法(或更高版本IsPropertyChanged
)内,您无法使用等于或其任何变体(==,!=) (因为它循环返回并导致堆栈溢出),但在这种情况下你只需要 与null
进行比较,你没有(我能想到的)需要比较 两个对象(你真的不需要你的自定义Equals)。因此对于 这些情况,只需使用object.ReferenceEquals
- 不会触发 关闭自定义Equals(它使用完全不同的路径)。
您只需处理实体!= null类型的检查(内部) - 通常使用object.ReferenceEquals
进行解决,例如
!object.ReferenceEquals(entity1, null)
而不是
entity1 != null
答案 1 :(得分:0)
我通过向IsPropertyChangedMethod添加深度参数来解决错误。现在错误不再发生,但我不确定我的代码现在是否正常工作,所以我会得到这个结论。
目前,以下是我为解决错误所做的更改:
<强> IsPropertyChanged:强>
public static bool IsPropertyChanged(PropertyDescriptor pd, object entity1, object entity2, int depth)
{
if (depth > 3) return false;
...
...
if (!pd.PropertyInfo.PropertyType.IsPrimitive || !(pd.PropertyInfo.PropertyType == typeof(String)))
{
return IsComplexChanged(pd, val1, val2, depth);
}
...
...
}
添加了参数并将其传递给IsComplexChanged
<强> IsComplexChanged:强>
private static bool IsComplexChanged(PropertyDescriptor pd, object val1, object val2, int depth)
{
var comparer = new ConexioEqualityComparer();
return !comparer.Equals(val1, val2, depth);
}
再次将参数传递给Equals
<强>等于:强>
public bool Equals(object x, object y, int depth)
{
var xType = x.GetType();
var yType = y.GetType();
if (xType != yType) return false;
return GetPropertiesWithoutKey(xType).All(pd => ConexioComparer.IsPropertyChanged(pd, x, y, ++depth));
}
添加增量并返回IsPropertyChanged