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)
 
(58 intermediate revisions by 14 users not shown)
Line 1: Line 1:
== Arrays and Collections, which should I use? ==
+
This guidance will help you '''choose the right collection type'''. It explains the basic uses of - and differences between - some of the various types of array-like containers you can use in Unity. If you haven't heard of arrays before, they are basically a single variable with a series of "compartments", where each compartment can contain a value. They're useful if you want to deal with a collection of values or objects together. In a game programming situation, you might use an array to store a reference to every enemy in your scene, or as a container for collected items in the player's inventory. Arrays can be 'iterated over', which is a fancy way of saying that you can go through each item in your array in sequence, and inspect or perform functions on each item in turn.
  
In this article I'm going to cover the following types of collection:
+
There are many types of containers, and a few of them use the name "array", but there are other types too. The broader term "collection" can be used to describe all these types of containers. These are the types of collection that I'll be describing in this article:
  
 
* Built-in array
 
* Built-in array
Line 9: Line 9:
 
* Generic List
 
* Generic List
 
* Generic Dictionary
 
* Generic Dictionary
* 2D Array (not yet written!)
+
* Hashset
 +
* 2D Array
  
There are other types for more specialised situations, but these are some of the basic 'staple diet' structures of the programming world.
+
There are other types for more specialised situations, but I have selected these as being some of the basic staples of programming.
  
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.
+
Because Unity is built on Mono, which is an open-source implementation of .Net, you have access to most of .Net's collection types. All of the above types are standard .Net types, with the exception of the "Javascript Array". The "Javascript Array" is a type which is added into the Unity Engine, and is only available if you're using the Javascript syntax in Unity - it's not available if you're using C#. However, it is essentially just a wrapper for the ArrayList class - which is available in C# - with a different set of functions provided. If you're coming to Unity having used Javascript or a Javascript-like language (such as ActionScript) elsewhere outside of Unity, it's important to be aware of these underlying differences, and bear in mind that Unity's "Javascript" isn't the same Javascript commonly used in WWW - it's UnityScript, just .Net with a different syntax laid over the top!
 
+
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:
 
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 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 '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.
 
* 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.
 
* For most collections, you can arbitrarily add and remove items at any position, and sort their contents.
 +
 +
By using LINQ, you can do a lot more:
 +
* mapping and filtering (Select and Where)
 +
* calculate sum or any aggregation you specify
 +
* basically replace a hand-rolled foreach-loop with a chain of LINQ functions
 +
* read more at [http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b MSDN page on LINQ]
  
 
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.
 
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 ==
 
== 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.
+
The most basic type of array, available in both JS and C#, is the built-in array. These used be limited by a fixed-size, but they can now be resized with "System.Array.Resize.(arrayname, size);" They are the fastest array in unity. 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.
 
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.
+
This type of array shows up in Unity's inspector window. This means that the contents of a built-in array can be populated in the Unity editor, by dragging and dropping references.  Generic Lists also have this ability, whereas Arrays and ArrayLists do not.
 +
 
 +
It's also usually the type of array you get back from Unity functions, if you use a function which may return a number of objects, such as [http://unity3d.com/support/documentation/ScriptReference/Component.GetComponentsInChildren.html GetComponentsInChildren].
  
 
Built-in arrays are declared by specifying the type of object you want to store, followed by brackets. Eg:
 
Built-in arrays are declared by specifying the type of object you want to store, followed by brackets. Eg:
Line 47: Line 47:
  
 
C#
 
C#
<csharp>TheType myArray = TheType[lengthOfArray];  // declaration
+
<syntaxhighlight lang="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
TheType thisValue = myArray[i];            // get a value from position i</csharp>
+
TheType thisValue = myArray[i];            // get a value from position i
 +
System.Array.Resize(ref myArray, size);    //resize array
 +
 
 +
string[] weapons = new string[] { "Sword", "Knife", "Gun" };
 +
 
 +
</syntaxhighlight>
  
  
 
Javascript
 
Javascript
<javascript>var myArray = TheType[lengthOfArray];      // declaration
+
<syntaxhighlight lang="javascript">var myArray = new TheType[lengthOfArray];      // declaration
var myNumbers = int[10];                  // declaration example using ints
+
var myNumbers = new int[10];                  // declaration example using ints
var enemies = GameObject[16];              // declaration example using GameObjects
+
var enemies = new GameObject[16];              // declaration example using GameObjects
 
var howBig = enemies.Length;              // get the length of the array
 
var howBig = enemies.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
var thisValue = myArray[i]                // get a value from position i</javascript>
+
var thisValue = myArray[i]                // get a value from position i
 +
System.Array.Resize. < Vector3 > (digselections2, selcount2);    //resize array
  
 +
var weapons = ["Sword", "Knife", "Gun"]  // Array values can also be declared along side the array itself
  
Useful list of functions (Methods):
+
</syntaxhighlight>
IndexOf, LastIndexOf, Reverse, Sort, Clear, Clone
+
  
[http://msdn.microsoft.com/en-us/library/system.array_members(VS.80).aspx Full MSDN Documentation for Built-in Array]
+
 
 +
[http://msdn.microsoft.com/en-us/library/system.array_members%28VS.80%29.aspx Full MSDN Documentation for Built-in Array]
 +
 
 +
Some direct links to useful Functions/Methods of Built-in Arrays:
 +
 
 +
[http://msdn.microsoft.com/en-us/library/system.array.indexof(VS.80).aspx IndexOf],
 +
[http://msdn.microsoft.com/en-us/library/system.array.lastindexof(VS.80).aspx LastIndexOf],
 +
[http://msdn.microsoft.com/en-us/library/system.array.reverse(VS.80).aspx Reverse],
 +
[http://msdn.microsoft.com/en-us/library/system.array.sort(VS.80).aspx Sort],
 +
[http://msdn.microsoft.com/en-us/library/system.array.clear(VS.80).aspx Clear],
 +
[http://msdn.microsoft.com/en-us/library/system.array.clone(VS.80).aspx Clone]
  
 
== Javascript Arrays ==
 
== 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.
+
The "Javascript Array" in unity is a special class that is provided as part of the Unity Engine 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# (but for C#, see "ArrayList" below).
  
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.
+
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 more costly in terms of performance. Another potential downside is 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.  In general, there's not really any reason to use Array, since other collection types do the same thing faster and with more features; it's left over from earlier in Unity's life when generic Lists weren't directly usable in Javascript.  If you need a dynamic array of mixed types, a generic List of Object will do the same thing as Array, but faster.
  
  
 
Basic Declaration & Use:
 
Basic Declaration & Use:
 
(Javascript Only)
 
(Javascript Only)
<javascript>var myArray = new Array();    // declaration
+
<syntaxhighlight lang="javascript">var myArray = new Array();    // declaration
 
myArray.Add(anItem);          // add an item to the end of the array
 
myArray.Add(anItem);          // add an item to the end of the array
 
var thisItem = myArray[i];    // retrieve an item from position i
 
var thisItem = myArray[i];    // retrieve an item from position i
 
myArray.RemoveAt(i);          // removes 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>
+
var howBig = myArray.length;  // get the length of the Array</syntaxhighlight>
 
+
 
+
Useful list of functions (Methods):
+
Concat, Join, Push, Add, Pop, Shift, RemoveAt, Unshift, Clear, Reverse, Sort
+
  
 
[http://unity3d.com/support/documentation/ScriptReference/Array.html Full Unity Documentation for Javascript Array]
 
[http://unity3d.com/support/documentation/ScriptReference/Array.html Full Unity Documentation for Javascript Array]
  
 +
Some direct links to useful Functions/Methods of Unity's Javascript Arrays:
  
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Concat.html Concat],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Join.html Join],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Push.html Push],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Add.html Add],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Pop.html Pop],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Shift.html Shift],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.RemoveAt.html RemoveAt],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Unshift.html Unshift],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Clear.html Clear],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Reverse.html Reverse],
 +
[http://unity3d.com/support/documentation/ScriptReference/Array.Sort.html Sort]
  
 
== ArrayLists ==
 
== 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.
+
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 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. They are obsoleted by generic Lists (see below), and are included primarily for compatibility with old code.
  
  
Line 100: Line 126:
  
 
Javascript
 
Javascript
<javascript>var myArrayList = new ArrayList();    // declaration
+
<syntaxhighlight lang="javascript">var myArrayList = new ArrayList();    // declaration
 
myArrayList.Add(anItem);              // add an item to the end of the array
 
myArrayList.Add(anItem);              // add an item to the end of the array
 
myArrayList[i] = newValue;            // change the value stored at position i
 
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!)
 
var thisItem : TheType = myArray[i];  // retrieve an item from position i (note the required casting!)
 
myArray.RemoveAt(i);                  // remove an item from position i
 
myArray.RemoveAt(i);                  // remove an item from position i
var howBig = myArray.Count;          // get the length of the array</javascript>
+
var howBig = myArray.Count;          // get the length of the array</syntaxhighlight>
  
  
 
C#
 
C#
<csharp>ArrayList myArrayList = new ArrayList();    // declaration
+
<syntaxhighlight lang="csharp">ArrayList myArrayList = new ArrayList();    // declaration
 
myArrayList.Add(anItem);                    // add an item to the end of the array
 
myArrayList.Add(anItem);                    // add an item to the end of the array
 
myArrayList[i] = newValue;                  // change the value stored at position i
 
myArrayList[i] = newValue;                  // change the value stored at position i
 
TheType thisItem = (TheType) myArray[i];    // retrieve an item from position i
 
TheType thisItem = (TheType) myArray[i];    // retrieve an item from position i
 
myArray.RemoveAt(i);                        // remove 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>
+
var howBig = myArray.Count;                // get the number of items in the ArrayList</syntaxhighlight>
 
+
 
+
Useful list of functions (Methods):
+
Add, Insert, Remove, RemoveAt, Clear, Clone, Contains, IndexOf, LastIndexOf, GetRange, SetRange,
+
AddRange, InsertRange, RemoveRange, Reverse, Sort, ToArray
+
  
 
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist_members.aspx Full MSDN Documentation for ArrayList]
 
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist_members.aspx Full MSDN Documentation for ArrayList]
  
 +
Some direct links to useful Functions/Methods of the ArrayList:
 +
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.add.aspx Add],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.insert.aspx Insert],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.remove.aspx Remove],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.removeat.aspx RemoveAt],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.clear.aspx Clear],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.clone.aspx Clone],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.contains.aspx Contains],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.indexof.aspx IndexOf],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.lastindexof.aspx LastIndexOf],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.getrange.aspx GetRange],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.setrange.aspx SetRange],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.addrange.aspx AddRange],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.insertrange.aspx InsertRange],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.removerange.aspx RemoveRange],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.reverse.aspx Reverse],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.sort.aspx Sort],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.arraylist.toarray.aspx ToArray]
  
 
== Hashtables ==
 
== Hashtables ==
Line 128: Line 168:
 
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".
 
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.
+
If you are familiar 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'.
+
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'. However, using a Dictionary (see below) is preferable over a Hashtable for much the same reason that a generic List is preferable over ArrayList.
  
  
Line 136: Line 176:
  
 
Javascript
 
Javascript
<javascript>var myHashtable = new Hashtable();                // declaration
+
<syntaxhighlight lang="javascript">var myHashtable:Hashtable = new Hashtable();                // declaration
 
myHashtable[anyKey] = newValue;                    // insert or change the value for the given key
 
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 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
 
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>
+
myHashtable.Remove(theKey);                        // remove the key & value pair from the Hashtable, for the given key.</syntaxhighlight>
  
  
 
C#
 
C#
<csharp>Hashtable myHashtable = new Hashtable();                // declaration
+
<syntaxhighlight lang="csharp">Hashtable myHashtable = new Hashtable();                // declaration
 
myHashtable[anyKey] = newValue;                          // insert or change the value for the given key
 
myHashtable[anyKey] = newValue;                          // insert or change the value for the given key
 
ValueType thisValue = (ValueType)myHashtable[theKey];    // retrieve a 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
 
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>
+
myHashtable.Remove(theKey);                              // remove the key & value pair from the Hashtable, for the given key.</syntaxhighlight>
  
 
Useful list of Functions (Methods):
 
Add, Remove, ContainsKey, ContainsValue, Clear, Clone
 
  
 
[http://msdn.microsoft.com/en-us/library/system.collections.hashtable_members.aspx Full MSDN Documentation for Hashtable Members]
 
[http://msdn.microsoft.com/en-us/library/system.collections.hashtable_members.aspx Full MSDN Documentation for Hashtable Members]
  
 +
Some direct links to useful Functions/Methods of the HashTable:
 +
 +
[http://msdn.microsoft.com/en-us/library/system.collections.hashtable.add.aspx Add],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.hashtable.remove.aspx Remove],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.hashtable.containskey.aspx ContainsKey],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.hashtable.containsvalue.aspx ContainsValue],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.hashtable.clear.aspx Clear],
 +
[http://msdn.microsoft.com/en-us/library/system.collections.hashtable.clone.aspx Clone]
  
 
== Generic List ==
 
== Generic List ==
 
+
The Generic List (also known as List<T>) 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.  
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:
 
Once you've declared it, you can only add objects of the correct type - and because of this restriction, you get two significant benefits:
Line 170: Line 212:
 
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.  
 
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:
+
The generic collections are not part of the standard System.Collections namespace, so to use them conveniently, you need to add a line at the top of any script in which you want to use them in C#:
  
<csharp>using System.Collections.Generic;</csharp>
+
<syntaxhighlight lang="csharp">using System.Collections.Generic;</syntaxhighlight>
  
 +
In Javascript:
 +
 +
<syntaxhighlight lang="javascript">import System.Collections.Generic;</syntaxhighlight>
  
 
Basic Declaration & Use:
 
Basic Declaration & Use:
(C# only)
+
 
<csharp>List<Type> myList = new List<Type>();                // declaration
+
(C#)
 +
<syntaxhighlight lang="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<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'
 
List<GameObject> enemies = new List<GameObject>();    // a real-world example of declaring a List of 'GameObjects'
Line 183: Line 229:
 
myList[i] = newItem;                                  // change the value in the List at position i
 
myList[i] = newItem;                                  // change the value in the List at position i
 
Type thisItem = List[i];                              // retrieve the item at position i
 
Type thisItem = List[i];                              // retrieve the item at position i
myList.RemoveAt(i);                                  // remove the item from position i</csharp>
+
myList.RemoveAt(i);                                  // remove the item from position i</syntaxhighlight>
  
 +
(Javascript)
 +
<syntaxhighlight lang="javascript">var myList : List.<Type> = new List.<Type>();  // declaration
 +
var someNumbers = new List.<int>();            // a real-world example of declaring a List of 'ints'
 +
var enemies = new List.<GameObject>();        // a real-world example of declaring a List of 'GameObjects'
 +
var vtcs = new List.<Vector3>(mesh.vertices);  // convert an array to a list
 +
myList.Add(theItem);                          // add an item to the end of the List
 +
myList[i] = newItem;                          // change the value in the List at position i
 +
var thisItem = List[i];                        // retrieve the item at position i
 +
myList.RemoveAt(i);                            // remove the item from position i</syntaxhighlight>
 +
numList = nums.ToList();                      // convert an array to list
  
Useful list of Functions (Methods):
+
[http://msdn.microsoft.com/en-us/library/d9hw1as6.aspx Full MSDN Documentation for Generic List]
Add, Remove, RemoveAll, Contains, IndexOf, LastIndexOf, Reverse, Sort, Clear, Clone, AddRange, GetRange, RemoveRange, ToArray
+
  
[http://msdn.microsoft.com/en-us/library/d9hw1as6.aspx Full MSDN Documentation for List(T)]
+
Some direct links to useful Methods of the Generic List:
  
 +
[http://msdn.microsoft.com/en-us/library/3wcytfd1(VS.80).aspx Add],
 +
[http://msdn.microsoft.com/en-us/library/sey5k5z4(VS.80).aspx Insert],
 +
[http://msdn.microsoft.com/en-us/library/cd666k3e(VS.80).aspx Remove],
 +
[http://msdn.microsoft.com/en-us/library/wdka673a(VS.80).aspx RemoveAll],
 +
[http://msdn.microsoft.com/en-us/library/5cw9x18z(VS.80).aspx RemoveAt],
 +
[http://msdn.microsoft.com/en-us/library/bhkz42b3(VS.80).aspx Contains],
 +
[http://msdn.microsoft.com/en-us/library/8bd0tetb(VS.80).aspx IndexOf],
 +
[http://msdn.microsoft.com/en-us/library/2cb8h8xb(VS.80).aspx LastIndexOf],
 +
[http://msdn.microsoft.com/en-us/library/5c6526tb(VS.80).aspx Reverse],
 +
[http://msdn.microsoft.com/en-us/library/3da4abas(VS.80).aspx Sort],
 +
[http://msdn.microsoft.com/en-us/library/dwb5h52a(VS.80).aspx Clear],
 +
[http://msdn.microsoft.com/en-us/library/z883w3dc(VS.80).aspx AddRange],
 +
[http://msdn.microsoft.com/en-us/library/21k0e39c(VS.80).aspx GetRange],
 +
[http://msdn.microsoft.com/en-us/library/884ee1fz(VS.80).aspx InsertRange],
 +
[http://msdn.microsoft.com/en-us/library/y33yd2b5(VS.80).aspx RemoveRange],
 +
[http://msdn.microsoft.com/en-us/library/x303t819(VS.80).aspx ToArray]
  
== Generic Dictionary ==
 
  
This is another Generic class, so the same restrictions apply (unsupported on iPhone, and un-declarable in Unity's Javascript).
+
[http://wiki.unity3d.com/index.php/List_:_Select_certain_elements_in_list_(JavaScript) Also, how to count certain item in List]
 +
 
 +
== Generic Dictionary ==
  
 
The Generic Dictionary is to the Hashtable what the Generic List is to the ArrayList.  
 
The Generic Dictionary is to the Hashtable what the Generic List is to the ArrayList.  
Line 201: Line 273:
 
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 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!
+
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, you can use type inference to alleviate this:
 +
 
 +
(C#)
 +
<syntaxhighlight lang="csharp">var myDictionary = new Dictionary<KeyType,ValueType>();</syntaxhighlight>
 +
(Javascript)
 +
<syntaxhighlight lang="javascript">var myDictionary = new Dictionary.<KeyType,ValueType>();</syntaxhighlight>
  
 
Again, to use this, you'll need to include the Generic Collections package by including this line at the top of your script:
 
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>
+
(C#)
 +
<syntaxhighlight lang="csharp">using System.Collections.Generic;</syntaxhighlight>
  
 +
(Javascript)
 +
<syntaxhighlight lang="javascript">import System.Collections.Generic;</syntaxhighlight>
  
 
Basic Declaration & Use:
 
Basic Declaration & Use:
(C# only)
+
 
<csharp>// declaration:
+
(C#)
Dictionary<KeyType,ValueType> myDictionary = new Dictionary<KeyType,ValueType>;
+
<syntaxhighlight lang="csharp">// declaration:
 +
Dictionary<KeyType,ValueType> myDictionary = new Dictionary<KeyType,ValueType>();
  
 
// and a real-world declaration example (where 'Person' is a custom class):
 
// and a real-world declaration example (where 'Person' is a custom class):
Dictionary<string,Person> myContacts = new Dictionary<string,Person>;
+
Dictionary<string,Person> myContacts = new Dictionary<string,Person>();
  
 
myDictionary[anyKey] = newValue;                // insert or change the value for the given key
 
myDictionary[anyKey] = newValue;                // insert or change the value for the given key
 
ValueType thisValue = myDictionary[theKey];      // retrieve a 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
 
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>
+
myDictionary.Remove(theKey);                    // remove the key & value pair from the Hashtable, for the given key.</syntaxhighlight>
  
 +
(Javascript)
 +
<syntaxhighlight lang="javascript">// declaration:
 +
var myDictionary : Dictionary.<KeyType,ValueType> = new Dictionary.<KeyType,ValueType>();
  
Useful list of Functions (Methods):
+
// and a real-world declaration example (where 'Person' is a custom class):
Add, Remove, ContainsKey, ContainsValue, Clear, Clone
+
var myContacts = new Dictionary.<String,Person>();
 +
 
 +
myDictionary[anyKey] = newValue;            // insert or change the value for the given key
 +
var thisValue = myDictionary[theKey];        // retrieve a value for the given key
 +
var 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.</syntaxhighlight>
  
 
[http://msdn.microsoft.com/en-us/library/3eayzh46.aspx Full MSDN Documentation for Dictionary(TKey,TValue)]
 
[http://msdn.microsoft.com/en-us/library/3eayzh46.aspx Full MSDN Documentation for Dictionary(TKey,TValue)]
  
[[Category:C_Sharp]]
+
Some direct links to useful Methods of the Generic Dictionary:
[[Category:Javascript]]
+
 
 +
[http://msdn.microsoft.com/en-us/library/k7z0zy8k(VS.80).aspx Add],
 +
[http://msdn.microsoft.com/en-us/library/kabs04ac(VS.80).aspx Remove],
 +
[http://msdn.microsoft.com/en-us/library/kw5aaea4(VS.80).aspx ContainsKey],
 +
[http://msdn.microsoft.com/en-us/library/a63811ah(VS.80).aspx ContainsValue],
 +
[http://msdn.microsoft.com/en-us/library/b5txwy7s(VS.80).aspx Clear],
 +
 
 +
== 2D Array ==
 +
 
 +
So far, all the examples of Arrays and Collections listed above have been one-dimensional structures, but there may be an occasion where you need to place data into an array with more dimensions. A typical game-related example of this is a tile-based map. You might have a 'map' array which should have a width and a height, and a piece of data in each cell which determines the tile to display. It is also possible to have arrays with more than two dimensions, such as a 3D array or a 4D array — however if you have a need for a 3D or 4D array, you're probably advanced enough to not require an explanation of how to use them!
 +
 
 +
There are two methods of implementing a multi-dimensional array. There are "real" multi-dimensional arrays, and there are "jagged" arrays. The difference is this:
 +
 
 +
With a "real" 2D array, your array has a fixed "width" and "height" (although they are not called width & height). You can refer to a location in your 2d array like this: myArray[x,y].
 +
 
 +
In contrast, "jagged" arrays aren't real 2D arrays, because they are created by using nested one-dimensional arrays. In this respect, what you essential have is a one-dimensional outer array which might represent your "rows", and each item contained in this outer array is actually an inner array which represents the cells in that row. To refer to a location in a jagged array, you would typically use something like this: myArray[y][x].
 +
 
 +
Usually, "real" 2D arrays are preferable, because they are simpler to set up and work with; however there are some valid cases for using jagged arrays. Such cases usually make use of the fact that, with a jagged array, each "inner" array doesn't have to be the same length (hence the origin of the term "jagged").
 +
 
 +
Note that Javascript doesn't currently support the syntax for declaring the type of jagged arrays directly.  You can use type inference, however:
 +
 
 +
<syntaxhighlight lang="javascript">var myJaggedArray = [ [1, 2, 3], [4, 5], [6, 7, 8, 9, 10] ]; // a jagged int array</syntaxhighlight>
 +
 
 +
In this case myJaggedArray is assigned a type of int[][], because the supplied values are all ints.  You can also use jagged arrays declared in C# scripts without any problems.
 +
 
 +
Basic Declaration & Use of "real" 2D arrays in C#:
 +
 
 +
<syntaxhighlight lang="csharp">// declaration:
 +
string[,] myArray = new string[16,4];            // a 16 x 4 array of strings
 +
 
 +
// and a real-world declaration example (where 'Tile' is a user-created custom class):
 +
Tile[,] map = new Tile[32,32];                  // create an array to hold a map of 32x32 tiles
 +
 
 +
myArray[x,y] = newValue;                        // set the value at a given location in the array
 +
ValueType thisValue = myArray[x,y];              // retrieve a value from a given location in the array
 +
int width = myArray.GetLength(0);                // get the length of 1st dimension of the array
 +
int length = myArray.GetLength(1);              // get the length of 2nd dimension of the array</syntaxhighlight>
 +
 
 +
In Javascript:
 +
 
 +
<syntaxhighlight lang="javascript">// declaration:
 +
var myArray : String[,] = new String[16,4];      // a 16 x 4 array of strings
 +
 
 +
// and a real-world declaration example (where 'Tile' is a user-created custom class):
 +
var map = new Tile[32,32];                      // create an array to hold a map of 32x32 tiles
 +
 
 +
myArray[x,y] = newValue;                        // set the value at a given location in the array
 +
var thisValue = myArray[x,y];                    // retrieve a value from a given location in the array
 +
var width = myArray.GetLength(0);                // get the length of 1st dimension of the array
 +
var length = myArray.GetLength(1);              // get the length of 2nd dimension of the array</syntaxhighlight>
 +
 
 +
== So which one should I use? ==
 +
 
 +
If there is no specific reason not to, '''use the generic containers'''.
 +
 
 +
Specific reasons might be:
 +
* optimizing memory efficiency and speed by using built-in arrays — since built-in arrays can be significantly faster than generic Lists for primitive types (up to 5X faster), it's a good idea to use them when you need the best possible speed.
 +
** changing Lists to Arrays isn't hard in the cases where Arrays are good enough for the job (known size), so why not still use Lists during development and save Array'ing to optimization phase?
 +
* third-party library uses ArrayLists and Hashtables (boooo, MiniJSON.cs, boooo), so I just want to avoid bunch of nasty-looking typecasts to stuff what they return into typed containers
 +
** well, you will need a typecast eventually anyway, and passing around Objects somehow implicitly trusting they are what they should is just asking for trouble
 +
** LINQ's Cast may help you with the problem of getting typed data out of untyped container
 +
 
 +
There's no good reason to use the JS Array class. It's relatively slow and won't work with #pragma strict code, unless you manually cast to the correct type when retrieving items. Use a generic List instead.
 +
 
 +
Similarly, ArrayList and Hashtable should be avoided, especially if you want to publish to the Windows store, since those collection types are obsolete and have been removed from the version of .NET that's used for Windows store apps. ("Real" .NET is used in that particular case, rather than Mono.)  Instead, use generic List and Dictionary, respectively.
 +
 
 
[[Category:Concepts]]
 
[[Category:Concepts]]
 
[[Category:Programming]]
 
[[Category:Programming]]

Latest revision as of 21:47, 2 February 2015

This guidance will help you choose the right collection type. It explains the basic uses of - and differences between - some of the various types of array-like containers you can use in Unity. If you haven't heard of arrays before, they are basically a single variable with a series of "compartments", where each compartment can contain a value. They're useful if you want to deal with a collection of values or objects together. In a game programming situation, you might use an array to store a reference to every enemy in your scene, or as a container for collected items in the player's inventory. Arrays can be 'iterated over', which is a fancy way of saying that you can go through each item in your array in sequence, and inspect or perform functions on each item in turn.

There are many types of containers, and a few of them use the name "array", but there are other types too. The broader term "collection" can be used to describe all these types of containers. These are the types of collection that I'll be describing in this article:

  • Built-in array
  • Javascript Array
  • ArrayList
  • Hashtable
  • Generic List
  • Generic Dictionary
  • Hashset
  • 2D Array

There are other types for more specialised situations, but I have selected these as being some of the basic staples of programming.

Because Unity is built on Mono, which is an open-source implementation of .Net, you have access to most of .Net's collection types. All of the above types are standard .Net types, with the exception of the "Javascript Array". The "Javascript Array" is a type which is added into the Unity Engine, and is only available if you're using the Javascript syntax in Unity - it's not available if you're using C#. However, it is essentially just a wrapper for the ArrayList class - which is available in C# - with a different set of functions provided. If you're coming to Unity having used Javascript or a Javascript-like language (such as ActionScript) elsewhere outside of Unity, it's important to be aware of these underlying differences, and bear in mind that Unity's "Javascript" isn't the same Javascript commonly used in WWW - it's UnityScript, just .Net with a different syntax laid over the top!

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.

By using LINQ, you can do a lot more:

  • mapping and filtering (Select and Where)
  • calculate sum or any aggregation you specify
  • basically replace a hand-rolled foreach-loop with a chain of LINQ functions
  • read more at MSDN page on LINQ

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.

Contents

[edit] Built-in Arrays

The most basic type of array, available in both JS and C#, is the built-in array. These used be limited by a fixed-size, but they can now be resized with "System.Array.Resize.(arrayname, size);" They are the fastest array in unity. 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 shows up in Unity's inspector window. This means that the contents of a built-in array can be populated in the Unity editor, by dragging and dropping references. Generic Lists also have this ability, whereas Arrays and ArrayLists do not.

It's also usually the type of array you get back from Unity functions, if you use a function which may return a number of objects, such as GetComponentsInChildren.

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


Basic Declaration & Use:

C#

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
System.Array.Resize(ref myArray, size);    //resize array
 
string[] weapons = new string[] { "Sword", "Knife", "Gun" };


Javascript

var myArray = new TheType[lengthOfArray];      // declaration
var myNumbers = new int[10];                   // declaration example using ints
var enemies = new 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
System.Array.Resize. < Vector3 > (digselections2, selcount2);     //resize array
 
var weapons = ["Sword", "Knife", "Gun"]  // Array values can also be declared along side the array itself


Full MSDN Documentation for Built-in Array

Some direct links to useful Functions/Methods of Built-in Arrays:

IndexOf, LastIndexOf, Reverse, Sort, Clear, Clone

[edit] Javascript Arrays

The "Javascript Array" in unity is a special class that is provided as part of the Unity Engine 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# (but for C#, see "ArrayList" below).

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 more costly in terms of performance. Another potential downside is 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. In general, there's not really any reason to use Array, since other collection types do the same thing faster and with more features; it's left over from earlier in Unity's life when generic Lists weren't directly usable in Javascript. If you need a dynamic array of mixed types, a generic List of Object will do the same thing as Array, but faster.


Basic Declaration & Use: (Javascript Only)

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

Full Unity Documentation for Javascript Array

Some direct links to useful Functions/Methods of Unity's Javascript Arrays:

Concat, Join, Push, Add, Pop, Shift, RemoveAt, Unshift, Clear, Reverse, Sort

[edit] 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 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. They are obsoleted by generic Lists (see below), and are included primarily for compatibility with old code.


Basic Declaration & Use:

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


C#

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

Full MSDN Documentation for ArrayList

Some direct links to useful Functions/Methods of the ArrayList:

Add, Insert, Remove, RemoveAt, Clear, Clone, Contains, IndexOf, LastIndexOf, GetRange, SetRange, AddRange, InsertRange, RemoveRange, Reverse, Sort, ToArray

[edit] 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 familiar 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'. However, using a Dictionary (see below) is preferable over a Hashtable for much the same reason that a generic List is preferable over ArrayList.


Basic Declaration & Use:

Javascript

var myHashtable:Hashtable = 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.


C#

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.


Full MSDN Documentation for Hashtable Members

Some direct links to useful Functions/Methods of the HashTable:

Add, Remove, ContainsKey, ContainsValue, Clear, Clone

[edit] Generic List

The Generic List (also known as List<T>) 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 conveniently, you need to add a line at the top of any script in which you want to use them in C#:

using System.Collections.Generic;

In Javascript:

import System.Collections.Generic;

Basic Declaration & Use:

(C#)

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

(Javascript)

var myList : List.<Type> = new List.<Type>();  // declaration
var someNumbers = new List.<int>();            // a real-world example of declaring a List of 'ints'
var enemies = new List.<GameObject>();         // a real-world example of declaring a List of 'GameObjects'
var vtcs = new List.<Vector3>(mesh.vertices);  // convert an array to a list
myList.Add(theItem);                           // add an item to the end of the List
myList[i] = newItem;                           // change the value in the List at position i
var thisItem = List[i];                        // retrieve the item at position i
myList.RemoveAt(i);                            // remove the item from position i

numList = nums.ToList(); // convert an array to list

Full MSDN Documentation for Generic List

Some direct links to useful Methods of the Generic List:

Add, Insert, Remove, RemoveAll, RemoveAt, Contains, IndexOf, LastIndexOf, Reverse, Sort, Clear, AddRange, GetRange, InsertRange, RemoveRange, ToArray


Also, how to count certain item in List

[edit] Generic Dictionary

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, you can use type inference to alleviate this:

(C#)

var myDictionary = new Dictionary<KeyType,ValueType>();

(Javascript)

var myDictionary = new Dictionary.<KeyType,ValueType>();

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

(C#)

using System.Collections.Generic;

(Javascript)

import System.Collections.Generic;

Basic Declaration & Use:

(C#)

// 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.

(Javascript)

// declaration:
var myDictionary : Dictionary.<KeyType,ValueType> = new Dictionary.<KeyType,ValueType>();
 
// and a real-world declaration example (where 'Person' is a custom class):
var myContacts = new Dictionary.<String,Person>();
 
myDictionary[anyKey] = newValue;             // insert or change the value for the given key
var thisValue = myDictionary[theKey];        // retrieve a value for the given key
var 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.

Full MSDN Documentation for Dictionary(TKey,TValue)

Some direct links to useful Methods of the Generic Dictionary:

Add, Remove, ContainsKey, ContainsValue, Clear,

[edit] 2D Array

So far, all the examples of Arrays and Collections listed above have been one-dimensional structures, but there may be an occasion where you need to place data into an array with more dimensions. A typical game-related example of this is a tile-based map. You might have a 'map' array which should have a width and a height, and a piece of data in each cell which determines the tile to display. It is also possible to have arrays with more than two dimensions, such as a 3D array or a 4D array — however if you have a need for a 3D or 4D array, you're probably advanced enough to not require an explanation of how to use them!

There are two methods of implementing a multi-dimensional array. There are "real" multi-dimensional arrays, and there are "jagged" arrays. The difference is this:

With a "real" 2D array, your array has a fixed "width" and "height" (although they are not called width & height). You can refer to a location in your 2d array like this: myArray[x,y].

In contrast, "jagged" arrays aren't real 2D arrays, because they are created by using nested one-dimensional arrays. In this respect, what you essential have is a one-dimensional outer array which might represent your "rows", and each item contained in this outer array is actually an inner array which represents the cells in that row. To refer to a location in a jagged array, you would typically use something like this: myArray[y][x].

Usually, "real" 2D arrays are preferable, because they are simpler to set up and work with; however there are some valid cases for using jagged arrays. Such cases usually make use of the fact that, with a jagged array, each "inner" array doesn't have to be the same length (hence the origin of the term "jagged").

Note that Javascript doesn't currently support the syntax for declaring the type of jagged arrays directly. You can use type inference, however:

var myJaggedArray = [ [1, 2, 3], [4, 5], [6, 7, 8, 9, 10] ]; // a jagged int array

In this case myJaggedArray is assigned a type of int[][], because the supplied values are all ints. You can also use jagged arrays declared in C# scripts without any problems.

Basic Declaration & Use of "real" 2D arrays in C#:

// declaration:
string[,] myArray = new string[16,4];            // a 16 x 4 array of strings
 
// and a real-world declaration example (where 'Tile' is a user-created custom class):
Tile[,] map = new Tile[32,32];                   // create an array to hold a map of 32x32 tiles
 
myArray[x,y] = newValue;                         // set the value at a given location in the array
ValueType thisValue = myArray[x,y];              // retrieve a value from a given location in the array
int width = myArray.GetLength(0);                // get the length of 1st dimension of the array 
int length = myArray.GetLength(1);               // get the length of 2nd dimension of the array

In Javascript:

// declaration:
var myArray : String[,] = new String[16,4];      // a 16 x 4 array of strings
 
// and a real-world declaration example (where 'Tile' is a user-created custom class):
var map = new Tile[32,32];                       // create an array to hold a map of 32x32 tiles
 
myArray[x,y] = newValue;                         // set the value at a given location in the array
var thisValue = myArray[x,y];                    // retrieve a value from a given location in the array
var width = myArray.GetLength(0);                // get the length of 1st dimension of the array 
var length = myArray.GetLength(1);               // get the length of 2nd dimension of the array

[edit] So which one should I use?

If there is no specific reason not to, use the generic containers.

Specific reasons might be:

  • optimizing memory efficiency and speed by using built-in arrays — since built-in arrays can be significantly faster than generic Lists for primitive types (up to 5X faster), it's a good idea to use them when you need the best possible speed.
    • changing Lists to Arrays isn't hard in the cases where Arrays are good enough for the job (known size), so why not still use Lists during development and save Array'ing to optimization phase?
  • third-party library uses ArrayLists and Hashtables (boooo, MiniJSON.cs, boooo), so I just want to avoid bunch of nasty-looking typecasts to stuff what they return into typed containers
    • well, you will need a typecast eventually anyway, and passing around Objects somehow implicitly trusting they are what they should is just asking for trouble
    • LINQ's Cast may help you with the problem of getting typed data out of untyped container

There's no good reason to use the JS Array class. It's relatively slow and won't work with #pragma strict code, unless you manually cast to the correct type when retrieving items. Use a generic List instead.

Similarly, ArrayList and Hashtable should be avoided, especially if you want to publish to the Windows store, since those collection types are obsolete and have been removed from the version of .NET that's used for Windows store apps. ("Real" .NET is used in that particular case, rather than Mono.) Instead, use generic List and Dictionary, respectively.

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox