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

C# 通过动态引用访问嵌套类成员时的StackOverflowException,c#,generics,dynamic,C#,Generics,Dynamic,我定义了一个从BindingList派生的泛型类,该类具有嵌套的非泛型类: class Generic<T> : BindingList<Generic<T>.Inner> { public class Inner { public object Foo { get; set; } } } 这是我能做的最小的复制品 从BindingList派生是一个重要的细节,如果我将其更改为列表,程序将正确执行 为什么会发生这种情况

我定义了一个从BindingList派生的泛型类,该类具有嵌套的非泛型类:

class Generic<T> : BindingList<Generic<T>.Inner>
{
    public class Inner
    {
        public object Foo { get; set; }
    }
}
这是我能做的最小的复制品

从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)  

我认为问题出在这里

Generic<T> :BindingList<Generic<T>.Inner>
Generic:BindingList
请注意,您将声明的类用作父类绑定列表中的泛型参数。所以我相信反射只是以一个不定式循环结束,你会得到堆栈溢出

当你使用

var d = new Generic<string>.Inner();
dynamic d = new Generic<string>.Inner();
var d=new-Generic.Inner();
编译器只是将其替换为Generic.Inner 所以是一样的

Generic<string>.Inner d = new Generic<string>.Inner();
Generic.Inner d=新的Generic.Inner();
但是当你使用

var d = new Generic<string>.Inner();
dynamic d = new Generic<string>.Inner();
dynamic d=new-Generic.Inner();
你真的使用反射。再一次,反思开始在你的课堂结构中深入挖掘,就像。。。您的类=>BindingList=>BindingList的泛型参数=>您的类(因为它是BindingList的泛型参数)=>BindingList=>等等,直到您得到StackOverflow


您可以更改为
Generic:BindingList
来打破这个不定式循环,它就可以工作了

非常感谢您的更正!我调查了这个我会说非常有趣的时刻,发现我是对的

首先,这不是一个错误!这就是微软团队解决这个问题的方式。我相信我上面写的都是真的

就像我说的,你最终得到一个不定式循环,然后得到StackOverflow,但在我看来,你得到它的速度非常快。所以,当你无法访问你的机器时,它看起来就像死了一样。我开始深入研究BindingList的结构,这里是结果

我创造

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

public class Level1<T>
{

}
类示例:Level1
{
公共字符串Name=“111”;
}
公营一级
{
}
大体上

dynamic d = new Example<string>();
var value = d.Name;
dynamic d=新示例();
var值=d.名称;
而且它有效!然后我增加了另一个级别

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

}

public class Level2<T>
{

}
公共类级别1:Level2
{
}
公营二级
{
}
然后我就有多余的东西了。我改成

public class Level1<T> : Level2
{

}

public class Level2
{

}
公共类级别1:Level2
{
}
公营二级
{
}
它又起作用了

所以我想微软的人刚才说。。。因此,这是无法通过并引发异常后的最大级别

现在让我们看看
BindingList

公共类绑定列表:集合,
IBindingList、IList、ICollection、IEnumerable、ICancelAddNew、,
IRaiseItemChangedEvents
注意
收藏

然后查看
列表

公共类列表:IList、ICollection、,
IList、ICollection、IReadOnlyList、IReadOnlyCollection、IEnumerable、,
数不清
只是接口


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

所以嗯。。。您在调试时是否查看了实际堆栈以查看其无限递归的位置?看起来像是DLR中的错误…内部类型不是必需的
Generic:BindingList
也会复制它。我认为这是DLR中的一个bug,我认为它的出现是因为
BindingList
继承自
Collection
(而
List
继承自object)。请参阅,以了解我试图进行的最少修改。正如@MackieChan指出的,内部类型不是必需的。这是同一个bug吗?你是什么意思?BindingList不会中断!正如我所说,问题不在BindingList中,问题在BindingList中。因为通过使反射从泛型到BindingList,再到泛型,再到BindingList,可以创建一个不定式循环。因此,你的内存不足,并得到这个例外重新阅读操作。或只是尝试自己!如果您将其定义为
class-Generic:BindingList
它将中断,但如果您将其定义为
class-Generic:List
它将工作。造成这种差异的原因是什么?我得出了相同的结论:继承的泛型类型是问题所在。(为了防止你错过,我在OP上发了帖子。)但说“这不是一个bug”是一个大胆的说法。至少,它应该抛出类似于
NotSupportedException
的东西。我真的不知道。听着,我相信他们刚才说你所做的会导致StackOverflow异常,所以他们认为。它们只是防止您的机器出现故障和真正的堆栈溢出情况。不支持意味着不可能,但这不是真的。这是可能的,但它会杀死你的系统。同样,这是非常相对的,取决于设计师。但是你找到了一个追尾人!!!。DLR无法解析C#编译器可以解析的对象成员。更改嵌套级别会触发错误,但不会触发错误,这一事实表明DLR的类型/成员解析实现是多么脆弱。
public class List<T> : IList<T>, ICollection<T>, 
    IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
    IEnumerable