Using "var" in C# script

Hello, I’m quite new to c# and I’m looking at someone else’s script (included below), which seems to provide a way to switch between different controller setups.

I understand most of this, but I’m confused by the use of “var”, for example

foreach (var mode in this.ControlModes) {
            if (mode != this.currentMode) {
                mode.Behaviour.enabled = false;
            }

If I hover the mouse-over “var” in visual studio, a box comes up telling me that “var” is of type “ControlModeSwitcher.ControlMode”, but how does the script know what type this “var” should be? Is it just inferred from the rest of the line, i.e. if a var is in the ControlModes array, it must be a ControlMode?

Does this syntax only work within a “foreach” loop, or can it be used elsewhere?
Is there any reason to use “var” here, rather than:

foreach (ControlMode mode in this.ControlModes) {
            if (mode != this.currentMode) {
                mode.Behaviour.enabled = false;
            }
        }
using UnityEngine;
using System.Linq;
using System;

public class ControlModeSwitcher : MonoBehaviour {
    [System.Serializable]
    public class ControlMode {
        public KeyCode KeyCode;
        public MonoBehaviour Behaviour;
    }

    public ControlMode[] ControlModes;

    public KeyCode[] ModeSwitchKeys;

    private ControlMode currentMode;

    void Start() {
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;
        if (this.ControlModes.Any()) {
            this.SetMode(this.ControlModes[0]);
        }
        foreach (var mode in this.ControlModes) {
            if (mode != this.currentMode) {
                mode.Behaviour.enabled = false;
            }
        }
    }

    void Update() {
        foreach (var mode in this.ControlModes) {
            if (Input.GetKeyDown(mode.KeyCode)) {
                this.SetMode(mode);
            }
        }
        if (this.currentMode != null && this.ModeSwitchKeys != null) {
            foreach (var keyCode in this.ModeSwitchKeys) {
                if (Input.GetKeyDown(keyCode)) {
                    int currentIndex = Array.IndexOf(this.ControlModes, this.currentMode);
                    this.SetMode(this.ControlModes[(currentIndex + 1) % this.ControlModes.Length]);
                }
            }
        }
    }

    void SetMode(ControlMode mode) {
        if (this.currentMode == mode) {
            return;
        }
        if (this.currentMode != null) {
            this.currentMode.Behaviour.enabled = false;
        }
        this.currentMode = mode;
        this.currentMode.Behaviour.enabled = true;
    }
}

I’m not a big fan of using var frequently, and this is one reason. It makes it more difficult to read code because you have to figure out the type based on context instead of it written right there. What var means is you’re letting the compiler figure out the type based on how the variable is used.

Another thing in that code which is irritating is using “this” all over the place. That’s unnecessary, and makes the code look more complicated than it should.

This code from Update above:

        foreach (var mode in this.ControlModes) {
            if (Input.GetKeyDown(mode.KeyCode)) {
                this.SetMode(mode);
            }
        }

could be rewritten as below and be easier to read, as an example:

        foreach (ControlMode mode in ControlModes) {
            if (Input.GetKeyDown(mode.KeyCode)) {
                SetMode(mode);
            }
        }
2 Likes

Yes, it’s inferred from the rest of the line where it is declared. If the compiler can’t determine the type on that line, it won’t allow you to use var. You are only allowed to use var in a situation where using the actual type name would be redundant. As such, it never makes a functional difference, so deciding whether or not to use “var” is 100% about what is more convenient to you, the meatbag reading and writing the code.

The biggest reason I find to use var is code readability, while the biggest reason to avoid using it is code readability.
Pro: compare these functionally identical snippets:

Dictionary<string, List<FoobarClass>> someDict = new Dictionary<string, List<FoobarClass>>();
// blah blah add stuff
foreach (KeyValuePair<string, List<FoobarClass>> someKeyValue in someDict) {
List<FoobarClass> thisList = someKeyValue.Value;
foreach (FoobarClass thisItem in thisList) {
Debug.Log($"Iterating over {thisItem}");
}
}

OR

var someDict = new Dictionary<string, List<FoobarClass>>();
// blah blah add stuff
foreach (var someKeyValue in someDict) {
var thisList = someKeyValue.Value;
foreach (var thisItem in thisList) {
Debug.Log($"Iterating over {thisItem}");
}
}

In this example, the second snippet is drastically easier to read, because once you have the main type, everything else in the code is just the obvious sub-part of it. Including the type over and over again is just noise. So “var” is excellent here.

As a second example, imagine that you need to refactor this code to use BarfooClass instead of FoobarClass. In the first snippet, you have to replace the class at least 5 times. In the second, you only have to change it in the first line. Another win for “var”.

On the other hand:

var theThing = FindMyThing();

I have no idea what theThing is here, because FindMyThing()'s return type is not immediately obvious. “var” is terrible here.

A general rule of thumb: If you at a glance can, like the compiler, immediately tell what type the thing is by looking at the code immediately surrounding it, then “var” is probably fine to use.

3 Likes

Yes, however I can’t really understand the rest of that line:

C# is a statically typed language and every variable does have a certain type at compile time. The compiler infers the type of the variable from the value that is assigned to it. In the special case of a foreach loop it’s the “return value” from the Enumerable or the element type of the array the foreach loop is iterating over.

Some examples:

var myVar1 = 42;  // will be of type "int"
var myVar2 = "some text"; // will be of type "string"
var myVar3 = new SomeClass(); // will be of type SomeClass
var myVar4 = SomeMethod();  // myVar4 will have the same type as the return type of SomeMethod

Those cases should be obvious. Though the 4th case should be avoided unless it’s clear what type a method returns.

Your foreach loop is also an edge case. It’s often more readable to explicitly type your variables. However if the type is a long, nested type like in your example, it’s sometimes easier to read when you use “var” as the code gets shorter. Though there are no fix rules when to use it and when not. You should always keep in mind that the code should be readable and understandable. In some cases the actual type is irrelevant.

Note that “var” can only be used for local variables. You can not use it to declare class member variables.

Thanks, these are all very clear answers. The only bit I didn’t quite understand was @Bunny83

“In the special case of a foreach loop it’s the “return value” from the Enumerable or the element type of the array the foreach loop is iterating over.”

I’m not sure if the “enumerable” here means an Enum or if you just mean “whatever the type of the array is”. The other examples make sense, so I think I understand the general idea.

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1?view=net-5.0

var is you telling the compiler please figure out this variable without specifying the variable type.
int x is the same as var x, except that var requires more cpu work.

1 Like

It’s because the actual way foreach loops work is very complicated, even if the effects are usually simple enough. You think they only run over lists and each item is the type of item in the list – a foreach over List gives ints, for example. But that’s not the real rule. You can give any type a foreach, that does whatever you want, using any number of any type you want. Your new type Cow containing only a string can have a foreach which loops over 20 random numbers. For a real example, Unity lets you run a foreach over Transform, giving the children (which are also transforms). C# didn’t look for a list to foreach over – Unity told it to.

So technically how does a foreach know the type of each item in the loop? You give your class a thing called an enumerator, and foreach keys off of that.

But it’s still same rule – “var” turns into whatever type was required to be there, including in foreach’s.

I struggle myself to understand the point of var, I think properly declaring your variables at the very least as others have already pointed out makes it far easier for other people to read and understand your code. If var becomes a thing generally I can see it causing a lot of confusion especially if people post up pseudo code for example then it would just end up being annoying to read.

(Warning: long tangent with unnecessary information follows)
The real headtrip is seeing this and trying to figure out why coroutines in Unity are of type IEnumerator.

And then learning that Unity has basically grabbed and twisted the structure of an enumerator (which is intended to, say, iterate over a list) because it’s the only feature in C# that allows a block of code to be halted in the middle and resumed later. You can run a foreach loop over your coroutines and it’ll work, though you’ll likely get just nulls or 0’s if you try to use the values you’re foreach-ing through (whatever you use with “yield return”).

And then realizing that when Unity’s internal code iterates over these they must be using these yield return values, because they need to be able to check for yield return StartCoroutine(…)

1 Like

The funny part is that while the yield keyword is directly coupled with the IEnumerator / IEnumerable interface, the foreach loop actually doesn’t care about those interfaces at all, which seems strange at first. The C# compiler actually uses pattern matching. So the object you pass into the for each loop just need to have a GetEnumerator method and the type that is returned must have a MoveNext method and a Current property. That are all the requirements.

Eric Lippert, one of the lead developers of the MS C# compiler, has written this blog post about the pattern matching of the foreach loop. The second paragraph reads:

Though the enumerable pattern is not the only thing that the foreach loop supports. Arrays are supported natively and essentially generate the usual for loop equivalent. On the other hand when iterating over a generic List it does use the Enumerator that the class implements. Note that the List even implements a struct enumerator so it does not callocate any heap memory. There are quite a few quirks when it comes to the foreach loop ^^. In my SimpleJSON I also implemented a struct enumerator that just wraps both, the Dictionary enumerator and the List enumerator so the JSONNode can provide a single struct enumerator that supports both, a json object and a json array. There are also the Key and Value enumerators which in turn wrap the combined enumerator. If you look closely those structs can act as both, an enumerable and enumerator at the same time. In fact the GetEnumerator method just returns “this” ^^.

Anyways, this of course has little to do with the “var” keyword as it’s just about the foreach loop. Just keep in mind that var is always statically typed. So the type is definitely known at compile time. As we said a couple of times now, “var” should only be used when it’s obvious from the surrounding code what type it has. Something I use quite often is this:

var sw = new System.Diagnostics.Stopwatch();

Because I don’t want to import the “System.Diagnostics” namespace since it also contains a Debug class which gives us trouble with Unity’s Debug class, I always use the full type name. Here it’s clear what type the sw variable has and it’s more readable as

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

As I mentioned above, highly nested types will make things even worse. Since we just talked about the Enumerator struct of a dictionary, that’s actually a nested type. So the shortest way to refer to this nested type is

Dictionary<string, SomeClass>.Enumerator myVariable;

Which is quite ugly and can get even longer depending on the generic types.

It can be useful with stuff like this:

Dictionary<string,Dictionary<string,int>> repository = new Dictionary<string,Dictionary<string,int>>();

Typing Dictionary<string,Dictionary<string,int>> twice on one line is deep into repeating yourself territory.

or even stuff like:

PlayerCruiseShipController controller = new PlayerCruiseShipController();

Using var just turns down the visual clutter a bit.

1 Like

I thought var was introduced for C#'s built-in database query language; because for some of those results it’s literally impossible to write the return type. var is the only way to do it. I think they even recommended only using var for those (or in similar situations where the return type was overly-complicated and not all that important to know).

But C#-ers love new features, plus in old Unity it’s language Unityscript used var (based on older game engines, where declaring variables was considered complicated), so of course you’re going to use it sometimes in Unity-C#, even where it’s not the best choice.

Since I am using Rider I gradually shifted to use var. I used to hated it, but now I find it convenient and tolerable. But it is crucial that Rider has a very good hint system in place.

So you always know what the type of the variable is. Obviously in this example the definition happens only one line above, but you know, the same if it is completely detached.

So Dr. Strangelove or: How I Learned to Stop Worrying and Love the var.

1 Like