//
you're reading...
.NET 2.0

I’m in love with generics

Out of boredom, and a need to create something with the next VS.NET I decided I’d revive my MUD project again.

For those not familiar with them, MUDs were basically the first MMORPG but they are more along the lines of Zork than Everquest.

When you deal with items or monsters in a room you typically refer to them by some keyword, but what happens if there are multiples of that item or monster in the room (or on your person)? In the muds I’ve played you typically type something like item.number where number is like an index into an array of that item type or if you’re telling it to do something to all of the items then number can also be “all”.

But what is the best way to organize this in memory?

I’ve decided to group them in a hash table using the item template as the key and a List of the item as the value. So how does one go about implementing this?

The old way would require me to do a lot of copy and pasting or implement everything with objects and cast everything.

Instead its only a few lines of code:

Click more to see the code and an explaination.

public interface ITemplate<TemplateFor>
{
  TemplateFor CreateInstance();
}

public interface ITemplateInstance<TemplateOf>
{
  TemplateOf Template { get; }
}

This basically sets up two interfaces, one will be applied to the Template type, and the other will represent an instance of that template with the Instance type having a reference to its template.

public class TemplateCollection<Template, Instance> :
  Dictionary<Template, List<Instance>>
  where Template : ITemplate<Instance>
  where Instance : ITemplateInstance<Template>

This defines a new generic class that is based on two types a Template type and an Instance type, it inherits from the generic Dictionary type using the Template as a key and a List of Instance objects as the value. Following that are two constraints, the Template type must implement ITemplate<Instance> and Instance must implement ITemplateInstance which provides a reference back to its template through the Template property.

public void Add( Instance inst )
{
  if( this [inst.Template] == null )
  {
    this [inst.Template] = new List<Instance>();
  }

  this [inst.Template].Add( inst );
}

This method will add a new instance of the Template type to the collection, creating a new List of the Instance type if needed. Notice that I can use the Template property on the instance because that is defined on the ITemplateInstance interface, one of the constraints placed on it. With ITemplateInstance implemented it provides a strongly typed reference back to the template so it all continues to work!

public void Remove( Instance inst )
{
  if( this [inst.Template] == null )
    return;

  List<Instance> list = this [inst.Template];

  list.Remove( inst );

  if( list.Count == 0 )
  {
    this.Remove( inst.Template );
  }
}

This code will remove a specific instance from the collection. First it ensures that an item of that template type exists then calls remove on the List if it does. Finally if no more instances are in the list it removes the entire template from the hash table to free up some memory.

public Instance this [Template template, int index]
{
  get
  {
    List<Instance> list = this [template];

    if( list == null )
      return Instance.default;

    if( list.Count > index )
      return Instance.default;

    return list [index];
  }
}

More of the same here, the only new part is that rather than returning null, which is illegal since I don’t know at compile time whether Instance with be a reference type or a value type. Instead I use a pseudo-property that only exists in generics, default which returns null for reference types and an empty value for value types.

There you go, I get to exhaust my adrenaline from writing that code and you get to learn something new about generics in .NET 2.0 w/ C#.

Update: I suppose it helps if I actually mention why this is good. Now instead of having to either cast a lot or duplicate lots of code I can use my new TemplateCollection to create collections of templates like so:

TemplateCollection<ItemTemplate, Item> items = 
  new TemplateCollection<ItemTemplate, Item>();

// Add new item to room
items.Add( itemTemplate, itemTemplate.CreateInstance() );

// Player wants 3rd instance of itemTemplate
itemInstance = items[itemTemplate, 2];

// Player picked up item, remove from collection
items.Remove( itemInstance );

// Player wants the rest of the items as well
// return a collection of items
List<Item> itemList = items[itemTemplate];

Because of that ease it will eliminate errors from my code and I can save time by not having to type a ton of casts nor do a lot of copy, paste, replace operations (the replace portion could then cause problems unless I do it by hand).

Advertisements

About James

I am a Senior Developer/Consultant for InfoPlanIT, LLC. I previously spent over 7 years as a Product Manager for what eventually became ComponentOne, a division of GrapeCity. While there, I helped to create ActiveReports 7, GrapeCity ActiveAnalysis, and Data Dynamics Reports.

Discussion

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archive

%d bloggers like this: