0

In vb.net, I'm trying to create an extension to duplicate/reverse/merge stacks. Please note that it might exists already but I'm facing an issue.

I've a module, called utility.vb that hold a whole bunch of <Extension()> like the Duplicate that I'm trying to write.

''' <summary>
''' Duplicate a stack of object to another
''' </summary>
''' <typeparam name="T">Object type in the stack</typeparam>
''' <param name="s">Stack to duplicate</param>
''' <returns></returns>
<Extension()>
Public Function Duplicate(Of T)(ByVal s As Stack(Of T())) As Stack(Of T())
    Dim tmp As New Stack(Of T())
    For i As Integer = s.Count - 1 To 0 Step -1
        tmp.Push(s(i))
    Next
    Return tmp
End Function

I'm doing a various amount of Push in a Stack called labelStack. But when I call the Duplicate function from my code (because I need to re-use the same stack multiple times), it is not compiling (please note that the stack is made of own created object class)

Dim summaryStack As Stack(Of CCNode) = labelStack.Duplicate()

The error is "'Duplicate' is not a member of 'Stack(Of MyForm.CCNode)'"

I also tried to change the signature of the extension like so:

Public Function Duplicate(Of T As {New})(ByVal s As Stack(Of T())) As Stack(Of T())

But without any success.

Can someone help me (pointing out my mistake, correcting it or give me a way to achieve my need without writing the function myself)?

P.S.: I'm using Stack because I need to Pop in reverse order of my Push and it seemed appropriate.

Skippy
  • 19
  • 5
  • 1
    Based on your method declaration, you need to pass in a stack of arrays of T and you get back a stack of arrays of T. I doubt that that was what you wanted. See my answer for a correct declaration, assuming I understand your requirement. – jmcilhinney May 12 '20 at 09:46

1 Answers1

1

You're doing it all wrong. If you want to reuse or reverse or any such thing then you should not be creating a Stack(Of T) to start with. Create either an array or a List(Of T), depending on whether you want be able to adjust the content, and then you can create as many Stack(Of T) and Queue(Of T) objects as you want from that. Both of those classes have a constructor that accepts an IEnumerable(Of T) as an argument so you can pass your array or List(Of T) to as many of those constructors as you like, e.g.

Dim items = {1, 2, 3, 4}
Dim s1 As New Stack(Of Integer)(items)
Dim s2 As New Stack(Of Integer)(items.Reverse())
Dim q1 As New Queue(Of Integer)(items)
Dim q2 As New Queue(Of Integer)(items.Reverse())

That said, I just did this:

Imports System.Runtime.CompilerServices

Public Module StackExtensions

    <Extension>
    Public Function Copy(Of T)(source As Stack(Of T)) As Stack(Of T)
        Dim newStack As New Stack(Of T)

        For Each item In source.Reverse()
            newStack.Push(item)
        Next

        Return newStack
    End Function

End Module

and it worked exactly as you want. I expected the input stack to be empty after that, as I thought that enumerating a Stack(Of T) would pop each item but, apparently, it doesn't.

Actually, I just realised that that means that the Stack(Of T) constructor will accept another Stack(Of T) as an argument, which makes the extension method even simpler:

Imports System.Runtime.CompilerServices

Public Module StackExtensions

    <Extension>
    Public Function Copy(Of T)(source As Stack(Of T)) As Stack(Of T)
        Return New Stack(Of T)(source.Reverse())
    End Function

End Module

That's so simple that I don't think that an extension method is even worth bothering with.

All that said, I'd still go with the array or List(Of T) as a single source of truth and create all the stacks from that. That way you can't possibly pop an item before you've created all the copies you need.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • I'm used to List(Of ...) but never sure that it will keep my order of adding elements. I'll have a look at Queue(Of ...) too but it is FIFO when I needed LIFO. It is always interesting to learn a new container anyway. – Skippy May 12 '20 at 10:26
  • Given that you can access items in a `List(Of T)` by index, you can be sure that the order will remain consistent. I just mentioned `Queue` because it works similarly, not because you should necessarily use it in this case. – jmcilhinney May 12 '20 at 10:55