I have defined a generic class that derives from BindingList and has a nested non-generic class:
class Generic<T> : BindingList<Generic<T>.Inner>
{
public class Inner
{
public object Foo { get; set; }
}
}
A StackOverflowException
occurs in mscorlib when attempting to access the Value
property via a dynamic reference like so:
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
This is the smallest reproduction i was able to make.
Deriving from BindingList is an important detail, if i change it to a List
the program executes correctly.
Why does this happen?
Edit:
This is the top of the call stack:
[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)
I think the problem is in this place
Generic<T> :BindingList<Generic<T>.Inner>
Notice you use the declared class as a generic parameter in the parent class BindingList. So I believe reflection just ends up with an infinitive loop and you get StackOverflow.
When you use
var d = new Generic<string>.Inner();
compiler just replaces it with Generic.Inner so it is the same like
Generic<string>.Inner d = new Generic<string>.Inner();
But when you use
dynamic d = new Generic<string>.Inner();
You really use reflection. Again reflection starts digging deeper in your class structure and it goes like... your class => BindingList = > generic parameter of BindingList => your class(because it's a generic parameter of BindingList) = > BindingList = > and so on until you get StackOverflow.
You can change to Generic<T> : BindingList<string>
to break this infinitive loop and it works!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With