StackOverflowException when accessing member of nested class via a dynamic reference

后端 未结 2 1688
被撕碎了的回忆
被撕碎了的回忆 2020-12-29 07:39

I have defined a generic class that derives from BindingList and has a nested non-generic class:

class Generic : BindingList.Inn         


        
相关标签:
2条回答
  • 2020-12-29 08:23

    Thank you very much for your correction! I investigated this I would say very interesting moment and found that I was right.

    First of all, this is not a BUG! This is just how the Microsoft team solved this issue. Again all what I wrote above I believe is true!

    So as I said you end up with an infinitive loop and get StackOverflow, but it seems to me that you get it very very fast. So no any long periods when you have no any access to your machine and just it looks like it's dead. I started digging deeper into the structure of BindingList and here the results.

    I created

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

    and in the main

    dynamic d = new Example<string>();
    var value = d.Name;
    

    and it works! Then I added another level

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

    and I got StackOverflow. I changed to

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

    and it works again!

    So I think that the guys from Microsoft just said ... so this is the max level after no way through and throw the exception.

    Now let's look at BindingList<T>

    public class BindingList<T> : Collection<T>, 
        IBindingList, IList, ICollection, IEnumerable, ICancelAddNew, 
        IRaiseItemChangedEvents
    

    Notice Collection<T>

    And look at List<T>

    public class List<T> : IList<T>, ICollection<T>, 
        IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
        IEnumerable
    

    Just interfaces....

    Therefore it works with List but not with BindingList!My example proves that!I believe they did it intentionally to stop infinitive looping.

    0 讨论(0)
  • 2020-12-29 08:30

    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!

    0 讨论(0)
提交回复
热议问题