Tutorial :Introducing Brevity Into C# / Java



Question:

Background

Currently, if I want to create a new object in C# or Java, I type something similar to the following:

List<int> listOfInts = new List<int>(); //C#
ArrayList<String> data = new ArrayList<String>(); //Java

C# 3.0 sought to improve conciseness by implementing the following compiler trick:

var listofInts = new List<int>();

Question

Since the compiler already knows that I want to create a new object of a certain type (By the fact that I'm instantiating it without assigning it a null reference or assigning a specific method to instantiate it), then why can't I do the following?

    //default constructors with no parameters:      List<int> listOfInts = new(); //c#      ArrayList<String> data = new(); //Java  

Follow Up Questions:

  1. What are possible pitfalls of this approach. What edge cases could I be missing?
  2. Would there be other ways to shorten instantiation (without using VB6-esque var) and still retain meaning?

NOTE: One of the main benefits I see in a feature like this is clarity. Let say var wasn't limited. To me it is useless, its going to get the assignment from the right, so why bother? New() to me actually shortens it an gives meaning. Its a new() whatever you declared, which to me would be clear and concise.


Solution:1

C# saves in the other end:

var listOfInts = new List<int>();  


Solution:2

What edge cases could I be missing?

I briefly discussed this possible C# syntax on my blog in January. See the comments to that post for some reader feedback on the pros and cons of the syntax.

Would there be other ways to shorten instantiation (without using VB6-esque var) and still retain meaning?

Possibly, yes.

"var" in C#, however, is nothing like "variant" in VB6. "var" does not mean the same thing as "object", nor does it introduce dynamic typing or duck typing. It is simply a syntactic sugar for eliminating the redundant stating of the type of the right hand side.


Solution:3

In C# 3 there's already the mirror image for local variables, implicitly typing:

var listOfInts = new List<int>();  

This doesn't work for non-local variables though.

In Java, type inference takes into the assignment target into account, so using static imports and cunning libraries such as the Google Java Collections you can write code such as:

List<Integer> integers = newArrayList();  

Note that that keeps the variable interface-based while specifying the implementation in the construction side, which is nice.


Solution:4

In the new Java 7 proposals there's a type inference proposal, which will life easier re. generics declarations.

e.g.

Map<String, List<String>> anagrams = new HashMap<String, List<String>>();  

vs

Map<String, List<String>> anagrams = new HashMap<>();  

See here for more information.


Solution:5

Your version is less readable, sorry.

Code is meant to be read by humans, only incidentally by machines.


Solution:6

In general when using object oriented approaches, you will often create more instances of a more specific type than your variable. Also, it is often a good idea to use a less specific type or an interface. In those cases, this would not make sense.

Think of interfaces:

IList<int> = new(); // What instance should the compiler infer?  

Also, from a technical point of view, the signature of an operation does not include its return type, so that this kind of assignment would be completely different from the normal case.


Solution:7

C# has:

var listOfInts = new List<int>();  

which achieves kind of the same thing.


Solution:8

C# 3.0 has a mechanism to reduce the duplication in typing, but it is done by being vague about the type you're declaring, but explicit in the type you are constructing:

e.g.

var listOfInts = new List<int>();  


Solution:9

I agree that would be a nice feature. A better example would be where even more typing is required:

Dictionary<string, int> myDictionary = new Dictionary<string, int>();  

Life would be easier, albeit only slightly, if that could be instantiated as:

Dictionary<string, int> myDictionary = new();  

and:

Dictionary<string, int> myDictionary = { {"a",1}, {"b",2} };  


Solution:10

In C#, there's

var listOfInts = new List<int>();  


Solution:11

in C#, theres already something like this namely:

var listOfInts = new List<int>();  


Solution:12

In Java this doesn't make too much sense, as you will usually declare variables with the interface type:

List<String> myList = new ArrayList<String>();  

It would, however, in most cases make sense to be able to omit the declaration of the generic type without compiler warnings, such as:

List<String> myList = new ArrayList();  

But as Java is always very explicit and verbose about everything, this might as well stay the same.

(And why again would anyone code C# or Java without an IDE?)

EDIT:

Oh, there's a proposal for that! Sweet. Thanks, Brian.


Solution:13

Java has

 List<String> data = newList(); //Java, where newList() is a helper method to create an ArrayList();   List<String> data = newList("Hello", "World"); // a helper method which takes a T....   Map<String, List<String>> anagrams = newMap(); // Java, where newMap creates a new  HashMap();  


Solution:14

Code is read from left to right (if your language is not right to left).

That means that

var someTypeWithALongName = new TypeWithALongName<TypeParamOne,TypeParamTwo>();   

puts important data to the right part (actual method / type constructor that is used to init variable, from which a reader of the code can infer knowledge about actual var type), which is less convenient to eye, compared to when it is located in the left.

What author suggests however is much better for a left to right reading human - we declare a variable of known type (not some unknown var type)

TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();  

now important data (actual type that variable will have) is to the left, we can scan code on left side and notice actual types, not a fence of var declarations

var x = ....;  var y = ....;  var z = ....;  var xy = ....;  

Code Complete book states that readability is the most important, and I find it hard to disagree with that. Saving 5(or less) seconds and using var instead of real type easily makes code review in future harder, can make code unreadable depending on the right part, and can plant unexpected errors that will be very hard to notice. All with the value of.. saving 5 seconds and not writing a declaring type for variable?

It is now a common knowledge that actual code writing is not taking that much time out of whole time consumed for program creation,especially if it is a product program) ( which usually has debugging, system testing, components integration, design, meetings, etc taking MUCH more time that actual code writing)

On other hand when we type

TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();  

I find it hard not to interpret that line as anything but calling a default constructor for type and creating an instance of the type.

Also in case of wall of initializations we get actual type names on the beginning of the line, so its easy to scan code from top to bottom and we don't have to move eyes to the end of string to know what actually this concrete var initialization does.( And if you think scanning line to end is a free roll task , first of all its not, and with var its not just scanning, its also checking whether there is a bug in the right part of initialization (for example method with different return type is called or some other types of bugs which var allows))

TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();  AnotherTypeWithLongNname someAnotherTypeWithLongNname = new();  List<int> idList = new();  Dictionary<int,string> lookupDict = new ();  

I am against var use except for cases it was created for (anonymous types , generally coming from LINQ), and if we were to save up some space in a code I would prefer any code reducing strategies were happening on the right side.

I also believe that using var to declare a variable and assigning it to a return value of some method highly complicates code analysis and often introduces hard to catch bugs, that would have been completely avoided if var wasn't possible for such cases, so if only the constructors code could be shortened to a new() or new(ParamType param) and not some other method like

var x = someTypeLocalIstance.ComputeResults()  

readability will only win once more.


Solution:15

I think Microsoft made it this way: a) var xy = new MyClass();

instead of this way: b) MyClass xy = new();

because a) is capable to hold anonymous classes and with b) that would not be possible.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »