The core idea
I don't see an issue with using a syntax similar to var
variables when declaring class variables:
public class Foo
{
var Bar = new Bar();
}
All the necessary information is there, it's not ambiguous, and it follows a known syntax (variable type inference).
However, a combined declaration and initialisation is a rare occurence for method members, as opposed to how often it occurs for variables. I suspect this is why it hasn't really been addressed by the language architects.
Your proposed syntax
As you identified, to reduce the redundancy, we should cut down on one of two redundant references. Currently, only this type of syntax is allowed (for variables):
var dictionary = new Dictionary<T, int>();
and not either of these:
Dictionary<T, int> dictionary = new();
Dictionary<T, int> dictionary = new var();
At face value, and what this question is trying to assert, you'd think that these are equally valid.
But are they?
Your example is slightly limited in that you're only considering concrete classes. Consider how this would work for interfaces (or abstract classes). First, the current existing way:
var userService = service.Get<IUserService>();
This works. The compiler identifies the return type of Get<IUserService>()
and then sets var
to the same type (presumably IUserService
in this example).
But for your suggested approach:
IUserService userService = new();
IUserService userService = new var();
This does not work. Without either a concrete object instantiation or a method with a defined return type, the compiler is incapable of determining exactly what you to have happen here.
You may think it's slightly cheaty that I introduce the service method in the existing example (since you can't instantiate an interface), but the point of the matter is that your "type-first-var-last" approach simply doesn't add any reduction to this case, as it would end up as:
IUserService userService = service.Get<IUserService>();
= no shortening.
This leads us to the simple conclusion that the existing approach allows for shortened yet consistent syntax in all cases, whereas your suggestions would be inconsistent or inapplicable depending on whether the used type is concrete or not.
In other words, your suggestion is simply not as good as the existing approach because it can't cover all relevant cases.
The default
approach
In the above, I have omitted your first suggestion:
Dictionary<T, int> dictionary = new default();
I would avoid this in general, as default
has a defined behavior. For reference types, default(T)
specifically returns null
.
When I read this suggestion, my initial takeaway was that you're assigning null
to the variable. While your syntax is subtly different (no type parameter used), I am opposed to having these very different behaviors both implemented on the same default
keyword.
Technically, it could be made the way you want it to. But it's going to have a negative impact on readability, so I don't like it.
var dictionary = new new Dictionary<T, int>();
Dictionary<T, int> dictionary
is a declaration, whilenew Dictionary<T, int>();
is a constructor call.var dictionary
uses type inference to infer the declared type. In short, this situation is already handled.var
can't be used unless you immediately instantiate the variable (for obvious reasons), so that would guarantee that you always have both types (declaration+instantiation) available and thus either of them could be inferred by the other.