I set out to try to implement a type-safe Collection class. I use these
classes a lot with VB6; it's easier and safer to refer to, for instance, a
Demo object and a Demos collection than to a generic collection of objects.

My goal was to obtain a type-safe Demos collection with the usual functions:
Add, Remove, Clear, Contains, and which could be referred to by index or by
key, like it is in VB.

I tried to inherit from System.Collection.Bases.TypedCollectionBase and
found that this base class can not be referred to with keys, only int
indexes, and I that *had* to define indexers if I wanted the individual
elements to be referred to. Then I tried to use NamedObjectCollectionBase
which has references both with indexes or keys, but the GetEnumerator()
class of the base
stubbornly returns only generic Objects which refuse to be casted to Demo
objects. In short, to make it work I had to implement both an indexer and an
IEnumerator member class with the corresponding GetEnumerator function
(thank you very much, Gunnarson, for your book. I'd be lost without it).
Being that the case, what point does it have to inherit from a class if you
have to implement almost everything by yourself? And since (AFAIK) there are
no templates in C#, that means that whenever I want to define a type-safe
collection I have to write all this code.

I guess I should be wrong at some point, but I don't know where.

Add to this that whenever you type "this" trying to implement an indexer (or
the text cursor falls in ANY part of the definition of any indexer), the IDE
collapses. So I had to have the source file opened both in the IDE and in an
external editor at the same time, and be careful not to touch with the IDE
text
cursor any part of the source involving the indexers.

Here's the code for a Demo class and a Demos collection. If some of the
gurus around here can tell me what can I cut/substitute/simplify, I'll be
eternally grateful. In particular I feel to be a waste to have to redefine
an enumerator if I already have one in the base class (and the Current
function cannot be made to return anything but object). But if I have to
then, what's the point in inheriting from an existing, complex class?
Wouldn't it be leaner to use directly an Array, ListArray or some simpler
class?

The Demo class is just a simple demo object with two properties: Name and
Description. The Demos class is supposed to be a type-safed collection of
Demo objects, which could be referred to as

Demos[n] -> returns a Demo object
Demos[n].Name or Demos[n].Description -> return the properties of a member
of
the collection
Demos["key"] -> returns a Demo object
Demos["key"].Name... etc., the same as above.
This is mimicking the standard Collection object behavior in VB6.

Thanks in advance,
Marco.

namespace Amisys.Collections
{
using System;
using System.Collections;

/// <summary>
/// clsDemos is a collection of clsDemo objects.
/// </summary>
public class clsDemos : NameObjectCollectionBase , IEnumerable
{
public clsDemos() : base()
{
}
public new IEnumerator GetEnumerator()
{
return((IEnumerator) new DemosEnumerator(this));
}
class DemosEnumerator : IEnumerator
{
clsDemos Demos;
int idx;

public DemosEnumerator(clsDemos col)
{
Demos = col;
idx=-1;
}
public bool MoveNext()
{
idx++;
if(idx >= Demos.Count)
return false;
else
return true;
}
public void Reset()
{
idx=-1;
}
public object Current
{
get
{
return Demos[idx];
}
}
}
public clsDemo Add(clsDemo Demo)
{
base.BaseAdd(Demo.Name, Demo);
return Demo;
}
public clsDemo Add(string Name, string Description)
{
clsDemo Demo;
Demo = new clsDemo(Name, Description);
base.BaseAdd(Demo.Name, Demo);
return Demo;
}
public void Remove(clsDemo Demo)
{
base.BaseRemove(Demo.Name);
}
public void Remove(string Name)
{
base.BaseRemove(Name);
}
public void Remove(int index)
{
base.BaseRemove(index);
}
// Indexers for int and string indexes
public clsDemo this[int index]
{
get
{
return (clsDemo)base.BaseGet(index);
}
set
{
base.BaseSet(index,value);
}
}
public clsDemo this[string Name]
{
get
{
return (clsDemo)base.BaseGet(Name);
}
set
{
base.BaseSet(Name,value);
}
}
}
/// <summary>
/// clsDemo is a class which implements a sample Object just
different to a standard Object.
/// </summary>
public class clsDemo
{
private string m_Name;
private string m_Description;

//constructors
public clsDemo()
{
m_Name = "";
m_Description = "";
}
public clsDemo(string Name, string Description)
{
m_Name = Name;
m_Description = Description;
}
//properties
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
}
}
public string Description
{
get
{
return m_Description;
}
set
{
m_Description = value;
}
}
}
}