C# - 使用Lambda的System.StackOverflowException

时间:2010-05-06 20:43:02

标签: c# .net lambda sorting stack-overflow

在什么情况下,此代码会因System.StackOverflowException而出错?

Accounts.Sort((x, y) => string.Compare(x.AccountId, y.AccountId));

更新
该财产写为:

    public string AccountId
    {
        get { return _accountId; }
        set { _accountId = value; }
    }

根本没什么特别的。排序也不会被覆盖。

6 个答案:

答案 0 :(得分:5)

查看callstack,您将看到一遍又一遍地执行哪个函数。如果这不可能(因为它在生产环境中运行),请提供更多信息。

关于被调用属性调用的内容,调用此函数的位置等

答案 1 :(得分:5)

如果AccountId做了一件非常重要的事情(任何除了访问本地字段外),那么这是最有可能的赌注。

一个有趣的事实是技术上 Sort要求排序是可传递的,字符串比较是not always transitive!但这很少会导致堆栈溢出(除非Sort方法使用某种FP方法); 可能导致它永远运行,但我相信内置类型甚至覆盖了它们(它们检查理论上的最大游程长度和中止,IIRC)。

我会看AccountId;如果它做了“聪明”的事情(比如从父集合中加载一些值),那么错误就是“聪明”。

答案 2 :(得分:5)

所以我遇到了一个棘手的情况,我在比较方法中得到了StackOverflow异常。

我的比较方法:

public bool Equals(Type rhs)
{
    if (rhs == null) return false;
    if (this == rhs) return true;

    return this.randomField.Equals(rhs.randomField);
}

我的接线员:

public static bool operator ==(Type lhs, Type rhs)
{
    if (lhs == null)
        return (rhs == null);
    else
        return lhs.Equals(rhs);
}

所以,发生的是==运算符调用Equals方法,然后在运行行this == rhs时调用==运算符。解决方案是将行转换为Object.ReferenceEquals(this, rhs)

答案 3 :(得分:4)

这是一个不可思议的想法:

帐户是否已宣布List<Account>

我想知道Accounts是否是一个声明为List<Account>之外的属性 - 例如,IList<Account> - 并且你有一个带有{的某个静态助手类{1}}未正确实施的扩展方法。当传入的参数为Sort时,这可能会尝试利用List<T>.Sort方法,但不会对List<T>执行必要的转换,从而产生保证List<T>

我的意思是这个。假设StackOverflowException是某个类的属性,看起来像这样:

Account

然后假设其他地方你有这个带有public class AccountManager { public IList<Account> Accounts { get; private set; } public AccountManager() { // here in the constructor, Accounts is SET to a List<Account>; // however, code that interacts with the Accounts property will // only know that it's interacting with something that implements // IList<Account> Accounts = new List<Account>(); } } 扩展方法的静态类:

Sort

在这种情况下,您发布的代码会抛出public static class ListHelper { public static void Sort<T>(this IList<T> list, Comparison<T> comparison) { // programmer tries to use the built-in sort, if possible if (list is List<T>) { // only problem is, list is here still typed as IList<T>, // so this line will result in infinite recursion list.Sort(comparison); // the CORRECT way to have done this would've been: // ((List<T>)list).Sort(comparison); return; } else { list.CustomSort(comparison); return; } } private static void CustomSort<T>(this IList<T> list, Comparison<T> comparison) { // some custom implementation } }


原始答案:

也许StackOverflowException是自定义集合类的对象,其Accounts方法调用自身?

Sort

也许public class AccountCollection : IEnumerable<Account> { // ... public void Sort(Comparison<Account> comparison) { Sort(comparison); // infinite recursion } // ... } 属性会自行调用?

AccountId

答案 4 :(得分:2)

StackOverflowException通常发生在你有一个疯狂的递归调用时。检查SortAccountId是否在调用自己。如果是这样,请检查这些递归函数的基本情况,并确保它们在它们应该停止时停止。

答案 5 :(得分:2)

仅仅因为此行抛出StackOverflow并不意味着它是导致问题的原因,例如。

void methodA()
{
   b();
   methodA();
}

这很可能在b()上获得堆栈溢出,因为它是对methodA()的递归调用;

我怀疑递归是围绕这行代码的方法。