29
class A
{
    A()
    {
        var x = 5;   // this is allowed
    }

    var _x = 5;   // the compiler is unhappy
}

I guess the compiler must be able to deduce the type for the member variable just the same way it does it for the local one. So what's the difference?

David Klempfner
  • 8,700
  • 20
  • 73
  • 153
armen
  • 335
  • 3
  • 6
  • because you can't use var out of a method. You can't declare a global var and since constructors are also methods, you don't get the error. – Pabuc Dec 16 '10 at 14:15
  • 1
    @Pabuc: What are you talking about? – SLaks Dec 16 '10 at 14:17
  • 7
    I think nearly all the explanations below are garbage, except for the fleeting references to [Lippert's post](http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx). The answer: because it's a lot of work given the way the compiler is built today. It's an internal problem. – Michael Haren Dec 16 '10 at 14:18
  • @SLaks: I'm talking about the same thing you're talking about. You can't declare a var out of a method and since constructors are also methods, you can.. – Pabuc Dec 16 '10 at 14:20
  • @Pabuc: Sorry; I misunderstood. – SLaks Dec 16 '10 at 14:54
  • My take:Class level variable will be only come into picture with an object instance of that particular class. Now the objects are instantiated at run time and since compiler needs the information for var at the compile time so definitely class level variable can not be declared as var. But methods are actually part of the class, not a part of each instance object itself. Object can only call the methods. So, method level variables can be initialized in the compile time only as it does have to wait till object instantiation at run time. So, var can be used to declare the method level variables. – shantanu ghosh Mar 26 '23 at 19:21

4 Answers4

27

Eric Lippert answered your question right here: Why no var on fields?

Basically, for the general case it would require re-writing the C# compiler, as the way it currently does type inference would not work for cycles of var field variable assignments.

eugen
  • 464
  • 5
  • 16
thecoop
  • 45,220
  • 19
  • 132
  • 189
9

The var keyword was designed for anonymous types, which can only be used inside of a method.

Also, you're wrong; the compiler cannot always deduce a var field.

What happens if you compile the following:

class A {
    public readonly var value = B.value;
}

class B {
    public readonly var value = B.value;
}

This situation is impossible to recreate with local variables, since a variable cannot be referenced before it's defined.

The general problem here is that you're asking the compiler to consume type information while it's still generating that information.
Eric Lippert explains in greater depth.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 8
    If the var feature was only designed for anonymous types they would disallow the use of it with regular variables. Eric Lippert himself says that he would like to have this feature work with fields but they have problems with imeplementation, not design conflict. – Stilgar Dec 16 '10 at 14:20
  • 1
    You: _anonymous types, which can only be used inside of a method_ One can ask then why anonymous types cannot be used in fields. It is possible to have a field initializer (to a field of explicit type `object` or `dynamic`) which assigns an instance of an anonymous type to that field. E.g. `static object Field = new { Cost = 3.5m, Age = 2, };`. It is also possible to have a field whose compile time type is a type parameter, like `static T Field` where `T` is from a generic containing class, and then have `T` become an anonymous type by type inference in a static factory method. – Jeppe Stig Nielsen Apr 23 '14 at 20:47
  • @JeppeStigNielsen: I mean a field of (compile-time) anonymous type. – SLaks Apr 23 '14 at 21:53
  • 1
    Yes, I know, but that could have been allowed, too, had `var` been allowed in fields. As I said, the closest we get is stuff like `var instance = Tuple.Create(new { Name = "Laks", });`. Here `intance` has a property `Item1` (and backing field) of compile-time type `T1`, but `T1` equals the anonymous type with a sole parameter, `new { Food = true, }` – Jeppe Stig Nielsen Apr 23 '14 at 22:23
  • 1
    "This situation is impossible to recreate with local variables" -- incorrect. A local variable is in lexical scope within its own initializer, and its type can influence overload resolution and therefore potentially the type of the initializer. http://ideone.com/IQ4e80 – Ben Voigt Nov 06 '14 at 15:14
2

I see two reasons:

  1. It might be desirable to make the declaration of types in a public interface explicit
  2. It's hard to implement. The C# compiler compiles in multiple phases.
    At first it parses everything apart from method bodies so it knows about everything outside of function bodies. Then it can use that information to compile method bodies individually. What happens while compiling one method body hasn't much effect on what happens when compiling other method bodies.
    If you could use var for fields the expression body of the field initializer would affect the type of the field and thus many other methods. So it doesn't fit the compiler design well.
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
0

This is a guess, but initialization of class-level fields must be done as part of the initialization (constructor) process for a Type, whereas initialization of a method-level variable happens when the method's stack frame is constructed. Perhaps the distinction is related to how these processes are compiled (how their implementation is created) inside the framework.

Charles Bretana
  • 143,358
  • 22
  • 150
  • 216