To me, the benefit of "Target-typed new expressions" is more with bringing consistency to class-scope member declarations and method-scope member declarations, so these two can look the same, and a programmer only has to read one way of declaring new members in C#:
public class MyClass {
private readonly MyDependency _myDependency = new();
public void MyMethodThatDoesWork() {
MyVariable variable = new();
}
}
As opposed to the (now old, IMO) var syntax/Java-like syntax mixture:
public class MyClass {
private readonly MyDependency _myDependency = new MyDependency();
public void MyMethodThatDoesWork() {
var variable = new MyVariable();
}
}
I can't see var going anywhere, many times you aren't directly creating a new object, but getting a generated object from something ( like linq) which tends to have more complicated type signatures.
Agreed that `var` isn't going anywhere, but this feature's best use case is with complex generics/enumerables and things like anonymous tuple types. For example:
// old:
var x = new List<KeyValuePair<string, int>>
{
new KeyValuePair<string, int>("a", 1),
new KeyValuePair<string, int>("b", 2)
};
// new
var x = new List<KeyValuePair<string, int>>
{
new("a", 1),
new("b", 2)
};
Another option if you're still on .NET framework is to use a collection initializer extension method. I add a comment when I do this and place the extension method in a separate namespace.
// ListExtensions.cs
internal static class
ListExtensions
{
public static void Add(this List<KeyValuePair<string, int>> list, string key, int value)
{
list.Add(new KeyValuePair<string, int>(key, value));
}
}
// new w/extension method
var x = new List<KeyValuePair<string, int>>
{
{"a", 1},
{"b", 2},
};
Wow, when I (only a C# dabbler) read about this feature in the article I thought it sounded incredibly silly, but this really sells it. Was there really no better way to create tuples before?
You could create tuples with `Tuple.Create("a", 1)` since at least .NET 4, if not 3.
Since C# 7 you can also create tuples using just `("a", 1)`. But tuples are not KeyValuePairs. So the new "new" syntax will be very helpful in a lot of cases.
I really don't understand why they haven't added implicit conversion operators between the modern ValueTuple and the legacy value-types like KeyValuePair, Tuple, and Pair, grumble. It's a non-breaking change!
Adding that is potentially a source breaking change. Admittedly an easy enough one to address, and they are more willing to make such changes in CoreFx, then they historically were, so it is not impossible that they could decide to do it.
For an example of this being a breaking change. Let's say that B is some other type implicitly convertable to A.
Right now `Method(SomeB, (4,5))` compiles fine, but if your proposed conversions were added, it would suddenly yield `CS0121: The call is ambiguous between the following methods or properties:...`.
Tuple is not a value type. And this means that they won't add an implicit conversion, because right now a major focus of .NET and C# is also performance. and this conversion would mean an implicit heap allocation. They'd rather avoid adding features of this sort as I understand it.
KeyValuePair<string, int> KeyValue(string key, int value)
{
return new KeyValuePair<string, int>(key, value);
}
// new w/local function
var x = new List<KeyValuePair<string, int>>
{
KeyValue("a", 1),
KeyValue("b", 2)
};
3. Use an array of C# 7 tuples and convert them in a loop or query.
4. Use generics to infer the argument types à la Tuple.Create. This technique can be helpful for using anonymous types with collections.
//KeyValuePair.cs
internal static class KeyValuePair
{
public static KeyValuePair<TKey, TValue> Create<TKey, TValue>(TKey key, TValue value)
{
return new KeyValuePair<TKey, TValue>(key, value);
}
}
// new w/helper class
var x = new List<KeyValuePair<string, int>>
{
KeyValuePair.Create("a", 1),
KeyValuePair.Create("b", 2)
};
Sure, in your own IDE, and reading the code you just wrote, no problem. But when doing code reviews and jumping all over, I want to see the type right there. Nothing more frustrating than reviewing a PR with var's all over. This isn't even up for debate anymore... No more var!
It is frustrating to still see var as the recommended way by Microsoft... You can even put in a rule to format the document and add explicit types as well on save. So complicated type signatures for linq aren't a problem!
This is completely the opposite of my own experience. Using “var” makes the code easier to write AND easier to read. The code becomes decluttered from all the mess of types everywhere and you can read what it is actually doing.
Anyone who names their variables properly should have no problem telling what kind of types are being worked with anyway. And in the rare case you absolutely need specifics, they’re just a tooltip away.
I always find these arguments against “var” somewhat absurd because those same programmers work with fields and properties and methods from other classes all the time, and none of those requires you to write the type.
For an example, if you were to access “someExternalThing.bigRedTrain”, the type of “bigRedTrain” would be written nowhere in the current class. I fail to see how using “var bigRedTrain” is any different.
Every time you write something like Foo.Bar, the type of the value returned by Foo is implicit - i.e. it's exactly like var. Do you never dot-chain properties and method calls? If you do, why should it be any different when some intermediate step in the chain gets a name?
> Nothing more frustrating than reviewing a PR with var's all over.
ooh you gotta try reviewing your PRs within visual studio [1] (and be sure to use VS internal diff tool as well) - var is no longer annoying with intellisense
There's a reasonable convention of specifying full type for a variable that is returned from a method where it's not very clear what the method returns without looking up method signature. This usually means that the method name can be is not descriptive enough, but there are case where you can't really fix that.
Other than that, I think var definitely is a huge benefit for readability and overall code design.
Even then, you only see the type signature when you are initializing the variable, not every time you use it.
If you really want to see type signatures everywhere, you should use something like Hungarian notation which embed type information in the name. And you should disallow method chaining and having methods or properties as parts of expressions.