Instantiation of recursive generic types slows down exponentially the deeper they are nested. Why?

后端 未结 4 717
独厮守ぢ
独厮守ぢ 2020-12-13 04:11

Note: I may have chosen the wrong word in the title; perhaps I\'m really talking about polynomial growth here. See the benchmark

4条回答
  •  醉梦人生
    2020-12-13 04:56

    Is there a desperate need to have a distinction between the empty stack and the non-empty stack?

    From a practical point of view you can't pop the value of an arbitrary stack without fully qualifying the type and after adding 1,000 values that's an insanely long type name.

    Why not just do this:

    public interface IImmutableStack
    {
        T Top { get; }
        IImmutableStack Pop { get; }
        IImmutableStack Push(T x);
    }
    
    public class ImmutableStack : IImmutableStack
    {
        private ImmutableStack(T top, IImmutableStack pop)
        {
            this.Top = top;
            this.Pop = pop;
        }
    
        public T Top { get; private set; }
        public IImmutableStack Pop { get; private set; }
    
        public static IImmutableStack Push(T x)
        {
            return new ImmutableStack(x, null);
        }
    
        IImmutableStack IImmutableStack.Push(T x)
        {
            return new ImmutableStack(x, this);
        }
    }
    

    You can pass around any IImmutableStack and you only need to check for Pop == null to know you've hit the end of the stack.

    Otherwise this has the semantics you're trying to code without the performance penalty. I created a stack with 10,000,000 values in 1.873 seconds with this code.

提交回复
热议问题