Click here to Skip to main content
15,888,968 members
Articles / Programming Languages / C++/CLI
Article

A linked list collection class in MC++

Rate me:
Please Sign up or sign in to vote.
1.00/5 (1 vote)
24 Jun 20022 min read 248.9K   1.6K   17   53
The .NET ArrayList class provides "dynamic arrays" which, to a C++ programmer should seem really innane. Here's a linked list collection class that can be used in any .NET language.

Introduction

If you examine the functionality of the ArrayList class, you'll find that it's quite ridiculous. When the array reaches maximum capacity, it creates a new array with double the capacity, copies the items from the old array into the new one and discards the old array. Convoluted and messy.

Every C/C++ programmer knows that the only way to make structures that are 'really' dynamic is to use linked lists. I've created a class in Managed C++ that does just that. Furthermore, I've included a TypedListBase abstract class from which you can inherit to make strongly typed collections. All this is put into a .NET dll and I've a program, written in C# that I used to test it.

The classes really don't do anything more than implement the IList, ICollection, IEnumerable and ICloneable. Therefore, it behaves identically to ArrayList as far as the programmer who's using it is concerned. I'm not getting into the details of the methods and properties of these interfaces here, but they're pretty straight-forward and self-explanatory, and the .NET Framework reference explains them quite well.

Implementing LinkedList

The LinkedList class maintains a linked list of LinkedListNode structures shown below:

MC++
__nogc struct LinkedListNode
{
    LinkedListNode __nogc* pNext;
    LinkedListNode __nogc* pPrev;
    gcroot<object*> item; // #include <vcclr.h> in StdAfx.h  
                          // makes this template available.
};

LinkedListNode::item stores the objects. The gcroot template is required to hold a managed object in an unmanaged struct/class.

The linked list class includes the following items, besides a constructor, destructor and the interface implementations:

MC++
public __gc __sealed class LinkedList : public IList, 
    public IEnumerable, public ICollection, public ICloneable
{
// Implementation
private:
    LinkedListNode __nogc* m_pHead;
    // Future versions will support reverse enumeration, 
    // like the STL classes.
    // Therefore, we need to store the tail as well.
    LinkedListNode __nogc* m_pTail;
    int m_count;
    // Used by the enumerator to check 
    // whether the list is modified after the
    // enumerator has been created.
    int m_version;	

    LinkedListNode* GetNodeAt(int index);
public:
    int GetVersion();

. . .
. . .

Implementing the enumerator

The code for LinkedList::GetEnumerator is:

MC++
IEnumerator* LinkedList::GetEnumerator()
{
    return new LinkedListEnumerator(this, m_pHead);
}

This class requires a pointer to the list it's working on and a pointer to the head. The class declaration is given below:

MC++
private  __gc __sealed class LinkedListEnumerator : public IEnumerator
{
// Implementation
private:
    LinkedList* m_list;
    LinkedListNode* m_pNode;
    LinkedListNode* m_pHead;
    int m_version;
public:
    LinkedListEnumerator(LinkedList* list, LinkedListNode* pHead);
    // Overrides of IEnumerator
public:
    __property Object* get_Current();
    bool MoveNext();
    void Reset();
};

The constructor calls list->GetVersion() and stores the return value in m_version. This number represents the state of the list when the enumerator is created. When the list is modified (by calling Add, Remove, Clear, etc.) the version is incremented. The IEnumerator functions check to make sure that the stored version and the current version are the same:

MC++
if (m_version != m_list->GetVersion())
    throw new InvalidOperationException(
        S"The list was modified after the enumerator was created.");

If the list is modified after the enumerator is created, there is a chance that LinkedListEnumerator::m_pNode and m_pHead are invalid, so the exception is thrown. This is really stretching it, but if the list is modified over 4 billion times (I think that's the capacity of an int), there will be an overflow. Well, this is how Microsoft implemented this behavior in ArrayList.

Testing the DLL with the program

Check out the program I've included. It has a GUI and lets you add strings to the list one by one and can add 500 random strings as well. It tests all the functions and lets you enumerate through the list using multiply threads. Try adding items while some threads are enumerating. They will throw InvalidOperationException, but an enumerator created after the items were added will run 'peacefully.'

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalhmmm.... Pin
sultan_of_6string21-Jun-02 18:25
sultan_of_6string21-Jun-02 18:25 
GeneralRe: hmmm.... Pin
Christian Graus21-Jun-02 19:37
protectorChristian Graus21-Jun-02 19:37 
GeneralRe: hmmm.... Pin
Rama Krishna Vavilala22-Jun-02 1:57
Rama Krishna Vavilala22-Jun-02 1:57 
GeneralRe: hmmm.... Pin
Christian Graus22-Jun-02 2:21
protectorChristian Graus22-Jun-02 2:21 
GeneralRe: hmmm.... Pin
Heath Stewart9-Jul-03 5:26
protectorHeath Stewart9-Jul-03 5:26 
GeneralProblems that are not very obvious Pin
21-Jun-02 16:37
suss21-Jun-02 16:37 
GeneralRe: Problems that are not very obvious Pin
22-Jun-02 18:26
suss22-Jun-02 18:26 
GeneralArrayList is actually efficient Pin
Oz Solomon21-Jun-02 16:16
Oz Solomon21-Jun-02 16:16 
GeneralRe: ArrayList is actually efficient Pin
Christian Graus21-Jun-02 16:43
protectorChristian Graus21-Jun-02 16:43 
GeneralRe: ArrayList is actually efficient Pin
24-Jun-02 5:58
suss24-Jun-02 5:58 
GeneralStandard Template Library Pin
Rodolfo Lima21-Jun-02 7:20
Rodolfo Lima21-Jun-02 7:20 
GeneralRe: Standard Template Library Pin
William E. Kempf21-Jun-02 7:56
William E. Kempf21-Jun-02 7:56 
GeneralRe: Standard Template Library Pin
Christian Graus21-Jun-02 15:28
protectorChristian Graus21-Jun-02 15:28 
GeneralRe: Standard Template Library Pin
sultan_of_6string21-Jun-02 15:32
sultan_of_6string21-Jun-02 15:32 
GeneralRe: Standard Template Library Pin
Christian Graus21-Jun-02 15:41
protectorChristian Graus21-Jun-02 15:41 
GeneralRe: Standard Template Library Pin
sultan_of_6string21-Jun-02 15:49
sultan_of_6string21-Jun-02 15:49 
GeneralRe: Standard Template Library Pin
Jörgen Sigvardsson8-Aug-02 23:21
Jörgen Sigvardsson8-Aug-02 23:21 
GeneralRe: Standard Template Library Pin
Nish Nishant21-Jun-02 15:52
sitebuilderNish Nishant21-Jun-02 15:52 
GeneralRe: Standard Template Library Pin
Christian Graus21-Jun-02 15:55
protectorChristian Graus21-Jun-02 15:55 
GeneralRe: Standard Template Library Pin
Rama Krishna Vavilala21-Jun-02 15:59
Rama Krishna Vavilala21-Jun-02 15:59 
GeneralRe: Standard Template Library Pin
Nish Nishant21-Jun-02 16:00
sitebuilderNish Nishant21-Jun-02 16:00 
GeneralRe: Standard Template Library Pin
Rama Krishna Vavilala21-Jun-02 16:17
Rama Krishna Vavilala21-Jun-02 16:17 
GeneralRe: Standard Template Library Pin
Christian Graus21-Jun-02 16:46
protectorChristian Graus21-Jun-02 16:46 
GeneralRe: Standard Template Library Pin
Nish Nishant21-Jun-02 18:48
sitebuilderNish Nishant21-Jun-02 18:48 
GeneralRe: Standard Template Library Pin
Christian Graus21-Jun-02 16:40
protectorChristian Graus21-Jun-02 16:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.