views:

303

answers:

4

MSDN categorizes var under Types.

variables that are declared at method scope can have an implicit type var

what does 'implicit type var' mean in this context?

Strictly said, if I have it to explain to fellow programmers.

Can I say; var is a Type, or do I have to say; var is a keyword that instructs the compiler to determine the type itself.

note: this is not meant to start a discussion about var, nor to learn the use of var. For once and for all I want to know excactly how to describe it and msdn is a bit confusing, that's it.

+13  A: 

var is a contextual keyword - along with yield, add and get for example.

In other words, you can use it as an identifer without prefixing it with @, but it still has a special meaning to the compiler in some places (i.e. where a type name is expected for a local variable declaration).

Using var to declare a local variable asks the compiler to infer the type of the variable based on the expression on the right hand side. For example:

var list = new List<string>();
var anon = new { Foo = "bar" };

The type of list is List<string>; the type of anon is an anonymous type, also introduced in C# 3. Part of the reason for introducing var in C# 3 was to allow for strongly typed variables using anonymous types - the variable still has the appropriate compile-time type, even though you couldn't explicitly state that type.

There are a few cases where var doesn't work, however, if the compiler doesn't have enough information:

var cantUseNull = null;
var cantUseLambda = x => x.Length;

There are others too. In each case you could just cast the expression on the right-hand side, so that the compiler knew what to use - but in that case you might as well just declare the variable explicitly instead.

<plug>
You can read more about this in C# in Depth. Fortunately, the chapter covering this is still available for free from the first edition page (you want chapter 8). I can't remember how much I've changed this chapter in the second edition...
</plug>

Jon Skeet
and can you please explain to me what an 'implicit type var' means in the msdn article as I quoted? Bit lost in translation here ;) SLightly edited the question, you where too fast...
Caspar Kleijne
@Caspar: It means you can use `var` to declare the type of the variable, in which case the compile-time type of the variable is the type of the expression on the right-hand side.
Jon Skeet
It's important not to lose the formatting there, it's 'implicit type **var** '. Var is an implicit typing in that the actual type is determined by the compiler from what is assigned to it, i.e. `var i = 10;`, as opposed to an explicitly typed variable, i.e. `int i = 10;` Implicit really means implied or inferred type. Does that help?
Lazarus
@Caspar: I've expanded my answer a bit - but if you download chapter 8 of C# in Depth first edition, that goes into a lot more detail :)
Jon Skeet
A: 

It's a bit of both. Technically, when using var, the variable is strongly typed, but the compiler determines the type. So I would say you'd be closest when saying 'var is a type'.

Cpt. eMco
A: 

var is a Type, like int is ... but what Type is it exactly??

Well, the compiler works that out for you (which is what implicitly means) based on the rest of the line.

e.g.

var b = "ahjhsad";

At compile time, var will be replaced with string.

var is used as a convenient short hand for the programmer, instead of having to write

List<string> myList = new List<string>();

a programmer can write

var myList = new List<string>();

and it means the same thing.

CVertex
Dang, you can't beat the skeet...
CVertex
"What is a type, exactly?" A good question. The C# specification does not actually *define* the word "type". It assumes you know what one is!
Eric Lippert
+10  A: 

Can I say var is a type, or do I have to say var is a keyword that instructs the compiler to determine the type?

It depends on how you look at it. Seriously!

The C# compiler does three kinds of analysis on programs, each subsequent analysis consuming the result of the previous one. The first kind of analysis we do is lexical analysis; we take the text and turn it into a series of tokens. Suppose you have

class C { static void Main(){ var x = 123; } }

We first determine that those tokens are CLASS IDENTIFIER(C) LEFTBRACE STATIC VOID IDENTIFIER(Main) LEFTPAREN RIGHTPAREN LEFTBRACE IDENTIFIERTHATMIGHTBEAKEYWORD(var) IDENTIFIER(x) EQUALS INTEGER(123) SEMICOLON RIGHTBRACE RIGHTBRACE.

At this stage of analysis, "var" is an identifier with a note on it that says that it might be the keyword var, not the identifier var.

The next analysis we do is a grammatical analysis where the tokens are organized into groups that form a "parse tree". In this case the tokens would be organized into this tree (indentation indicates nesting level in the tree)

declaration of class: CLASS
  class name: IDENTIFIER(C)
  class body begins: LEFTBRACE
    declaration of method:
      method modifier: STATIC
      return type: VOID
      method name: IDENTIFIER(Main)
        formal parameter declarations:
          formal parameter declarations begin: LEFTPAREN
          formal parameter declarations end: RIGHTPAREN
        method body:
          method body begins: LEFTBRACE
            local declaration statement:
              type: IDENTIFIERTHATMIGHTBEAKEYWORD(var)
              local name: IDENTIFIER(x)
              initializer:
                assignment operator: EQUALS
                integer literal expression: INTEGER(123)
              statement ends: SEMICOLON
           method body ends: RIGHTBRACE
  class body ends: RIGHTBRACE

At this point var has been classified as a type, grammatically. It it in the place we would expect a type declaration if this is a grammatically legal program.

But at this point we do not know whether "var" refers to a type or is being used as a keyword. That requires semantic analysis.

When we do the semantic analysis of the parse tree we say "OK, there's a class C, it's got a method Main, which declares a local variable x. What is the type of that local variable?"

At this point there are two possibilities. The first possibility is that there is a class, struct, enum, interface or delegate type named "var" in the global namespace. (There are no "using" directives in this program fragment so we don't have to check any other namespaces, and the type is not partial so we don't have to check any other type declarations). We search the global namespace of all the referenced assemblies looking for a type called "var". We also do semantic analysis of the type declarations in all other files, again, looking for a type called var.

If we find one, then "var" refers to that type.

If we don't find one then we assume that "var" is being used as a contextual keyword that introduces an implicitly typed local.

So, to answer your question:

Lexically, the code fragment "var" is an identifier token with a note on it that says "by the way, this might actually be a keyword".

Grammatically, the token "var" is a type when it appears at a position in the grammar where a type is expected.

Semantically, the type syntax "var" is a type when there is a type in scope called var; if there is no such type and "var" is being used as the type of a local declaration then the type syntax "var" does not refer to a type. Rather, it is an instruction to the compiler to infer the actual type of the local.

Eric Lippert
Thanks for the answer, I indeed saw that public class var{} overrules var keyword as you described,so your explanation really makes sense to me, thanks! PS:Does this mean I have to demote Jon ? ;)
Caspar Kleijne
and in the code IDENTIFIERTHATMIGHTBEAKEYWORD is the thing that does it, that in var x= 123, var might be a keyword
Caspar Kleijne
I had no idea you could create a type `var` that would override the keyword, but I suppose it's necessary to preserve backward compatibility. Out of curiosity, is there a way to still use `var` as a keyword, even if such a type is in scope?
Dan Bryant
@Dan: Nope. There is a syntax for "I mean this to be an identifier" which is to prefix the keyword with @. But there is no syntax that goes the other way.
Eric Lippert