gpt4 book ai didi

c# - 通过动态 : . NET/C# 框架错误访问泛型类型成员时出现 StackOverflowException?

转载 作者:行者123 更新时间:2023-12-03 02:48:31 24 4
gpt4 key购买 nike

在程序中我使用 dynamic关键字调用最佳匹配方法。但是,我发现框架崩溃并显示 StackOverflowException在某些情况下。

我已尝试尽可能简化我的代码,同时仍然能够重现此问题。

class Program
{
static void Main(string[] args)
{
var obj = new SetTree<int>();
var dyn = (dynamic)obj;
Program.Print(dyn); // throws StackOverflowException!!
// Note: this works just fine for 'everything else' but my SetTree<T>
}
static void Print(object obj)
{
Console.WriteLine("object");
}

static void Print<TKey>(ISortedSet<TKey> obj)
{
Console.WriteLine("set");
}
}

如果新实例实现 ISortedSet<TKey>,该程序将通常打印“set”接口(interface)并为其他任何内容打印“对象”。但是,通过以下声明 StackOverflowException而是抛出(如上面的评论中所述)。

interface ISortedSet<TKey> { }

sealed class SetTree<TKey> : BalancedTree<SetTreeNode<TKey>>, ISortedSet<TKey> {}

abstract class BalancedTree<TNode>
where TNode : TreeNode<TNode> { }

abstract class SetTreeNode<TKey> : KeyTreeNode<SetTreeNode<TKey>, TKey> { }

abstract class KeyTreeNode<TNode, TKey> : TreeNode<TNode>
where TNode : KeyTreeNode<TNode, TKey> { }

abstract class TreeNode<TNode>
where TNode : TreeNode<TNode> { }

无论这是否是一个错误,StackOverflowException 都非常令人不安。被抛出,因为我们无法捕获它,也几乎无法提前确定是否会抛出异常(从而终止进程!)。

有人可以解释一下发生了什么事吗?这是框架中的错误吗?

当调试并切换到“反汇编模式”时,我看到了这个:

disassembly

在该位置注册转储: register dump

EAX = 02B811B4 EBX = 0641EA5C ECX = 02C3B0EC EDX = 02C3A504 ESI = 02C2564C
EDI = 0641E9AC EIP = 011027B9 ESP = 0641E91C EBP = 0641E9B8 EFL = 00000202

这只是告诉我这确实一定是框架中的某种错误。

我已经filed a bug report on Microsoft Connect但我有兴趣知道这里发生了什么。我的类声明在某种程度上不受支持吗?

不知道为什么会发生这种情况,这让我担心我们在其他地方使用 dynamic关键词。我可以完全不相信吗?

最佳答案

我创建了一个更短、更切题的SSCCE这说明了问题:

class Program
{
static void Main()
{
dynamic obj = new Third<int>();
Print(obj); // causes stack overflow
}

static void Print(object obj) { }
}

class First<T> where T : First<T> { }

class Second<T> : First<T> where T : First<T> { }

class Third<T> : Second<Third<T>> { }

查看调用堆栈,它似乎在 C# 运行时绑定(bind)程序中的两对符号之间跳跃:

Microsoft.CSharp.RuntimeBinder.SymbolTable.LoadSymbolsFromType(
System.Type originalType
)

Microsoft.CSharp.RuntimeBinder.SymbolTable.GetConstructedType(
System.Type type,
Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol agg
)

Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.SubstTypeCore(
Microsoft.CSharp.RuntimeBinder.Semantics.CType type,
Microsoft.CSharp.RuntimeBinder.Semantics.SubstContext pctx
)

Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.SubstTypeArray(
Microsoft.CSharp.RuntimeBinder.Semantics.TypeArray taSrc,
Microsoft.CSharp.RuntimeBinder.Semantics.SubstContext pctx
)

如果我不得不冒险猜测,您所进行的一些泛型类型约束嵌套已成功地使绑定(bind)器混淆,以递归方式遍历约束中涉及的类型以及约束本身。

继续在 Connect 上提交错误;如果编译器没有被这个问题捕获,运行时绑定(bind)器可能也不应该被捕获。

<小时/>

此代码示例运行正确:

class Program
{
static void Main()
{
dynamic obj = new Second<int>();
Print(obj);
}

static void Print(object obj) { }
}

internal class First<T>
where T : First<T> { }

internal class Second<T> : First<Second<T>> { }

这让我相信(对运行时绑定(bind)器的内部结构没有太多了解)它正在主动检查递归约束,但只有一层深。由于中间有一个中间类,绑定(bind)器最终不会检测到递归,而是尝试遍历它。 (但这只是一个有根据的猜测。我会将其作为附加信息添加到您的 Connect bug 中,看看是否有帮助。)

关于c# - 通过动态 : . NET/C# 框架错误访问泛型类型成员时出现 StackOverflowException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22672775/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com