C# Language features
There are 2 very significant features about the C# language. One is it is a language that is designed for the .Net platform and second is it is a completely object oriented language, designed from a scratch. Saying so, during the design process of this language, the designers could learn from all their experiences with other object oriented language since the inception of the concept of object orientation.
Elaborating, C# is a full language in itself. Meaning it was designed for the .Net platform, but it is not a part of the .Net platform. Surprisingly there are features in C# that are not actually supported by .Net like operator overloading. However we must never forget that C# was primarily designed to generate code targeted towards the .Net platform.
The .Net execution environment is known as the Common language runtime or the .Net runtime. Before the code generated by C# is executed in the CLR, it has to be compiled. The compilation is done in 2 phases. The code is compiled into Microsoft Intermediate Language (MSIL), the MSIL is compiled into platform specific code by the CLR.
This 2 step compilation provides all the advantages of the .Net platform like platform independence, performance improvement because of the JIT Compiler, language interoperability, etc.
Hence forth, this article is going to me more like a discussion. It is not even properly organized. Since C# is a big language, it is quite difficult to summarize the entire thing into one article. So I am just going to put down everything that comes to my mind about this language. And the best way of doing it is to put down all the features of C#.
So here goes…
C# Features.
Generics
Generics is one of the most important features of C#. Generics, the way it is implemented in C#, is a feature that was first thought of in the C# language. There were templates and other form of generics existing before C# in other languages, but there was a major difference in their implementation.
Generics are generic data types. They are what the word actually means. We can divide the data types into two broad categories. Strongly typed data types and weakly typed data types.
Arrays are strongly typed data types and lists are weakly typed data types. You have to know the size and type of the array during compile time. The advantage is that you know at compile time if you are trying to push a string into an array of type Customers. The compiler will complain and won’t let you go ahead. The disadvantage is that you have to know what type of elements that array is going to store, and the size of the array, at compile time. You cannot make that decision at runtime.
On the other hand lists are weakly typed data types. What it means is that it doesn’t matter what is stored inside a list at compile time. Which means that if you create a list of the Customer object, and try to pull out a string object, the compiler is not going to complain, and you are not going to find out till runtime that it is not going to work.
So there are times when we need the advantages of both these types. We need a data type that is strongly typed and also provides all the advantages of a weakly typed data type. This is exactly what generics does. It gives you a proxy data type, which you can define at the time you define your generic variable. And then you decide later on what type that proxy data type is. Furthermore it is not just a list it could be a dictionary, a hashtable, or any other type of collection object you require.
For example, you want to create a list of Customers. But you do not know this at compile time. So all you have to do is create a list of type <T> (or “X” or “Y” or “ProxyDataType” or it could be anything that you want since it is just a proxy name for a type). Now the compiler will consider T as a data type and do all the type checking required. The question arises, what type is <T>? Now the first time you reference the list, meaning the first time you push an element into or pull an element out of the list, that is when you decide what <T> is. It could be any other data type. An integer or a reference type like Customers or BankAccounts, etc. so basically the first time we reference a list that uses a generic, the list becomes the type with which we reference it at that point of time. So after the first reference with type integers, it becomes a list of integers.
Comparing C# generics with java, when you create a java generic, it converts all the <T>s into Object type. Which means basically all it is doing is type casting your type <T> into object type and then re type casting it into the required data type. So at the first reference, the <T> which is now an object type is again converted into the type referred with. For example if you refer <T> with int, it is converted back into type int using boxing, which can be considered as a performance overhead. So basically we are not really delaying the decision of the type being used in the collection object. We are making the decision at compile time, and then changing it during runtime. While on the other hand we are truly delaying the decision of the type of the collection object till runtime in C# generics while maintaining the strong typing.
Strong data typing.
Strong data typing means all the variables in the C# are clearly marked as being of some type. there is data type like the variant. The Intermediate language doesn’t support any data type that are ambiguous. There are many advantages of strong data typing like language interoperability, garbage collection, security and application domains. All these are services provided by the .Net platform. But they rely heavily on strong data typing.
Distinct value and reference types.
The intermediate language provides a set of primitive data types. But one of the most important characteristics about the intermediate language is that it makes a strong distinction between the value and the reference types. The value types are those where the value of your variable is directly stored. The reference types are those that store only a reference to the memory address where the data is stored. This same feature goes the C# language.
Attributes.
Attributes is a feature that C++ and COM developers would be familiar with. The idea behind attributes is to provide extra information regarding some item in the program that can be used by the compiler. Attributes are supported by the .Net platform and hence by C# and even other languages like Visual Basic .Net.
The peculiar thing is that in .Net you can define your custom attributes. These user defined attributes will be kept with metadata for the corresponding data types and methods. And of course since .Net is language independent, an attribute defined in one language can be used in another language.
I am kind of seeing that this article is discussing more about the .Net features rather than discussing C# features. Well since C# was designed for the .Net platform, there is nothing that I can discuss about C# that wouldn’t really get the .Net platform into the picture.
You may pick any of the topics within here and start a discussion. And it would be really nice to have a discussion pertaining to a language. About the intent of a particular feature, etc. I think it provides fantastic opportunity to explore a language and its internals.