代码似乎没有传递某一行,导致StackOverflowException

时间:2014-10-30 11:09:31

标签: c# linq

我有一小段代码可以比较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
    }

正如您在上一次编辑中所看到的,我已经找到了循环的位置。

首先,一个函数Ge​​tChangedProperties()调用Comparer.IsPropertyChanged,在IsPropertyChanged调试器中总是调到Comparer.IsComplexChanged,这指的是Equals。 在GetPropertiesWithoutKey(...)中的Equals中的lambda表达式中,Comparer.IsPropertyChanged是calles,然后创建循环。我已经写下了所采取措施的时间表。

如果有人想看到这个问题,我就会拍照。

我希望有人可能知道解决方案,或者可以帮助我开始解决问题,非常感谢您的帮助,因为我现在正在填补空白。

随时欢迎任何进一步的问题

2 个答案:

答案 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