I just want to add some information since sparkzbarca answer is not entirely correct
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>>();