RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Basic Generics for .Net 2.0

mordero

Knight
Basic Generics for .Net 2.0

With .net 2.0 (and thus RunUO 2.0), we are now able to use generics in our code. When it comes to scripting for RunUO, we will usually only use a List or a Dictionary.

Note
You need this at the top of your script:
Code:
using System.Collections.Generic;

Lists
A generic list works a lot like an arraylist, only it is type-safe (it will only allow objects of the same type to be added to it).

This example will create a list of strings.
Code:
List<string> m_Strings = new List<string>();
So, when you try to compile this, the compiler will check to make sure that any object that is being added to this list is a string.

Following from that last example, we will now add a string to this list.
Code:
string s = "Hello World!";
m_Strings.Add(s);
//m_Strings now contains string s

However, if you were to try to add an integer to the list, the compiler would throw an error and wouldnt compile your code.
Code:
int i = 7;
m_Strings.Add(i);
//will NOT compile!!

This is nice because now you never have to worry about throwing an exception at runtime due to you trying to work with the wrong type of object (which could happen when working with ArrayLists).

A useful property of lists is Count. Count will return the number of items currently in the list.
Code:
List<string> m_Strings = new List<string>();
m_Strings.Add("Hello");
//m_Strings.Count returns 1
m_Strings.Add("Word!");
//m_Strings.Count returns 2

A generic list provides many methods that you can use in order to work with the items in it. Some of the more help ones include Find, FindAll, Exists, Add, Remove, Contains, Clear, ForEach, and Insert.

The following will be used for the examples
Code:
List<Person> People = new List<Person>();
People.Add(new Person("Eric", 20));
People.Add(new Person("Kyle", 19));
People.Add(new Person("Brian", 20));
People.Add(new Person("Mike", 30));
People.Add(new Person("Bob", 25));
People.Add(new Person("George", 40));
People.Add(new Person("Jim", 20));
People.Add(new Person("Todd", 30));
 
//People.Count returns 8
 
//the class that we will be using
class Person
{
     private string m_name;
     public string Name
     {
          get { return m_name; }
          set { m_name = value; }
     }
     private int m_age;
     public int Age
     {
          get { return m_age; }
          set { m_age = value; }
     }
     public Person(string name, int age)
     {
          m_name = name;
          m_age = age;
     }
}

**Some of these methods may be a bit hard to understand how they work, but just look at them piece by piece and you will get it. This is mostly for those methods that I am using the key word delegate in. This is because there is a somewhat simpler way of doing some of these things, but by using delegate, you cut down on your code and once you understand it, it truly makes it easier to understand.**

List.Add
Will add an object to the end of a list.

The following will add a Person to People.
Code:
Person p = new Person("Bill", 45);
People.Add(p);

List.Insert
Insert is very similar to Add, except you can choose where in the list you want to add the object.

This will add a person to the 2nd spot in the list.
Code:
People.Insert(1, new Person("Bill", 45));

List.Remove
Will remove the object from the list.

The following will add and then remove the object from the list.
Code:
Person p = new Person("Bill", 45);
People.Add(p);
//People now contains the Person p
People.Remove(p);
//Person p has been removed from People

List.Clear
This will remove every object from the list, thus clearing everything

This code will clear the List People
Code:
People.Clear();

List.Find
This will search the list for an object that meets the conditions and returns the first one found.

The following code will search People for a Person named "Eric" and return that Person.
Code:
Person person = People.Find(delegate(Person p) {//Person p represents all of the Person items inside of the list
     if (p.Name == "Eric")
     {
          return true;//if the Person p item's name is Eric, then return true. When it returns true, this means that this Person meets the conditions specified (in this case, Name == "Eric")
     }
     else
     {
          return false;//this Person p does not meet the requirements
     }
});

List.FindAll
This will search the list for any objects that meet the conditions and returns a new list containing those objects.

The following code will search People for Persons with the age of 20.
Code:
List<Person> persons = People.FindAll(delegate(Person p) {//Person p represents all of the Person items inside of the list
     if (p.Age == 20)
     {
          return true;//if the Person p item's age is 20, then return true. When it returns true, this means that this Person meets the conditions specified (in this case, Age == 20)
     }
     else
     {
          return false;//this Person p does not meet the requirements
     }
});
As you can see this is identical in usage to Find, but it now returns a List<Person> instead of just a single Person

List.Exists
This will search the list for an object that meets the conditions and return true or false if it finds one (or more).

The following code will check to see if a Person with the age of 21 exists in the list.
Code:
bool exists = People.Exists(delegate(Person p) {//Person p represents all of the Person items inside of the list
     if (p.Age == 20)
     {
          return true;
     }
     else
     {
          return false;
     }
});
//returns false
Again, this is identical in usage to Find and FindAll, but returns a bool. Quite easy, right?

List.Contains
Similar to Exists, but there is no need to use a delegate since it takes an object as its parameter. If the type is not a value type, it must be the exact object (or a copy of it) if you wish to see if it is contained in People. So it cannot be a new object with the same properties, etc as the one you are looking for.

The following will add a Person to the list and then check if it is contained in it.
Code:
Person p = new Person("Bill", 45);
People.Add(p);//add it to People
bool b = People.Contains(p); 
//b is true
People.Remove(p);//Remove it from People
b = People.Contains(p);
//b is false


List.ForEach
Will iterate through the list.

This will loop through People and write out each Person's name
Code:
 People.ForEach(delegate(Person p)
{
     Console.WriteLine(p.Name);
});

Well thats pretty much it for lists, they are quite simple to use and provide type safety at compile time which would prevent any exceptions from being throw at runtime (which is nice :)) while also provide many methods for you to use to make your life easier.

Dictionary
Dictionaries are very similar to lists, except instead of having to use an int as your key, you are now able to specify your own type for the key. So you could use a string, int, Mobile, etc for your key. You could even use a bool but that would limit your Dictionary to only 2 KeyValuePairs. The key MUST be unique in the collection, while the values can be the same.

Dictionary also contains the Count property. Count does the same thing that it did for Lists and will return the total number of items in the dictionary.

Overall, I find dictionaries more difficult to work with and usually you wont need to use them. However, when you do, here are some of the more useful methods for dictionaries: Add, Remove, Clear, ContainsKey, ContainsValue.

Sadly, there is no foreach method contained in a dictionary, but it is not too difficult to iterate through one.

The following will be used in the examples. I will just be using the person name as their key because I am lazy.
Code:
Dictionary<string,Person> People = new Dictionary<string,Person>();
People.Add("Eric", new Person("Eric", 20));
People.Add("Bill", new Person("Bill", 21));
 
//the class that we will be using
class Person
{
     private string m_name;
     public string Name
     {
          get { return m_name; }
          set { m_name = value; }
     }
     private int m_age;
     public int Age
     {
          get { return m_age; }
          set { m_age = value; }
     }
     public Person(string name, int age)
     {
          m_name = name;
          m_age = age;
     }
}

Dictionary.Add
Just as in lists, this will add a new object to the collection.

The following will add a new Person to People
Code:
People.Add("Joe", new Person("Joe", 25));

Dictionary.Remove
Same as with lists, this will remove the object from the collection. It takes the key as its parameter. It will return true if the object was found and removed or false if it wasnt found (and thus not removed).

The following will remove Joe from the collection.
Code:
People.Remove("Joe");

Dictionary.Clear
Same as the list method, this will clear the collection.

The following removes every object from People
Code:
People.Clear();

Dictionary.ContainsKey
Determines if the specified key is in the collection. If the key is not a value type, it must be the same object or a copy of it.

The following will check if there is an KeyValuePair with Eric as the key
Code:
People.ContainsKey("Eric");//would return true

Dictionary.ContainValue
Determines if the specified value is in the collection. If the value is not a value type, it must be the same object or a copy of it.

The following will add a Person p to the dictionary, see if it is contained, remove it, and check again
Code:
Person p = new Person("Bill", 45);
People.Add("Bill", p);
bool b = People.ContainsValue(p);//returns true
People.Remove("Bill");
b = People.ContainsValue(p);//returns false

Iterating through a Dictionary
To loop through a dictionary, the easiest way is to use a KeyValuePair like such.
Code:
 foreach(KeyValuePair<string,Person> kvp in People)
{
     kvp.Key; //returns the key
     kvp.Value;//returns the value
}
As you can see the KeyValuePair is similar to a dictionary as it needs a key and a value type, which must be the same as the dictionary you are iterating through.

Conclusion
Although generics offer much much more for you to use, when it comes to RunUO, lists and dictionaries are the majority of what you will need to use. Now that you know some of the methods that come with each, it will hopefully make it much easier for you to work with some of changes between RunUO 1.0 and RunUO 2.0. Good luck!!!

Notes:
A value type is one of the following: char, Int16, Int32 (int), Int64, bool, etc.
A reference is everything else (including strings and user defined classes).

Resources:
http://msdn2.microsoft.com/en-us/library/system.collections.generic.aspx

If you find any errors, please be sure to point them out. Thanks :D

Thanks to:
Arul for pointing out an error on value/reference types.
 
Top