通过动态引用访问嵌套类的成员时出现StackOverflowException

err*_*404 16 c# generics dynamic

我已经定义了一个派生自BindingList的泛型类,并且有一个嵌套的非泛型类:

class Generic<T> : BindingList<Generic<T>.Inner>
{
    public class Inner
    {
        public object Foo { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

StackOverflowException当尝试Value通过动态引用访问属性时,mscorlib中出现A ,如下所示:

dynamic d = new Generic<string>.Inner();
var value = d.Foo; // StackOverflowException

var value = d.Bar    // StackOverflowException as well, not a 
                     // 'RuntimeBinderException' like you would expect when
                     // trying to access a non-existing member
Run Code Online (Sandbox Code Playgroud)

这是我能够制作的最小的复制品.

如果我将其更改List为程序正确执行,则从BindingList派生是一个重要的细节.

为什么会这样?

编辑:

这是调用堆栈的顶部:

[Managed to Native Transition]  
mscorlib.dll!System.RuntimeTypeHandle.Instantiate(System.Type[] inst)   
mscorlib.dll!System.RuntimeType.MakeGenericType(System.Type[] instantiation)    
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.CType.CalculateAssociatedSystemTypeForAggregate(Microsoft.CSharp.RuntimeBinder.Semantics.AggregateType aggtype)   
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.CType.CalculateAssociatedSystemType(Microsoft.CSharp.RuntimeBinder.Semantics.CType src)   
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.CType.AssociatedSystemType.get()  
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.GetAggregate(Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol agg, Microsoft.CSharp.RuntimeBinder.Semantics.AggregateType atsOuter, Microsoft.CSharp.RuntimeBinder.Semantics.TypeArray typeArgs)  
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.GetAggregate(Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol agg, Microsoft.CSharp.RuntimeBinder.Semantics.TypeArray typeArgsAll)    
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.GetAggregate(Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol agg, Microsoft.CSharp.RuntimeBinder.Semantics.TypeArray typeArgsAll)    
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.SubstTypeCore(Microsoft.CSharp.RuntimeBinder.Semantics.CType type, Microsoft.CSharp.RuntimeBinder.Semantics.SubstContext pctx)    
Microsoft.CSharp.dll!Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.SubstTypeArray(Microsoft.CSharp.RuntimeBinder.Semantics.TypeArray taSrc, Microsoft.CSharp.RuntimeBinder.Semantics.SubstContext pctx)  
Run Code Online (Sandbox Code Playgroud)

小智 1

非常感谢您的指正!我对此进行了调查,我想说这是非常有趣的时刻,发现我是对的。

首先,这不是BUG!这就是微软团队解决这个问题的方法。我再次相信我上面写的都是真的!

正如我所说,你最终会得到一个不定式循环并得到 StackOverflow,但在我看来,你得到它的速度非常非常快。因此,不会有很长一段时间你无法访问你的机器,而它看起来就像死了一样。我开始深入研究 BindingList 的结构,这里是结果。

我创建

class Example<T> : Level1<Example<T>>
{
    public string Name = "111";
}

public class Level1<T>
{

}
Run Code Online (Sandbox Code Playgroud)

并在主要

dynamic d = new Example<string>();
var value = d.Name;
Run Code Online (Sandbox Code Playgroud)

它有效!然后我添加了另一个级别

public class Level1<T> : Level2<T>
{

}

public class Level2<T>
{

}
Run Code Online (Sandbox Code Playgroud)

我得到了 StackOverflow。我改为

public class Level1<T> : Level2
{

}

public class Level2
{

}
Run Code Online (Sandbox Code Playgroud)

它又起作用了!

所以我认为微软的人刚刚说过......所以这是在没有办法通过并抛出异常后的最高级别。

现在让我们看看BindingList<T>

public class BindingList<T> : Collection<T>, 
    IBindingList, IList, ICollection, IEnumerable, ICancelAddNew, 
    IRaiseItemChangedEvents
Run Code Online (Sandbox Code Playgroud)

注意Collection<T>

看看List<T>

public class List<T> : IList<T>, ICollection<T>, 
    IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
    IEnumerable
Run Code Online (Sandbox Code Playgroud)

只是接口....

因此它适用于 List,但不适用于 BindingList!我的例子证明了这一点!我相信他们故意这样做是为了停止不定式循环。

  • 我得出了同样的结论:继承的泛型类型就是问题所在。(我在OP上发布了[这个要点](https://gist.github.com/default-kramer/7239781)以防你错过它。)但是说“这不是一个错误”是一个大胆的主张。至少,它应该抛出类似“NotSupportedException”的内容。 (2认同)