Choosing the right collection type

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
m (Added links to MSDN and Unity documentation pages)
m (Built-in Arrays: -fixed error in code (missing 'new' in c# example))
Line 47: Line 47:
  
 
C#
 
C#
<csharp>TheType myArray = TheType[lengthOfArray];  // declaration
+
<csharp>TheType myArray = new TheType[lengthOfArray];  // declaration
int[] myNumbers = int[10];                // declaration example using ints
+
int[] myNumbers = new int[10];                // declaration example using ints
GameObject enemies = GameObject[16];      // declaration example using GameObjects
+
GameObject enemies = new GameObject[16];      // declaration example using GameObjects
 
int howBig = myArray.Length;              // get the length of the array
 
int howBig = myArray.Length;              // get the length of the array
 
myArray[i] = newValue;                    // set a value at position i
 
myArray[i] = newValue;                    // set a value at position i

Revision as of 16:32, 7 October 2009

Contents

Arrays and Collections, which should I use?

In this article I'm going to cover the following types of collection:

  • Built-in array
  • Javascript Array
  • ArrayList
  • Hashtable
  • Generic List
  • Generic Dictionary
  • 2D Array (not yet written!)

There are other types for more specialised situations, but these are some of the basic 'staple diet' structures of the programming world.

A 'collection' is a term that can be used to describe all these types of containers. Collections are objects which are designed to allow you to group together many other objects or items in a single container. You will usually want to use an array - or some other type of collection - when you need to manipulate or work with many objects of the same type. An 'array' is just one of the many types of collections available.

At its simplest level, an array can be thought of as a container for a series of objects, arranged in a sequential manner.

Because Unity is built on Mono, which is an open-source implementation of .Net, you have access to most of use .Net's collection types. In addition, Unity has a special 'Javascript Array' type, which is available if you're using Javascript in Unity.

All types of collections share a few common features:

  • You can fill them with objects, and read back the values that you put in.
  • You can 'iterate' through them, which means you can create a loop which runs the same piece of code against each item in the collection.
  • You can get the length of the collection.
  • For most collections, you can arbitrarily add and remove items at any position, and sort their contents.

Below, I describe some of the most common types of collection, along with their pros and cons, and some (but not all) of their most useful properties and methods.


Built-in Arrays

The most basic type of array, available in both JS and C#, is the built-in array. The main shortcoming of built-in arrays is that they have a fixed-size (which you choose when you declare the array), however this shortcoming is balanced by their very fast performance. For this reason, built-in arrays are the best choice if you need the fastest performance possible from your code (for example, if you're targeting iPhone). If there is a fixed and known number of items that you want to store, this is the best choice.

It's also common to use this type of array if you have a varying number of items to store, but you can decide on a 'maximum' for the number of objects that you'll need. You can then leave some of the elements in the array null when they're not required, and design your code around this. For example, for the bullets in a shooting game, you may decide to use an array of size 50, allowing a maximum of 50 active bullets at any one time.

This type of array is also the only type of array which shows up in Unity's inspector window. This means that a built-in array is the correct choice if you want to populate its contents in the Unity editor, by dragging and dropping references.

Built-in arrays are declared by specifying the type of object you want to store, followed by brackets. Eg:


Basic Declaration & Use:

C# <csharp>TheType myArray = new TheType[lengthOfArray]; // declaration int[] myNumbers = new int[10]; // declaration example using ints GameObject enemies = new GameObject[16]; // declaration example using GameObjects int howBig = myArray.Length; // get the length of the array myArray[i] = newValue; // set a value at position i TheType thisValue = myArray[i]; // get a value from position i</csharp>


Javascript <javascript>var myArray = TheType[lengthOfArray]; // declaration var myNumbers = int[10]; // declaration example using ints var enemies = GameObject[16]; // declaration example using GameObjects var howBig = enemies.Length; // get the length of the array myArray[i] = newValue; // set a value at position i var thisValue = myArray[i] // get a value from position i</javascript>


Useful list of functions (Methods): IndexOf, LastIndexOf, Reverse, Sort, Clear, Clone

Full MSDN Documentation for Built-in Array

Javascript Arrays

The 'Javascript Array' in unity is a class that is provided in addition to the standard .net classes. You can only declare them if you are using a Javascript syntax script - you can't declare them in C#. Javascript arrays are dynamic in size, which means you don't have to specify a fixed size. You can add and remove items to the array, and the array will grow and shrink in size accordingly. You also don't have to specify the type of object you want to store. You can put objects of any type into a Javascript array, even mixed types in the same array.

Javascript arrays are therefore somewhat easier to use than built-in arrays, however they are a bit more costly in terms of performance (although performance cost here is only worth worrying about if you are dealing with very large numbers of objects, or if you're targeting the iPhone). Another potential downsideis that there are certain situations where you need to use explicit casting when retrieving items because of their 'untyped' nature - despite Javascript's dynamic typing.


Basic Declaration & Use: (Javascript Only) <javascript>var myArray = new Array(); // declaration myArray.Add(anItem); // add an item to the end of the array var thisItem = myArray[i]; // retrieve an item from position i myArray.RemoveAt(i); // removes an item from position i var howBig = myArray.length; // get the length of the Array</javascript>


Useful list of functions (Methods): Concat, Join, Push, Add, Pop, Shift, RemoveAt, Unshift, Clear, Reverse, Sort

Full Unity Documentation for Javascript Array


ArrayLists

The ArrayList is a .Net class, and is very similar to the Javascript Array mentioned previously, but this time available in both JS and C#. Like JS Arrays, ArrayLists are dynamic in size, so you can add and remove items, and the array will grow and shrink in size to fit. ArrayLists are also untyped, so you can add items of any kind, including a mixture of types in the same ArrayList. ArrayLists are also similarly a little more costly when compared to the blazingly fast performance of built-in arrays. ArrayLists have a wider set of features compared to JS Arrays, although neither of their feature sets completely overlaps the other.


Basic Declaration & Use:

Javascript <javascript>var myArrayList = new ArrayList(); // declaration myArrayList.Add(anItem); // add an item to the end of the array myArrayList[i] = newValue; // change the value stored at position i var thisItem : TheType = myArray[i]; // retrieve an item from position i (note the required casting!) myArray.RemoveAt(i); // remove an item from position i var howBig = myArray.Count; // get the length of the array</javascript>


C# <csharp>ArrayList myArrayList = new ArrayList(); // declaration myArrayList.Add(anItem); // add an item to the end of the array myArrayList[i] = newValue; // change the value stored at position i TheType thisItem = (TheType) myArray[i]; // retrieve an item from position i myArray.RemoveAt(i); // remove an item from position i var howBig = myArray.Count; // get the number of items in the ArrayList</csharp>


Useful list of functions (Methods): Add, Insert, Remove, RemoveAt, Clear, Clone, Contains, IndexOf, LastIndexOf, GetRange, SetRange, AddRange, InsertRange, RemoveRange, Reverse, Sort, ToArray

Full MSDN Documentation for ArrayList


Hashtables

A Hashtable is a type of collection where each item is made up of a "Key and Value" pair. It's most commonly used in situations where you want to be able to do a quick look-up based on a certain single value. The piece of information that you use to perform the look-up is the 'key', and the object that is returned is the "Value".

If you are familliar with web development, it's similar to the type of data in a GET or POST request, where every value passed has a corresponding name. With a Hashtable however, both the keys and the values can be any type of object. For most practical applications, it's usually the case that your keys are going to be all the same type (eg, strings) and your values are likely to be all of the same type too (eg, GameObjects, or some other class instance). As with ArrayLists, because Hashtable keys and values are untyped, you usually have to deal with the type casting yourself when you retrieve values from the collection.

Hashtables are designed for situations where you want to be able to quickly pick out a certain item from your collection, using some unique identifying key - similar to the way you might select a record from a database using an index, or the way you might pick out the contact details of a person using their name as the 'unique identifier'.


Basic Declaration & Use:

Javascript <javascript>var myHashtable = new Hashtable(); // declaration myHashtable[anyKey] = newValue; // insert or change the value for the given key var thisValue : ValueType = myHashtable[theKey]; // retrieve a value for the given key (note the required type casting) var howBig = myHashtable.Count; // get the number of items in the Hashtable myHashtable.Remove(theKey); // remove the key & value pair from the Hashtable, for the given key.</javascript>


C# <csharp>Hashtable myHashtable = new Hashtable(); // declaration myHashtable[anyKey] = newValue; // insert or change the value for the given key ValueType thisValue = (ValueType)myHashtable[theKey]; // retrieve a value for the given key int howBig = myHashtable.Count; // get the number of items in the Hashtable myHashtable.Remove(theKey); // remove the key & value pair from the Hashtable, for the given key.</csharp>


Useful list of Functions (Methods): Add, Remove, ContainsKey, ContainsValue, Clear, Clone

Full MSDN Documentation for Hashtable Members


Generic List

First of all, Generics are not supported at all on iPhone, because it runs on an earlier version of Mono. In addition, you can't declare Generics in unity's Javascript, because it does not support the syntax required. This is one of the many reasons I reccomend using C# over Javascript in Unity - but that's a different story!

The Generic List is similar to the JS Array and the ArrayList, in that they have a dynamic size, and support arbitrary adding, getting and removing of items. The significant difference with the Generic List (and all other 'Generic' type classes), is that you explicitly specify the type to be used when you declare it - in this case, the type of object that the List will contain.

Once you've declared it, you can only add objects of the correct type - and because of this restriction, you get two significant benefits:

  • no need to do any type casting of the values when you come to retrieve them.
  • performs significantly faster than ArrayList

This means that if you were going to create an ArrayList, but you know that you will only be putting objects of one specific type of object into it, (and you know that type in advance) you're generally better off using a Generic List. For me, this tends to be true pretty much all the time.

The generic collections are not part of the standard System.Collections namespace, so to use them, you need to add a line a the top of any script in which you want to use them:

<csharp>using System.Collections.Generic;</csharp>


Basic Declaration & Use: (C# only) <csharp>List<Type> myList = new List<Type>(); // declaration List<int> someNumbers = new List<int>(); // a real-world example of declaring a List of 'ints' List<GameObject> enemies = new List<GameObject>(); // a real-world example of declaring a List of 'GameObjects' myList.Add(theItem); // add an item to the end of the List myList[i] = newItem; // change the value in the List at position i Type thisItem = List[i]; // retrieve the item at position i myList.RemoveAt(i); // remove the item from position i</csharp>


Useful list of Functions (Methods): Add, Remove, RemoveAll, Contains, IndexOf, LastIndexOf, Reverse, Sort, Clear, Clone, AddRange, GetRange, RemoveRange, ToArray

Full MSDN Documentation for List(T)


Generic Dictionary

This is another Generic class, so the same restrictions apply (unsupported on iPhone, and un-declarable in Unity's Javascript).

The Generic Dictionary is to the Hashtable what the Generic List is to the ArrayList. The Generic Dictionary provides you with a structure for quickly looking up items from a collection (like the Hashtable), but it differs from the Hashtable in that you must specify explictly the types for the Keys and Values up-front, when you declare it.

Because of this, you get similar benefits to those mentioned in the Generic List. Namely, no annoying casting needed when using the Dictionary, and a significant performance increase compared to the Hashtable.

Because you need to specify the types for both the Keys and the Values, the declaration line can end up a little long and wordy. However, once you've overcome this they are great to work with!

Again, to use this, you'll need to include the Generic Collections package by including this line at the top of your script:

<csharp>using System.Collections.Generic;</csharp>


Basic Declaration & Use: (C# only) <csharp>// declaration: Dictionary<KeyType,ValueType> myDictionary = new Dictionary<KeyType,ValueType>;

// and a real-world declaration example (where 'Person' is a custom class): Dictionary<string,Person> myContacts = new Dictionary<string,Person>;

myDictionary[anyKey] = newValue; // insert or change the value for the given key ValueType thisValue = myDictionary[theKey]; // retrieve a value for the given key int howBig = myDictionary.Count; // get the number of items in the Hashtable myDictionary.Remove(theKey); // remove the key & value pair from the Hashtable, for the given key.</csharp>


Useful list of Functions (Methods): Add, Remove, ContainsKey, ContainsValue, Clear, Clone

Full MSDN Documentation for Dictionary(TKey,TValue)

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox