I don’t get this. I see this in various scripts, projects and even the tutorials. Why does everyone using C# subject themselves to non-generic collections? Why are people not using System.Collections.Generic? You gain type safety and a LOT of speed. The acclaimed speed difference between lists and built-in arrays is, in fact, entirely due to using non-generic collections. If you use System.Collections.Generic.List for example, it’ll be just as fast as a built in array (some benchmarks even show it being negligibly faster).
I’m a veteran .NET developer but new to Unity. Is there a reason for this? It seems rather silly…
In Unity iPhone 1.x for the reason that it means that you can remain on .NET 1.1 which makes a fair difference in size
On the desktop: cause its standard and generics don’t seem to be that common with new switchers from unitscript or general webdevelopment with JS etc.
I personally only use generics cause type safety is one of the reasons why I favor modern language over the less modern and more non-standard ones.
But the major reason might be that such classes can never be used as base layer for unityscript / boo, cause they don’t understand the concept (ok unity 3 unityscript finally has some kind of generics support, don’t ask to which degree though and if it can interact with the fully fledged C# generics world)
also unity iphone 1.x / unity 2.x are mono 1.2.5 which is .NET 2.0 basically, many generic datastructures aside of list<> and dictionary<,> are missing
That’s true, I’d forgotten about the iPhone. That’s certainly fair. And I see your point about JavaScript but not about Boo, since Boo does support generics. Of course I’m of the opinion that no one should use JavaScript because it’s a terrible language but that’s another discussion.
What types are missing from Mono 1.2.5? I thought Mono 1.2 has more or less feature parity with .NET 2.0. That means you have the entire set of generic types.
Not in Mono it isn’t (or at least not in Unity). If you want the best speed, stick to built-in arrays.
Javascript in Unity isn’t Javascript, it’s JScript.NET. And in Unity 3.0 it has generics.
Because the default .cs script in Unity has “using Systems.Collections”, and people don’t generally pay any attention to it and leave it in. It’s not like it hurts anything.
That’s what it is…I knew there was something important that needed Systems.Collections and couldn’t remember what it was. I was sitting here looking through a bunch of my scripts trying to figure it out. (Well, 95% of my scripts that use coroutines are JS anyway…)
Ah well the coroutine restriction is not that much of a hard restriction. if you create object instance to execute it or don’t have parallel coroutines, you can use an instance variable of generic nature.
I do this on a near day to day base in relation to webservices and the corresponding in application cache management.
It should be. There’s no reason why it should suddenly not be true in Mono for Unity.
Yes but it’s still weakly typed which is why I don’t like it. The implication of generics in 3.0 seems to suggest otherwise and I look forward to seeing what that brings.
What do you mean exactly? Why wouldn’t they work? Like, you can’t use a generic collection inside a coroutine?
However, it is in fact totally true. I just ran a simple benchmark, and int[ ] is 19 times faster (yes, nineteen) than List. List is almost 4.5 times faster than using an ArrayList, however. (Which makes int[ ] about 85 times faster than ArrayList.) You should never make assumptions about code you haven’t seen; you need to test actual results.
No, it’s not weakly typed.
This compiles:
using UnityEngine;
using System.Collections;
public class NewBehaviourScript : MonoBehaviour {
IEnumerator Start () {
yield return new WaitForSeconds(1);
print ("You just waited a second!");
}
}
This does not:
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
IEnumerator Start () {
yield return new WaitForSeconds(1);
print ("You just waited a second!");
}
}
There is, you can just explicitely declare the return as System.Collections.IEnumerator etc
but its a pain in the butt to do that all script long so you normally just have the using in and omit the whole rats tail in front there.
Thats likely why its there by default (and why UnityScript imports it along unityengine behind the scene by default too)
nope, its explicitely non generic
That holds for all unity related things, they never accept generic “extensions” of old classes in general.
Thats what some people had to find out the hard way on other ends too, but the most trivial case is generics + editor exposure which goes under: skip it baby if its anything but list<>, which is just another reason they are not that popular
And just to stop that idea upfront:
no, you can also not create customeditors for generics, as unity does not support generics for such usages.
Similiar to the case that you need to put a non-generic version of a class into the class file aside of a generics using one if you want to use it in unity as someclass isn’t the same as someclass yet someclass is expected if the file is called someclass.cs
I thought it was but you’re right. Thinking about it, it’d have to be since it’s implemented on the CLR which is inherently strongly typed.
Oh. So just so do this:
using UnityEngine;
using System.Collections.Generic;
public class NewBehaviourScript : MonoBehaviour {
System.Collections.IEnumerator Start () {
yield return new WaitForSeconds(1);
print ("You just waited a second!");
}
}
By the way, that benchmark is flawed. With the method they’re using, ushort[ ] is in fact slower than List in Unity too, so indeed that’s correct about Mono. However, what they’re doing with passing ushort[ ] to the Sum function, which uses IList, makes it slower. If you remove the Sum function and replace it with functionally identical code that just iterates through ushort[ ] directly, and code that iterates though List directly, then ushort[ ] is 15 times faster than List. I’m not sure what’s going on there with casting or whatnot with the Sum function, but that’s definitely not the way to use built-in arrays if you actually want the speed they provide.
Here’s what I did with that benchmark code in Unity, where I inlined the function so it works with the arrays natively:
const int Size = 500000;
void Start ()
{
ushort[] array = new ushort [Size];
float timer = Time.realtimeSinceStartup;
int result = 0;
for (int i = 0; i < array.Length; ++i)
result += array [i];
Debug.Log (" ushort[]: " + (Time.realtimeSinceStartup - timer));
List<ushort> list = new List<ushort> (Size);
for (int i = 0; i < Size; ++i) list.Add (0);
timer = Time.realtimeSinceStartup;
result = 0;
for (int i = 0; i < list.Count; ++i)
result += list [i];
Debug.Log ("List<ushort>: " + (Time.realtimeSinceStartup - timer));
}
You’re right. I forgot to add elements to the list in my benchmark (it only had capacity), and thus Count was always 0. The difference is negligible in either case.