What to use: var or object name type? [duplicate]
This question already has an answer here:
- Use of var keyword in C# 86 answers
this is a question that when programming I always wonder: What to use when we are writing code:
var myFiles = Directory.GetFiles(fullPath);
string myFiles = Directory.GetFiles(fullPath);
var is new and is a Implicitly Typed Local Variables, so we can only use locally and it has rules like can't be null, etc., but I wonder if we get any advantage of using it "normally".
The "normally" part says, not in Anonymous Types, Object and Collection Initializers and Query Expressions where that was the intent to use the var anonymous object, so what I mean is... just like the example above.
what are your thoughts?
Beyond the obvious use of
var with LINQ, I also use it to abbreviate hairy variable declarations for readability, e.g.:
var d = new Dictionary<string, Dictionary<string, Queue<SomeClass>>>();
In general, I get a kind of comfort (for want of a better word) from static typing that makes me reluctant to give it up. I like the feeling that I know what I'm doing when I'm declaring a variable. Declaring a variable isn't just telling the compiler something, it's telling the person reading your code something.
Let me give you an example. Suppose I have a method that returns a
List<string>. This code is certainly correct, and I think it's how 90% of C# developers would probably write it:
List<string> list = MyMethod();
Obviously, right? In fact, here's a place you could just as easily use
True enough. But this version of the code isn't just declaring a variable, it's telling me what the person who wrote it is intending to do:
IEnumerable<string> list = MyMethod();
The developer who wrote that code is telling me "I'm not going to be changing this list, nor am I going to use an index to access its members. All I'm going to do is iterate across it." That's a lot of information to get across in a single line of code. It's something you give up if you use
Of course, you're not giving it up if you weren't using it in the first place. If you're the kind of developer who would write that line of code, you already know that you wouldn't use
I just reread Jon Skeet's post, and this quote from Eric Lippert jumped out at me:
Implicitly typed locals are just one small way in which you can deemphasize the how and thereby emphasize the what.
I think that actually in a lot of cases using implicit typing is leaving the what implicit. It's just OK to not dwell on the what. For instance, I'll casually write a LINQ query like:
var rows = from DataRow r in parentRow.GetChildRows(myRelation) where r.Field<bool>("Flag") orderby r.Field<int>("SortKey") select r;
When I read that code, one of the things I think when I'm reading it is "
rows is an
IEnumerable<DataRow>." Because I know that what LINQ queries return is
IEnumerable<T>, and I can see the type of the object being selected right there.
That's a case where the what hasn't been made explicit. It's been left for me to infer.
Now, in about 90% of the cases where I use LINQ, this doesn't matter one tiny little bit. Because 90% of the time, the next line of code is:
foreach (DataRow r in rows)
But it's not hard to envision code in which it would be very useful to declare
IEnumerable<DataRow> - code where a lot of different kinds of objects were being queried, it wasn't feasible to put the query declaration next to the iteration, and it would be useful to be able inspect
rows with IntelliSense. And that's a what thing, not a how thing.
You'll get a huge variety of opinions on this one - from "use var everywhere" to "only use var with anonymous types, where you basically have to." I like Eric Lippert's take on it:
All code is an abstraction. Is what the code is “really” doing is manipulating data? No. Numbers? Bits? No. Voltages? No. Electrons? Yes, but understanding the code at the level of electrons is a bad idea! The art of coding is figuring out what the right level of abstraction is for the audience.
In a high level language there is always this tension between WHAT the code does (semantically) and HOW the code accomplishes it. Maintenance programmers need to understand both the what and the how if they’re going to be successful in making changes.
The whole point of LINQ is that it massively de-emphasizes the "how" and massively emphasizes the "what". By using a query comprehension, the programmer is saying to the future audience "I believe that you should neither know nor care exactly how this result set is being computed, but you should care very much about what the semantics of the resulting set are." They make the code closer to the business process being implemented and farther from the bits and electrons that make it go.
Implicitly typed locals are just one small way in which you can deemphasize the how and thereby emphasize the what. Whether that is the right thing to do in a particular case is a judgment call. So I tell people that if knowledge of the type is relevant and its choice is crucial to the continued operation of the method, then do not use implicit typing. Explicit typing says "I am telling you how this works for a reason, pay attention". Implicit typing says "it doesn’t matter a bit whether this thing is a List or a Customer, what matters is that it is a collection of customers."
Personally I don't tend to use it if the type isn't reasonably obvious - where I include LINQ queries as being "reasonably obvious". I wouldn't do it for
Directory.GetFiles for instance, as it's not really obvious that that returns a
string instead of (say) a
FileInfo (or something else entirely) - and that makes a big difference to what you do later.
If there's a constructor call on the right hand side of the assignment operator, I'm much more likely to go with
var: it's blatantly obvious what the type will be. This is particularly handy with complex generic types, e.g.
Personally I only use var in two places:
- With anonymous types, ie. LINQ-related (where var is required in some cases)
- When the statement declares and constructs a specific type at the same type
ie. this is an example of point 2:
var names = new List<String>();
Edited: This in response to Jon Skeet's question.
The above answer was in fact simplified. Basically, I use var where the type is either:
- Unnecessary to know (not that many places though)
- Impossible to know (LINQ, anonymous types)
- Otherwise known, or clear from the code
In the case of a factory method, where all you need to know at the place where you write the code is that the object you get back is a descendant of some type, and that some type has a static factory method, then I would use var. Like this:
var connection = DatabaseConnection.CreateFromConnectionString("...");
The above example is a real example from my code. It is clear, at least to me and the people that use this code, that connection is a DatabaseConnection descendant, but the exact type is not needed for neither understanding the code, nor using it.
I tried the "use var everywhere" style... and here is why I didn't continue to use it.
- Degraded readability at times
- Limits Intellisense after =
- Typing "var" really wasn't much shorter than typing "int", "string", etc., especially with intellisense.
With that said, I DO still use it with LINQ.
Coming from the land of functional programming, where type-inference rules the day, I use
var for all locals wherever possible.
In Visual Studio, if you are ever wondering what the type of any local is, all you have to do is hover over it with your mouse.
This post have some good guidlines on when to use var type interface or object types.
I tend to use
var everywhere, but my co-workers said stop, it is less readable to us. So I now I use
var only on anonymous types, LINQ queries and where is constructor on right side.
I think it's interesting to note how this is usually handled in Haskell. Thanks to the Curry-Howard isomorphism, the (most general) type of any expression in Haskell can be inferred, and thus type declarations are essentially not required anywhere, with a few exceptions; for example, sometimes you deliberately want to limit the type to something more specific than would be inferred.
Of course, what is required and what is recommended are not the same thing; in practice, the convention seems to be that top-level definitions always have type declarations, while localised definitions have the type declarations left out. This seems to strike a good balance between explicitness-for-readability of the definition as a whole, contrasted with brevity-for-readability of the local "helper" or "temporary" definitions. If I understand correctly, you can't use
var for "top-level" definitions (like a method or global function) in the first place, so I guess this translates to "use
var everywhere you can" in C# world. Of course, typing "
int" is the same number of keystrokes as "
var", but most examples will be longer than that.