This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use of var keyword in C#
After discussion with colleagues regarding the use of the 'var' keyword in C# 3 I wondered what people's opinions were on the appropriate uses of type inference via var?
For example I rather lazily used var in questionable circumstances, e.g.:-
foreach(var item in someList) { // ... } // Type of 'item' not clear.
var something = someObject.SomeProperty; // Type of 'something' not clear.
var something = someMethod(); // Type of 'something' not clear.
More legitimate uses of var are as follows:-
var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.
Interestingly LINQ seems to be a bit of a grey area, e.g.:-
var results = from r in dataContext.SomeTable
select r; // Not *entirely clear* what results will be here.
It's clear what results will be in that it will be a type which implements IEnumerable, however it isn't entirely obvious in the same way a var declaring a new object is.
It's even worse when it comes to LINQ to objects, e.g.:-
var results = from item in someList
where item != 3
select item;
This is no better than the equivilent foreach(var item in someList) { // ... } equivilent.
There is a real concern about type safety here - for example if we were to place the results of that query into an overloaded method that accepted IEnumerable<int> and IEnumerable<double> the caller might inadvertently pass in the wrong type.
Personally I find the circumstances you describe far from questionable, since there is no point in repeating yourself unless you specifically want the static type of a variable to be different than the static type of the expression used to initialize the variable. For example:
IEnumerable<int> foo = new List<int>(); // It's IEnumerable on purpose
Furthermore, there are absolutely no type safety concerns with var. The point is not that the variable can be of "any" type. It is of a very specific type, but you simply do not care to spell that type out.
I'm only using it as a place holder until I'm sure which datatypes I'm using.
Sure this is a short answer but I think it's pretty close that when you should use the var keyword.
the var keyword is used as shorthand in the language, but isn't a .NET type. The compiler must know the type of the variable to use the var keyword - so it is type-safe.
I personally only use it if the type name is also used in the assignment and the name is possible too long to duplicate in the code.
var dictionary = new Dictionary<string, string>();
It is also used for anonymous types (but still, the compiler must know the signature of the anonymous type).
var fred = new { Age = 23, Name = "Fred" };
This method is used commonly in the select clause of LINQ queries.
Just an "abstraction" or "syntax sugar" to be able to write a code without specifying first the type (this is no your first cases)
In second case: LINQ queries, instead, to rapresent some unknown, dynamic, not concrete, if you wish, type.
could be:
var results = from item in someList
where item != 3
select item; //item a class instance
could be
var results = from item in someList
where item != 3
select item.ItemName; //string property of that class
could be
var results = from item in someList
where item != 3
select new {item.ItemName, item.ID}; //unknown type dynamically generated, that conains the string and integer, like result
As far as I know var remains strong typed. The compiler calculated what the proper type should be. In fact it has no real meaning.
It is only a trick to reduce the number of manipulations. For instance when you change a type in one class, this can result in a cascade of modification. But its only a way to migrate work from the programmer to the compiler.
For instance your Linq query will result in a type IEnumerable<TA>. When you change some class so the result will be IEnumerable<TB> there is no need to change this part of the code.
Related
I have a method:
public Task<IEnumerable<MyDetails>> HandleAsync(...)
Within this method, I simply build a list of items.
IEnumerable<MyDetails> myDetails = new List<MyDetails> {
new MyDetails{ Name = 'John' },
new MyDetails{ Name = 'James' },
new MyDetails{ Name = 'Anne' },
};
And then return the result.
return Task.FromResult(insuraceTypeDetails);
In a code review, I'm being asked to use var instead of IEnumerable<MyDetails>
However, when attempting that, I get an error on my return:
Cannot convert type Threading.Tasks.Task<List> to
Threading.Tasks.Task<IEnumerable>
I thought this would be fine, but the compiler will not allow it. Can I use var here? Or am I correctly explicitly telling the compiler what we need?
In a code review, I'm being asked to use var instead of IEnumerable<MyDetails>
var will infer the type the variable from the intialization, in this cast a List<MyDetails>. But as you have discovered, you need the variable to be an IEnumerable<MyDetails> to match the return type.
You could do something goofy like convert it to an IEnumerable:
return Task.FromResult(insuraceTypeDetails.AsEnumerable());
or do an explicit cast:
return Task.FromResult((IEnumbrable<MyDetails>)insuraceTypeDetails);
but those are just working around a dogmatic coding style. There's absolutely nothing wrong with explicitly declaring the variable type, especially when using the inferred type does not work.
Use IEnumerable<MyDetails> and explain to your colleagues why var is not the right choice here.
This question already has answers here:
Using var or not using var [duplicate]
(3 answers)
Closed 4 years ago.
What is the "proper" way to use
var x = "text";
or
string x = "text";
Does it matter which I use? Is there a "standard" way people usually do it? I only ask because sometimes Rider suggests that I use var.
There are a few times where you must use an explicit type, and instances where you must use var.
Must use explicit type:
If you declare a variable without initializing it, or, if you want to initialize a variable explicitly as null
string myString;
int i;
string someString=null;
DateTime? nullableDate=null;
Must use var:
When you use an anonymous type, or a generic type with one or more type parameters that are anonymous types.
var stuff = new {Name="Bob", Age=25};
var bunchOfStuff = from item in items select new {item.Name, item.Age};
Otherwise
It's a question of style and/or taste
var is mostly syntactic sugar however there are times when you must use var and that's when you assign variables to anonymous types.
Anonymous type example:
var anonymousType = new { Name = "Mathew", DOB = DateTime.Now };
Console.WriteLine($"{anonymousType.Name} : {anonymousType.DOB}");
As far as when to use it otherwise... this is an opinion and or team guideline. There's nothing gained or lost doing it either way.
That said; here's my opinion.. this question will get put on hold for too broad but in the mean time here's a little something to look at however you choose.
I like var but I believe it can be confusing if you're not careful how you name / use variables but... personally I prefer var. It's shorter and can clean up code or make it somewhat shorter. Especially when you have somethin like Person person = new Person(); There's just too many Person's there for me... I also like how var mimics the syntax of JavaScript somewhat (although the two declarations are different).
var is not different than declaring the type out right so in your question string x or var x it doesn't matter. The compiler infers the type that is being assigned and that's what var becomes.
I do recommend this... When you declare ANY variables, especially those using var I would always name the declaration as close to the type as possible so that it doesn't matter which you choose. Name the variables correctly and no one should give you a hard time either way... Then again; this is all opinion.
var person1 = new Person();
Person person2 = new Person();
var employee1 = new Employee();
Employee employee2 = new Employee();
var employee3 = new Employee();
Person person3 = new Employee();
person1.Name = "Mathew";
person2.Name = "Mark";
employee1.Name = "Luke";
employee2.Name = "John";
employee3.Name = "Acts";
person3.Name = "Romans";
The documentation for var says:
An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type.
In the end, there is functionally no difference. So, to answer your question, no, it doesn't matter which one you use. And it is for that very reason that there is no "standard" or "proper" one to use.
Use what you prefer.
I know I can name parameters when I create a tuple implicitly like:
var me = (age: 21, favoriteFood: "Custard");
Is it possible to name parameters when a tuple is created explicitly? i.e.
var me = new ValueTuple<int, string>(21, "Custard");
No, you can't. The ValueTuple types are actually independent of the named field support in C#. The latter works more like named properties for anonymous types. That is, the compiler analyzes the code and generates aliases to the appropriate members according to your declarations and usages. It is through the assignment that the compiler learns the names of the fields. Since the basic constructor syntax doesn't provide a mechanism to name the fields, you can't use that to directly generate a tuple with named fields.
Of course, there are ways you can re-interpret the value returned from the constructor syntax, to assign names to that returned value. I'm assuming you're aware of that approach and are looking for something more direct.
As an example of what I mean by "re-interpret", you could do something like this:
static (int value, string text) ConvertToNamed((int, string) t) => t;
then this would name the fields, in a new variable:
var t1 = new ValueTuple<int, string>(21, "hello");
var t2 = ConvertToNamed(t1);
The variable t1 is stuck with Item1 and Item2. But the compiler will implicitly generate the desired names for the variable t2.
Maybe a better example is one where you don't require the additional method:
(int value, string text) t = new ValueTuple<int, string>(21, "hello");
Again, you're not really naming the fields in the constructor syntax, but they are reinterpreted by the local variable declaration.
This is probably not a serious limitation. In a scenario where there's a desire to have a persistent, easily-assigned name, it's probably better to declare a user-defined type than to use the tuple syntax anyway. You can write deconstructors for user-defined types as well, and declaring types like that means the names are first-class citizens when it comes to reflection, dynamic, etc.
You can cast to named tuple during assignment:
var me = ((int value, string text)) new ValueTuple<int, string>(21, "Custard");
Was looking for this when using ValueTuple in Linq. I did a F2-rename variable and it created the following syntax:
var query = from x in myList
select (First: x.something, Second: x.other) into g
select new Whatever(g.First, g.Second);
... C# 7.0 doesn’t enable the use of custom item names when using the
explicit System.ValueTuple<…> data type. Therefore, if you replace var
in Example 8 of Figure 1, you’ll end up with warnings that each item
name will be ignored.
Source
I'm posting this answer because the closest the docs come to explaining this is:
Data members of ValueTuple types are fields. Data members of Tuple
types are properties.
I don't believe so. Here are docs that I found on ValueTuple:
https://learn.microsoft.com/en-us/dotnet/api/system.valuetuple-7?view=netframework-4.7
I personally have not used the ValueTuble type. I have used the Tuple class before like this:
var tuple = new Tuple<int, string>(21, "Custard");
var number = tuple.Item1;
var st = tuple.Item2;
However I find using Tuples, especially when passed thru methods to be clunky. Always having to know what is in Item1 and Item2 etc. According to the ValueTuple docs, it is used in the same way.
Shouldn't you just make an entity class?
I have used the Anonymous Type which I think will suit your needs.
var anyom = new
{
age = 21,
favoriteFood = "Custard"
};
number = anyom.age;
st = anyom.favoriteFood;
[TestMethod]
public void TestMyGenericBaseClasses()
{
Type typeCrazy = ThisPartyIsTypeCrazyWOOT();
// How do I create a generic object?
MadnessOhYeah<typeCrazy> sanity = new MadnessOhYeah<typeCrazy>();
// How do I use a generic object after it has been created?
Assert.IsTrue(sanity.MyTrueFunction(), "this is sparta");
// How do I call a generic function generically?
bool result = MyFunction<typeCrazy>();
Assert.IsTrue(result, "I did not get my teeth whitened!");
}
Is there any way to make this compile? (ThisPartyIsTypeCrazyWOOT returns a Type) Because this is a test, we're not concerned about having to use reflection or anything, unless that's just absolutely crazy.
I'm getting the vibe that this isn't going to be possible though, and that our test functions will just have to be more specific.
You need Type.MakeGenericType Method. Then Activator.CreateInstance Method.
Update 2: The first example I posted still doesn't 100% answer the question, since it involves a cast to List<int>, which is a type that is known at compile time. Below is a reflection-only solution that illustrates how you can use a generic type knowing nothing about the type argument itself. But, as you can see, it's... well, disgusting ;)
Type userType = GetUserSuppliedType();
// Now let's say userType is T.
// Then here we are getting the type typeof(List<T>).
// But, of course, there's no way to have any such information in the code.
Type listOfUserType = typeof(List<>).MakeGenericType(new[] { userType });
// This is effectively calling new List<T>();
object listObject = Activator.CreateInstance(listOfUserType);
// Do you see how messy this is getting?
MethodInfo addMethod = listOfUserType.GetMethod("Add");
// We better hope this matches userType!
object input = GetUserSuppliedInput();
// I suppose we could check it, to be sure...
if (input == null || input.GetType() != userType)
{
throw new InvalidOperationException("That isn't going to work!");
}
// Here we are finally calling List<T>.Add(input) -- just in the most ass-
// backwards way imaginable.
addMethod.Invoke(listObject, new[] { input });
Update: OK, if you insist on doing this, here's an example of how it's possible—but very cumbersome!
Type genericListType = typeof(List<>);
Type listOfInt32Type = genericListType.MakeGenericType(new[] { typeof(int) });
object listObject = Activator.CreateInstance(listOfInt32Type);
List<int> list = (List<int>)listObject;
list.Add(1);
Generics can't quite work like this because a Type object could be anything. Consider this code:
var list = new List<int>();
list.Add(1);
The type of list in the above code is known to be List<int>, which defines what operations are legal on list such as Add(1).
Now consider this instead:
Type t = GetTypeFromIndeterminateSourceSuchAsUserInput();
var list = new List<t>();
list.Add(?);
When t is a Type object rather than the name of a type (like int) which the compiler can parse, it's not really possible to instantiate a generic type using that type—or rather, it's possible (see Andrey's answer), but you can't really use the resulting object in any sort of generic way.
Now, you might think that something like this ought to work:
Type t = typeof(int);
var list = new List<t>();
list.Add(1);
...but just because the value of t is known (by you) at compile time doesn't change the way things work in general.
Anyway, yes it's possible using reflection; but if you go down that path, you're committing to a pretty reflection-heavy solution. What I'm getting at is that in general it isn't a particularly realistic thing to do.
When I do a query that returns an anonymous type
var assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new {p.Asset, p.Asset.PropertyTbl};
Can I type the return to anything other than var?
You cannot* return an anonymous type because the caller would not know what type it is and wouldn't be able to use it.
If you want to return the results, you can create objects of a non-anonymous type:
IEnumerable<Foo> assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new Foo { Bar = p.Asset, Baz = p.Asset.PropertyTbl};
You can also use the Tuple type in .NET 4 if you don't want to create a custom class for your values.
* This is not strictly true - it is possible but you should avoid doing it. Here is a link anyway if you really want to.
You can use object or dynamic (in .NET 4.0) instead of var but don't expect to find a name to an anonymous type. In your case using var is better as it will preserve the strong typing at least until you leave the scope of the current method.
You could define a new class:
public class AssetProp
{
public virtual string Asset {get;set;}
public virtual string PropertyTbl {get;set;}
}
And then you can return it as that class:
IEnumerable<AssetProp> assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new AssetProp {p.Asset, p.Asset.PropertyTbl};
Not really, since the new {p.Asset, p.Asset.PropertyTbl} code creates an anonymous type. Even using object doesn't really gain you much since you can't cast it to anything useful later on, so you would have to use reflection to access the properties.
Not really. If you cast to object you wont be able to access the properties of your anonymous class.
The var keyword was specifically introduced for dealing with anonymous classes - why would you want to avoid it? If you need to return the data you should name the class.
You can if you use lambda expressions, otherwise you can do a cast but do some good exception handling.
you can also do this (it does relate much to your problem though, because you just move "var" somewhere else, but it's interesting that it recognize those types as same)
var element = new { id = 7 };
List<object> collection = new List<object>();
element = collection.Select(item => new { id = 0 }).First();