C#, difference between foreach(var i... and foreach(Transform i...

Hi Everyone,

Hopefully a quick question. I’ve recently decided to drop JS in favour of learning C# so this is probably a newbie question.

It seems the compiler doesn’t mind either of these:

Transform[] trans;
foreach(var i in trans){

}

and

Transform[] trans;
foreach(Transform i in trans){

}

Could someone explain the practical difference in Unity between the two? I notice documentation opts for the latter.

Is the compiler automatically choosing an appropriate type? Is it bad practice to use var here?

Thanks for your time.

yes Var means the compiler determines the type of the object.

I would say yes it’s bad practice.

Declaring the type of the object allows the compiler to let you know when you do something bad.

for example

var Mytransform;

Mytransform = MyGameobject;

this is allowed, thats because Mytransform is a variable not a transform, so it won’t throw an error until you start playing the game and it realizes its a transform. Unless it becomes a game object and then you try to do transform stuff with it.

Basically you can end up with code that lets things be things they are not (an issue in java) and you won’t know it (it will compile) until you play

Also Autocomplete is VERY nice and probably (i never use variable)
doesnt work well with var.

If i type

transform mytransform;

the compiler knows its a transform and if i type

mytransform.addforce

it will throw an error because it knows that function is not a transform function
(it wouldn’t do this for a var type variable)

further more if i begin typing

mytransform.for

it will automatically type forward for me and i can just press enter because it knows there are only a few choices.

I would always use type declared code.
It is safer and less prone to errors.

If you would like more info google strongly typed vs weakly typed programming languages for the pro’s/con’s of each.

Mark as answered if you feel I answered your question please

I just want to add some information since sparkzbarca answer is not entirely correct :wink:

You can’t declare “just a variable”. In C# a variable always has a type. If you just write:

var someVariable;

you will get an error in Unity (ps. this line might work in “normal” C#, but it will simply create an object variable instead.):

CS0818: An implicitly typed local variable declarator must include an initializer

That’s because the compiler tries to infer the type from your code. This is only possible when you initialize the variable when you declare it:

var someVar = 1;          // this is an integer variable
var someVar = 1.0f;       // this is a float variable
var someVar = 1.0;        // this is a double variable
var someVar = transform;  // this is a Transform variable

It’s just a short form for writing:

int someVar = 1;
float someVar = 1.0f;
double someVar = 1.0;
Transform someVar = transform;

The same applies to the foreach loop. Using the var-keyword will automatically type the variable as the type contained in the collection you iterate over. So when you iterate over a Transform array the for-variable will be of type Transform

Note: It is possible to declare a variable which looks like it has no type. Just use the type “object”. Every type in C# /.NET / Mono can be assigned to an object variable. While reference types like classes can be assigned to such a variable without problems, value-types like ints, floats, structs need to be “boxed”. Thats an implicit conversion where the compiler will copy the “value” onto the heap so it gets a reference which can be stored in the object variable.

The downside of such variables is that the compiler doesn’t know what is actually stored in the variable. To use the “thing” that’s stored in the variable it need to be casted into the “right” type. Casting, boxing and unboxing will reduce the preformance since the runtime has to check if the object can be casted into the given type. That’s why you usually avoid object-variables.

Back to the question. It makes no difference if you use the var keyword in a foreach loop or the actual type as long as the collection is typed.

For example. If you want to iterate over the children of a gameobject you cah use such a foreach loop:

foreach(Transform child in gameObject.transform)
{
    Debug.Log(child.name);
}

This is possible because the Transform class implements the IEnumerable interface. However they did not implement the generic-typed IEnumerable but the untyped version. That means when using the var-keyword here, the child variable will be of type object since the compiler doesn’t know what the IEnumerable will return. The above loop will try to cast the “thing” it gets from the collection into a Transform.

foreach(var child in gameObject.transform)
{
    Debug.Log(child.name); // FAILS!!!
    var transformVar = (Transform)child; //transformVar will be typed as "Transform" since a transform is assigned to it.
    Debug.Log(transformVar.name); // works
}

In this example the child variable will be of type object and needs to be casted to Transform before you can use it.

Finally i wouldn’t say it’s bad practice in general. The important thing is that it’s obvious what the type actually is. For example a variable named childRenderers suggests two things:

  • It’s an array or collection because it’s plural
  • It will most likely contain "Renderer"s

In most cases it’s not important to know the exact type as long as you know what you expect from that variable.

Another good example of using “var” is when declaring quite complex temporal Lists:

    var tmpList = new List<List<ProceduralPropertyDescription>>();

this is way easier to read instead of this:

    List<List<ProceduralPropertyDescription>> tmpList = new List<List<ProceduralPropertyDescription>>();