This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Use of var keyword in C#
Being relatively new to C# I was wondering the motivation MS had to introduce the var implicit typed variables. The documentation says:
An implicitly typed local variable is strongly typed just as if you
had declared the type yourself, but the compiler determines the type.
Some lines further:
In many cases the use of var is optional and is just a syntactic
convenience
This is all nice but in my mind, this will only cause confusion.
Say you are reviewing this for loop.
foreach (var item in custQuery){
// A bench of code...
}
Instead of reviewing the content and the semantics of the loop, I would loose precious time looking for the item's type!
I would prefer the following instead:
foreach (String item in custQuery){
// A bench of code...
}
The question is: I read that implicit typed variables help when dealing with LINQ, does really help to use it in other scenarios?
The var keyword was needed when LINQ was introduced, so that the language could create a strongly typed variable for an anonymous type.
Example:
var x = new { Y = 42 };
Now x is a strongly typed variable that has a specific type, but there is no name for that type. The compiler knows what x.Y means, so you don't have to use reflection to get to the data in the object, as you would if you did:
object x = new { Y = 42 };
Now x is of the type object, so you can't use x.Y.
When used with LINQ it can for example look like this:
var x = from item in source select new { X = item.X, Y = item.Y };
The x variable is now an IEnumerable<T> where T is a specific type which doesn't have a name.
Since the var keyword was introduced, it has also been used to make code more readable, and misused to save keystrokes.
An example where it makes the code more readable would be:
var list =
new System.Collections.Generic.List<System.Windows.Forms.Message.Msg>();
instead of:
System.Collections.Generic.List<System.Windows.Forms.Message.Msg> list =
new System.Collections.Generic.List<System.Windows.Forms.Message.Msg>();
This is a good use of the var keyword, as the type already exists in the statement. A case where the keyword can be misused is in a statement like:
var result = SomeMethod();
As the SomeMethod name doesn't give any indication of what type it returns, it's not obvious what the type of the variable will be. In this case you should write out the type rather than using the var keyword.
I think some of the motivation was to allow something like this -
List<int> list = new List<int>();
to be turned into this -
var list = new List<int>();
The second example is shorter and more readable, but still clearly expresses the intent of the code. There are instances when it will be less clear, but in lots of situations you get conciseness with no loss of clarity.
var is really needed for anonymous types, which are used in Linq a bit:
var results =
from item in context.Table
select new {Name=item.Name, id=item.id};
Since the collection is of an anonymous type, it can not be named. It has a real type, but not one with a name before compilation.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Apologies in advance if the question is opinion based. Why would you pick the first variant of the following three, while declaring local variables in C#?
var list1 = new List();
List list2 = null;
var list1 = new List();
var list2 = (List)null;
// this variant would allow easy refactoring from class to struct
var list1 = new List();
var list2 = default(List);
While this is impossible:
var list1 = new List(), list2 = null;
EDITED to provide the context:
void DoSomething(Action action) { /* ... */ }
// ..
var list1 = new List();
List list2 = null;
// ...
DoSomething(() => { list2 = new List(); list2.Add(1); });
var is shorter and some people prefer it over specifying the type explicitly. In the context of anonymous types, you don't have an option except to use var, such as in
var point = new { X = 1, Y = 2 }
var is only syntactic sugar though. Not specifying the type does not mean it's dynamic. It only means the compiler will infer the type from usage. In the end, the compiled code is the same.
Within our team, we have a standard to use var on the left side when the right side is one of the following:
New object construction
Cast
Anonymous
In all other cases our internal standard does not allow var because in other cases it may not be explicitly clear what the variable type is to the reader (even though the compiler knows). For example, if you have a statement like this:
var x = SomeMethod();
What is the type of x? The compiler knows because it knows what SomeMethod() returns. Do you remember off-hand? Do you remember for every method in your application? We find it more expressive to not use var in these cases.
For a null value, I would always specify the type. Casts and such seem like just an odd mechanism to allow you to use var when it really gains you nothing.
List list = null;
In case 2, all that you're doing is telling the compiler that list is going to be a List type object, and it will be initialized to null. You could do that, but it's a roundabout way of declaring a variable as being of type List.
You would only want to use case 3 if you're dealing with generics. The point of it being that you may not know if the type is a reference type or a value type, var list = null is not a valid statement for value types. The default keyword will ensure that either null is set for reference types and 0 for value types.
Answer:
According to MSDN Reference: Implicitly Typed Local Variables
var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
So, as far as a question to a real problem goes, this probably isn't a very good question, but it's bugging me and I can't find an answer, so I consider that to be a problem.
What is the specificity of var? The MSDN reference on it states the following:
An implicitly typed local variable is strongly typed just as if you had declared the type yourself
Bur it doesn't seem to say anywhere what type it is strongly typed for. For example, if I have the following:
var x = new Tree();
But I then don't call any methods of Tree, is x still strongly typed to tree? Or could I have something like the following?
var x = new Tree();
x = new Object();
I'm guessing this isn't allowed, but I don't have access to a compiler right now, and I'm really wondering if there are any caveats that allow unexpected behaviour like the above.
It's strongly typed to the type of the expression on the right side:
The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement.
From here.
It's tied to the type on the right-side of the equals-sign, so in this case, it is equivalent to:
Tree x = new Tree();
Regardless of whatever interface or base classes are tied to Tree. If you need x to be of a lower type, you have to declare it specifically, like:
Plant x = new Tree();
// or
IHasLeaves x = new Tree();
Yes, in your example x is strongly typed to Tree just as if you had declared the type yourself.
Your second example would not compile because you are redefining x.
No, it is exactly the same, had you typed Tree x = new Tree();. Obviously the only unambiguous inference the compiler can do is the exact type of the right hand side expression, so it won't suddenly become ITree x
So this doesn't work:
Tree x = new Tree();
x = new Object(); //cannot convert implicitly
If you are curious, the dynamic is closer to the behavior you expect.
dynamic x = new Tree();
x = new Object();
In the example:
var x = new Tree();
is the same as
Tree x = new Tree();
I've found it is always better to use "var" since it facilitates code re-factoring.
Also, adding,
var x = new Object();
in the same scope would break compilation due to the fact that you cannot declare a variable twice.
var is neither a type nor does it make the variable something special. It tells the compiler to infer the type of the variable AT COMPILE TIME by analyzing the initialization expression on the right hand side of the assignment operator.
These two expressions are equivalent:
Tree t = new Tree();
and
var t = new Tree();
Personally I prefer to use var when the type name is mentioned explicitly on the right hand side or when the exact type is complicated and not really relevant as for results returned from LINQ queries. These LINQ results are often just intermediate results that are processed further:
var x = new Dictionary<string, List<int>>();
is easier to read than the following statement and yet very clear:
Dictionary<string, List<int>> x = new Dictionary<string, List<int>>();
var query = someSource
.Where(x => x.Name.StartsWith("A"))
.GroupBy(x => x.State)
.OrderBy(x => x.Date);
Here query is of type IOrderedEnumerable<IGrouping<string, SomeType>>. Who cares?
When the type name does not appear on the right hand side and is simple, then I prefer to write it explicitly as it doesn't simplify anything to use var:
int y = 7;
string s = "hello";
And of cause, if you create anonymous types, you must use var because you have no type name:
var z = new { Name = "Coordinate", X = 5.343, Y = 76.04 };
The var keyword was introduced together with LINQ in order to simplify their use and to allow to create types on the fly in order to simulate the way you would work with SQL:
SELECT Name, Date FROM Person
var result = DB.Persons.Select(p => new { p.Name, p.Date });
I am trying to parallelize a query with a groupby statement in it. The query is similar to
var colletionByWeek = (
from item in objectCollection
group item by item.WeekStartDate into weekGroups
select weekGroups
).ToList();
If I use Parallel.ForEach with shared variable like below, it works fine. But I don't want to use shared variables in parallel query.
var pSummary=new List<object>();
Parallel.ForEach(colletionByWeek, week =>
{
pSummary.Add(new object()
{
p1 = week.First().someprop,
p2= week.key,
.....
});
}
);
So, I have changed the above parallel statement to use local variables. But the compiler complains about the source type <IEnumerable<IGrouping<DateTime, object>> can not be converted into System.Collections.Concurrent.OrderablePartitioner<IEnumerable<IGrouping<DateTime, object>>.
Am I giving a wrong source type? or is this type IGouping type handled differently? Any help would be appreciated. Thanks!
Parallel.ForEach<IEnumerable<IGrouping<DateTime, object>>, IEnumerable<object>>
(spotColletionByWeek,
() => new List<object>(),
(week, loop, summary) =>
{
summary.Add(new object()
{
p1 = week.First().someprop,
p2= week.key,
.....
});
return new List<object>();
},
(finalResult) => pSummary.AddRange(finalResult)
);
The type parameter TSource is the element type, not the collection type. And the second type parameter represents the local storage type, so it should be List<T>, if you want to Add() to it. This should work:
Parallel.ForEach<IGrouping<DateTime, object>, List<object>>
That's assuming you don't actually have objects there, but some specific type.
Although explicit type parameters are not even necessary here. The compiler should be able to infer them.
But there are other problems in the code:
you shouldn't return new List from the main delegate, but summary
the delegate that processes finalResult might be executed concurrently on multiple threads, so you should use locks or a concurrent collection there.
I'm going to skip the 'Are you sure you even need to optimize this' stage, and assume you have a performance issue which you hope to solve by parallelizing.
First of all, you're not doing yourself any favors trying to use Parallel.Foreach<> for this task. I'm pretty sure you will get a readable and more optimal result using PLINQ:
var random = new Random();
var weeks = new List<Week>();
for (int i=0; i<1000000; i++)
{
weeks.Add(
new Week {
WeekStartDate = DateTime.Now.Date.AddDays(7 * random.Next(0, 100))
});
}
var parallelCollectionByWeek =
(from item in weeks.AsParallel()
group item by item.WeekStartDate into weekGroups
select new
{
p1 = weekGroups.First().WeekStartDate,
p2 = weekGroups.Key,
}).ToList();
It's worth noting that there is some overhead associated with parallelizing the GroupBy operator, so the benefit will be marginal at best. (Some crude benchmarks hint at a 10-20% speed up)
Apart from that, the reason you're getting a compile error is because the first Type parameter is supposed to be an IGrouping<DateTime, object> and not an IE<IG<..,..>>.
The only advantage I can see to do:
var s = new ClassA();
over
ClassA s = new ClassA();
Is that later if you decide you want ClassB, you only have to change the RHS of the declaration.
I guess if you are enumerating through a collection you can also just to 'var' and then figure out the type later.
Is that it?? Is there some other huge benefit my feeble mind does not see?
It's mostly syntactic sugar. It's really your preference. Unless when using anonymous types, then using var is required. I prefer implicit typing wherever possible though, it really shines with LINQ.
I find it redundant to type out a type twice.
List<string> Foo = new List<string>();
When I can easily just type var when it's obvious what the type is.
var Foo = new List<string>();
var is useful for anonymous types, which do not have names for you to use.
var point = new {X = 10, Y = 10};
This will create an anonymous type with properties X and Y. It's primarily used to support LINQ though. Suppose you have:
class Person
{
public String Name {get; set;}
public Int32 Age {get; set;}
public String Address {get; set;}
// Many other fields
}
List<Person> people; // Some list of people
Now suppose I want to select only the names and years until age 18 of those people who are under the age of 18:
var minors = from person in people where person.Age < 18 select new {Name = person.Name, YearsLeft = 18 - person.Age};
Now minors contains a List of some anonymous type. We can iterate those people with:
foreach (var minor in minors)
{
Console.WriteLine("{0} is {1} years away from age 18!", minor.Name, minor.YearsLeft);
}
None of this would otherwise be possible; we would need to select the whole Person object and then calculate YearsLeft in our loop, which isn't what we want.
I started what turned out to be a hugely controversial thread when I first signed on here (my choice of "evilness" to describe general use of var was obviously a terrible choice.) Needless to say, I have more appreciation for var than I did before I started that thread, as well as a better understanding of how it can be usefully used:
The evilness of 'var' in C#?
Some good reasons to use var:
Brevity
Reduction of Repetition (DRY)
Reduced refactoring effort
Supports anonymous types (key reason it was added to C#)
Have a look at this questions. Maybe they'll help you decide.
Use of var keyword in C#
https://stackoverflow.com/questions/633474/c-do-you-use-var
It allows me to not repeat myself unnecessary. Consider this:
Dictionary<string, List<int>> dict = new Dictionary<string, List<int>>();
We have a very long typename repeated twice on the same line twice with absolutely no benefit. Furthermore, if you ever need to refactor this, you'll need to update the type twice. Whereas this is just as expressive:
var dict = new Dictionary<string, List<int>>();
There's still no doubt about type of dict here, but the code is shorter, and I would claim that it is easier to read as well.
Actually "var" in C# is used to deal with anonymous type.
Like:
var t = new {number = 10, name = "test"};
The overarching reason for the implicit typing was to support anonymous types, like those produced by LINQ queries. They can also be a big benefit when dealing with complex-typed generics...something like Dictionary<int,List<string>>. That's not too complex, but imagine enumerating...
foreach KeyValuePair<int,List<string>> pair in myDictionary
{
}
is simplified with implicit typing.
While the var keyword was primarily introduced to support anonymous types, the main argument I've seen for using it more widely is for brevity/more readable code, plus fitting more on your line of code:
Dictionary<string, double> data = new Dictionary<string, double>();
versus
var data = new Dictionary<string, double>();
Though not a good reason for most people, I also like the var keyword as a blind programmer, as I listen to the code being read out and thus here the variable name after just one syllabul :-)
I'm trying to loop through the results of a function that is returning an anonymous object of results.
public static object getLogoNav()
{
XDocument loaded = XDocument.Load(HttpContext.Current.Request.MapPath("~/App_Data/LOGO_NAV_LINKS.xml"));
var query = from x in loaded.Elements().Elements()
select new
{
Name = x.FirstAttribute.Value,
Value = x.Value
};
return query;
}
codebehind page:
var results = Common.getLogoNav();
foreach(var nav in results) {
string test = nav.Name;
}
You can't have an anonymous class as a return type in C# 3 (and 4 for that matter) and you can't cast an object to an anonymous type. Your three options are:
Doing the loop within the scope of the anonymous class (most of the time, this is the method)
Casting to object and using reflection (slow and not very easy to do unless you do some expression tree magic)
Converting to a named class and returning and instance of that.
(In C# 4) you can create some dynamic type magic to achieve a similar effect but that would be really the same as option 2 with some syntactic sugar.
Jon Skeet wrote an entry about returning anonymous type. I hope you don't use it.