In C#, how do inferred variables using var behave with respect to memory and lifecycle?
Ok, I've been reading everything I can find on var, and I'm pretty sure I've got a handle on their basic behaviors and type inference. I've always been a big proponent of explicit types, so var makes me a little edgy when I'm reading code. So I have a couple of questions regarding its memory usage and the behavior of a variable declared with var over the course of that variable's lifecycle in memory.
Since var is an inference to an explicit or anonymous type, will its memory be allocated in the same place its corresponding type would be or is var universally created on the heap and accessed as if it were an object. As an example:
int i = 5; // puts this on the stack
var i = 5; // does this also go on the stack?
Does a declared var have a constant type once it is initialized or can it be adjusted as well? I ask this because I can't find in the documentation that specifies this, and I just read something in this SO question by @Eric Lippert:
a variable is a storage location whose contents change
Having tested the following code, I see an implicit conversion exception even at the IDE level. I don't have the experience with LINQ at this point to run a similar test with respe开发者_开发知识库ct to anonymous types. Do they follow this same behavior? Will the IDE recognize a type mismatch at design time or would such code receive a run-time exception?
var i = 5; // Initializes as int, value is 5
i = "Steve"; // Type casting error
Finally, is there ever a situation that you can think of where you may know a type at design time but it would be prudent to use var anyway? I ask because I've seen code samples where people do this, and from what I've read it strikes me as just lazy-coding.
EDIT: I realize there are a lot of articles talking about this topic, but I haven't found any that answer these questions specifically (though some hint one way or another). I would be happy to read any document you feel is relevant to these topics, just please post a link.
var
is 100% syntactic sugar in the C# compiler. When the actual IL is generated, the type is explicitly defined. var
-declared variables do not behave any differently from their explicitly-defined counterparts. The dearth of information you're seeing is coming from the fact that var
is simpler than you're assuming. There is quite literally no difference between these two lines:
var i = 10;
int j = 10;
(Other than the fact that you see the words var
and int
, of course; they are functionally completely identical).
var variables are infered by the compiler, they are really just syntactical sugar, there is no difference between:
var i =0;
and
int i = 0;
in the compiled code.
They were added for the purpose of allowing anonymous types, e.g.
var MyVar = new { prop1="A string", prop2=5};
Yes var varables recognise a type mismatch at compile time, the compiler dynamically creates a class for them when it compiles. e.g. the below would not compile:
var MyVar = new { prop1="A string", prop2=5};
MyVar = "Fred";
As others have said, var
has no effect on how the variables behave in terms of memory - it just means you don't specify the name. For anonymous types you couldn't specify the name, first because you don't know it at compile time, and second because the names are deliberately "unspeakable" - they're not valid in C#. (Generally they contain <>
for example.)
The IL generated for code using var
and code using an explicit name is exactly the same. Just as a normal variable can't change type, nor can a variable declared using var
... so in your example where you try to assign the value "Steve" to a variable which has an implicit type of int
, you'll get a compile-time error exactly as if you'd explicitly declared it to be of type int
.
As for when to use var
and when not to, I have a few rules of thumb:
- Obviously if you want the variable to have a type other than the compile-time type of the assigned expression, you've got to do it explicitly
- For constructor calls, it's always clear what the the type is even if you're using
var
var
is useful for emphasizing what the code is meant to do rather than how- Often I use
var
if the explicit name would be extremely long - particularly for generics with multiple type arguments.
Basically it's all about readability: if the code is easier to read using var
, go for it. If not, don't. Note that this isn't the same as saving typing... code is generally read more than it's written, so think about your reader. Eric Lippert wrote a great note when tech reviewing the first edition of C# in Depth, which is worth a read.
Simple answer: exactly the same as normal variables.
var
declarations are translated into specific (strong) types at compile-timee. var
is simply a method of automatic type inference, and has nothing to do with dynamic languages. At the end of the day, it's just the compiler being clever and translating var
into what actual type you want.
"Since var is an inference to an explicit or anonymous type, will its memory be allocated in the same place its corresponding type would be or is var universally created on the heap and accessed as if it were an object"
The important thing about var, is that the compiler changes the var statement to the actual type at compile time, so:
var number = 1;
Will get changed to:
System.Int32 number = 1;
...by the compiler. And as such the memory locations for storage of these types is no different. var is essentially syntactic sugar. So, method local declarations of value types will get stored on the stack, reference pointers will get stored on the stack with the referenced objects on the heap.
Once you have declared a variable as var, because this is translated into its full type by the compiler, you can't then dynamically change the type:
var i = 5;
i = "Steve";
...is invalid, because its already been declared as an Int32.
Anonymous types follow a similar behaviour, where a type is created by the compiler during compilation.
"Finally, is there ever a situation that you can think of where you may know a type at design time but it would be prudent to use var anyway?"
Personally, I follow a simple pattern:
For primitives, I always put the type:
int i = 5;
string name = "Matt";
For complex types, I mostly do this:
var instance = new MyComplexTypeInstance();
For LINQ results, I stick to var:
var result = from i in something select i;
For methods, if the method is descriptive of the type being returned, then I will use var.
var instance = GetInstance();
Whereas, more complex method names, I'd put the actual type:
Result result = DoSomethingWeirdAndWonderful();
Each developer will find something they are comfortable with, the choice is yours. As var is only really a design-time thing, its all syntactic sugar.
精彩评论