The C# Programming Language Version 4.0

Visual Studio 2010 and the .NET Framework 4.0 will soon be in beta and there are some excellent new features that we can all get excited about with this new release. Along with Visual Studio 2010 and the .NET Framework 4.0 we will see version 4.0 of the C# programming language. In this blog post I thought I'd look back over where we have been with the C# programming language and look to where Anders Hejlsberg and the C# team are taking us next.

In 1998 the C# project began with the goal of creating a simple, modern, object-oriented, and type-safe programming language for what has since become known as the .NET platform. Microsoft launched the .NET platform and the C# programming language in the summer of 2000 and since then C# has become one of the most popular programming languages in use today.

With version 2.0 the language evolved to provide support for generics, anonymous methods, iterators, partial types, and nullable types.

When designing version 3.0 of the language the emphasis was to enable LINQ (Language Integrated Query) which required the addiiton of:

    • Implictly Typed Local Variables.

    • Extension Methods.

    • Lambda Expressions.

    • Object and Collection Initializers.

    • Annonymous types.

    • Implicitly Typed Arrays.

    • Query Expressions and Expression Trees.



If you're in need of learning about, or distilling knowledge of, any of these language features that I have mentioned so far I would highly recommend that you take a look at the C# Programming Language by Anders Hejlsberg, Mads Torgersen, Scott Wiltamuth, and Peter Golde.

What is excellent about this edition is that it contains annotations from many other Microsoft employees and Visual C# MVP's giving you additional perspectives on the language and its capabilities. Another excellent book is Essential LINQ by Charlie Calvert and Dinesh Kulkarni.







   


In the past programming languages were designed with a particular paradigm in mind and as such we have languages that were, as an example, designed to be either object-oriented or functional. Today however, languages are being designed with several paradigms in mind. In version 3.0 the C# programming language acquired several capabilities normally associated with functional programming to enable Language Integrated Query (LINQ).

In version 4.0 the C# programming language continues to evolve, although this time the C# team were inspired by dynamic languages such as Perl, Python, and Ruby. The reality is that there are advantages and disadvantages to both dynamically and statically typed languages.

Another paradigm that is driving language design and innovation is concurrency and that is a paradigm that has certainly influenced the development of Visual Studio 2010 and the .NET Framework 4.0. See the MSDN Parallel Computing development center for more information about those changes. I'll also be blogging more about Visual Studio 2010 and the .NET Framework 4.0 in the next few weeks.

Essentially the C# 4.0 language innovations include:

    • Dynamically Typed Objects.

    • Optional and Named Parameters.

    • Improved COM Interoperability.

    • Safe Co- and Contra-variance.



Enough talking already let's look at some code written in C# 4.0 using these language innovations...

In C# today you might have code such as the following that gets an instance of a statically typed .NET class and then calls the Add method on that class to get the sum of two integers:

Calculator calc = GetCalculator();
int sum = calc.Add(10, 20); 

Our code gets all the more interesting if the Calculator class is not statically typed but rather is written in COM, Ruby, Python, or even JavaScript. Even if we knew that the Calculator class is a .NET object but we don't know specifically which type it is then we would have to use reflection to discover attributes about the type at runtime and then dynamically invoke the Add method.

object calc = GetCalculator();
Type type = calc.GetType();
object result = type.InvokeMember("Add",
                                  BindingFlags.InvokeMethod, null,
                                  new object[] { 10, 20 });
int sum = Convert.ToInt32(result);

If the Calculator class was written in JavaScript then our code would look somewhat like the following.

ScriptObect calc = GetCalculator();
object result = calc.InvokeMember("Add", 10, 20);
int sum = Convert.ToInt32(result);

With the C# 4.0 we would simply write the following code:

dynamic calc = GetCalculator();
int result = calc.Add(10, 20);

In the above example we are declaring a variable, calc, whose static type is dynamic. Yes, you read that correctly, we've statically typed our object to be dynamic. We'll then be using dynamic method invocation to call the Add method and then dynamic conversion to convert the result of the dynamic invocation to a statically typed integer.

You're still encouraged to use static typing wherever possible because of the benefits that statically typed languages afford us. Using C# 4.0 however, it should be less painful on those occassions when you have to interact with dynamically typed objects.

Another major benefit of using C# 4.0 is that the language now supports optional and named parameters and so we'll now take a look at how this feature will change the way you design and write your code.

One design pattern you'll often see as that a particular method is overloaded because the method needs to be called with a variable number of parameters.

Let's assume that we have the following OpenTextFile method along with three overloads of the method with different signatures. Overloads of the primary method then call the primary method passing default values in place of those parameters for which a value was not specified within the call to the overloaded method.

public StreamReader OpenTextFile(
         string path,
         Encoding encoding,
         bool detectEncoding,
         int bufferSize) { }

public StreamReader OpenTextFile(
         string path,
         Encoding encoding,
         bool detectEncoding) { }

public StreamReader OpenTextFile(
         string path,
         Encoding encoding) { }

public StreamReader OpenTextFile(string path) { }

In C# 4.0 the primary method can be refactored to use optional parameters as the following example shows:

public StreamReader OpenTextFile(
         string path,
         Encoding encoding = null,
         bool detectEncoding = false,
         int bufferSize = 1024) { }

Given this declaration it is now possible to call the OpenTextFile method omitting one or more of the optional parameters.

OpenTextFile("foo.txt", Encoding.UTF8);

It is also possible to use the C# 4.0 support for named parameters and as such the OpenTextFile method can be called omitting one or more of the optional parameters while also specifying another parameter by name.

OpenTextFile("foo.txt", Encoding.UTF8, bufferSize: 4098);

Named arguments must be provided last although when provided they can be provided in any order.

If you have ever written any code that performs some degree of COM interoperability you have probably seen code such as the following.

object filename = "test.docx";
object missing = System.Reflection.Missing.Value;

doc.SaveAs(ref filename,
           ref missing, ref missing, ref missing,
           ref missing, ref missing, ref missing,
           ref missing, ref missing, ref missing,
           ref missing, ref missing, ref missing,
           ref missing, ref missing, ref missing);

With optional and named parameters the C# 4.0 language provides significant improvements in COM interoperability and so the above code can now be refactored such that the call is merely:

doc.SaveAs("foo.txt");

When performing COM interoperability you'll notice that you are able to omit the ref modifer although the use of the ref modifier is still required when not performing COM interoperability.

With previous versions of the technologies it was necessary to also ship a Primary Interop Assembly (PIA) along with your managed application. This is not necessary when using C# 4.0 because the compiler will instead inject the interop types directly into the assemblies of your managed application and will only inject those types you're using and not all of the types found within the PIA.

The final language improvement that we will explore is co-variance and contra-variance and we'll begin by exploring co-variance with .NET arrays.

string[] names = new string[] {
                     "Anders Hejlsberg",
                     "Mads Torgersen",
                     "Scott Wiltamuth",
                     "Peter Golde" };


Write(names);

Since version 1.0 an array in the .NET Framework has been co-variant meaning that an array of strings, for example, can be passed to a method that expects an array of objects. As such the above array can be passed to the following Write method which expects an array of objects.

private void Write(object[] objects)
{
}

Unfortunately arrays in .NET are not safely co-variant as we can see in the following code. Assuming that the objects variable is an array of strings the following will succeed.

objects[0] = "Hello World";

Although if an attempt is made to assign an integer to the array of strings an ArrayTypeMismatchException is thrown.

objects[0] = 1024;

In both C# 2.0 and C# 3.0 generics are invariant and so a compiler error would result from the following code:

List<string> names = new List<string>();

Write(names);

Where the Write method is defined as:

public void Write(IEnumerable<object> objects) { }

Generics with C# 4.0 now support safe co-variance and contra-variance through the use of the in and out contextual keywords. Let's take a look at how this changes the definition of the IEnumerable<T> and IEnumerator<T> interfaces.

public interface IEnumerable<out T>
{
    IEnumerator<T> GetEnumerator();
}


public interface IEnumerator<out T>
{
    T Current { get; }
    bool MoveNext();
}

You'll notice that the type parameter T of the IEnumerable interface has been prefixed with the out contextual keyword. Given that the IEnumerable interface is read only, there is no ability specified within the interface to insert new elements with the list, it is safe to treat something more derived as something less derived. With the out contextual keyword we are contractually affirming that IEnumerable<out T> is safely co-variant. Given that IEnumerable<out T> is safely co-variant we can now write the following code:

IEnumerable<string> names = GetTeamNames();

IEnumerable<object> objects = names;

Because the IEnumerable<out T> interface uses the out contextual keyword the compiler can reason that the above assignment is safe.

Using the in contextual keyword we can achieve safe contra-variance, that is treating something less derived as something more derived.

public interface IComparer<in T>
{
    int Compare(T x, T y);
}

Given that IComparer<in T> is safely contra-variant we can now write the following code:

IComparer<object>
objectComparer = GetComparer();
IComparer<string> stringComparer = objectComparer;

Although the current CTP build of Visual Studio 2010 and the .NET Framework 4.0 has limited support for the variance improvements in C# 4.0 the forthcoming beta will allow you to use the new in and out contextual keywords in types such as IComparer<in T>. The .NET Framework team is updating the types within the framework to be safely co- and contra-variant.

I've listed here some resources you might find useful in exploring the capabilities of the C# 4.0 programming language and would encourage you to also download and install the beta once it is available in the coming months.

Categories:
For more complete information about compiler optimizations, see our Optimization Notice.

Comments

Ok Doug, that looks like pretty cool. Will improve the performance of my applications to run safer and faster?



Frameworks are only win32 api wrappers that are made up of Defined Types such as namespaces, enums, structs, methods and classes. Anyone with knowledge of message arcitecture and interop services can easily build frameworks as reusable dll's that incorporate all the missing elements like DWMAPI and VFW; as for driver/hardware interaction most hardware vendors supply documentation on the workings of the api's which can also be imported with interop services into a class library for use in managed applications. so stop waiting on the updates and make them yourselves. submit them, go GNU style and opensource it if your worried its not good enough, then many people can make mods and repost them to you and then you can incorporate it into your version.
I say to you all, stop waiting on the updates and read up on C++ win32 implimentation which can be found at MSDN Library and learn to use the header files to to buld complete Class Libraries for the API's we dont have, I have completed the entire DWMAPI and will submit it soon, (still need to add some exception handlers and delegates) i wanna make it as user friendly as posible.
managed code is the way to go, rather than constantly revalidating everthing echtime something is accessed just doing it at runtime in the JIT compiler makes it worth all the while, as for programming in C# or any managed language for that matter you dont really even need the framework just the normal api's - But please dont reinvent the wheel if there is allready a framework for something that dosent suit your need just stack it

ex:
public class MyTcpClient : TcpClient
{
public MyTcpClient(string hostname, int port)
: base(hostname, port)
{

}
// your extra Methods, Classes , Enums, and Structs here!
}

ex: message architecture
namespace UnsafeNativeMethods
{
[System.Runtime.InteropServices.DllImport("DwmApi.dll")]
public static extern int DwmIsCompositionEnabled
(
ref bool fEnabled
);
}

ex: usage
bool IsCompositionEnabled()
{
bool fEnabled = false;
try
{
int hResult = -1;
if ((hResult = UnsafeNativeMethods.DwmIsCompositionEnabled(ref fEnabled)) != 1)
{
throw new Exception("Error Checking Status of Composition");
}
return fEnabled;
}
catch (Exception)
{
return fEnabled;
}
}

Have fun!!!!!!


sorry typed the wrong thing in code
here's the right example

ex: message architecture
class UnsafeNativeMethods
{
[System.Runtime.InteropServices.DllImport("DwmApi.dll")]
public static extern int DwmIsCompositionEnabled
(
ref bool fEnabled
);
}


C# is already a nice language, BUT default parameters and static/dynamic typing have been around for years. Delphi had it 15 years ago and VB3 probably the same. COM interop changes are a bit late! Why not just have a look at all the languages and see what is missing and then add them properly. Me for one needs the WITH statement and also why not add proper SETS like in Delphi/Pascal. I love "IF optDisplay in Options". I'm not sure but can C# actually do what the introduced in Delphi a few years back. The ability to update a class lower in the hierarchy. Introduce and change methods of something you inherit, but not just your predecessor ... maybe even the base object. I know OO purists will freak, but are they the guys using these features and producing real code that has to run faultless for years?



Thanks Doug and others for comments, I really appreciate it :).

@Doug: thank you for your books suggestion, but I'm not having struggles with C# (yet) :P. Instead, I am a team leader of a nice company. The problems are that my developers have some difficulties to catch up with C#, and most of them use C# 2.0 styles except when they need to do database with LINQ. And none of them say they want to use the new Dynamic so far.. :(. I also agree with them about "Dynamic will introduce many harder-to-trace bugs, increase the development time".

If I code an app for myself, I will try all the best combinations of techs like Reflection, LINQ, Dynamic... etc for the fun of it (yes it's really fun when you can code something "beautiful" :P). However, when it comes to work, I would rather try the least time consumed way. While LINQ, Anonymous and others are great changes -- I really love them because they simplified the work, the incoming change of Dynamic has potential to produce some hard to trace bugs in large-scale projects.

I am not saying Dynamic is a bad thing; I am just saying it is not a great change for us.

IMHO, C# roadmap is focus on getting more users. C# new features set is trying to combine many other languages to C#, like JavaScript + C#, or C++ + C#.. in order to persuade more developers to use C#. This is nice, because C# indeed is a very nice language. However, this leaves many of us developers unsatisfied. Microsoft should do a survey to learn how many percent of developer actually uses more than one language in their project, like C# + JavaScript, C# + Ruby. While there are many nice features developers would love to see, Microsoft added to C#4.0 the features that the majority of us do not need, or simply can do it in not-really-hard-way.

Some people will tell that Microsoft did this because many companies have their codes in C++, and Microsoft introduces an easy way to immigrate to C#. However, again, Microsoft does not see the reason why they coded their projects in C++, the speed, and because most of their developers are mastered C++ not C#. Instead of making C# more faster (support multi-core), making C# more easier to master, Microsoft end up making it more unnecessarily complicate.

It is like the Vista. Instead of improving the speed, reduce ram consumption; Microsoft added many "effects" just to make the OS more beautiful. It would attract some users because of the beauty, and they would try Vista. But many users have left Vista because it did not meet their expectations. I do not want the same thing with C#. Windows 7 is on the right track, focus on stability and speed, which majority of users expected to see for many years. I also hope C# will focus on the features that majority of current users would love to see, not the features to bring more new users or to satisfy a few percent of users.

@Paul Berlett: I like your comment, I would love to see a "with" statement for C#. It is not hard to implement I think, and it is valuable for most of us (unlike some features that only target a few percent of us). Still, I think optional parameters is a nice enough feature :).

@mastermemorex: I do not think any of the above features will actually make your applications faster, but I think C# team has done many improvements in their framework :). They did a good job maintaining a great framework.

@ JeoWilson: I completely agree with you. Manage code is the way to go.

I would love to hear your opinions.
Kindest regards,
Hai
P.S: My first name is "Thanh Hai" not "Thanh" :P. You can also call me Hai for short. Thank you for reading.



Why is Microsoft pouring this much money into a language that has no future. C# hasn't because it's so attached to a certain platform. C# isn't a necesesarry language and that's why it has no future. Like Java hasn't.


Hey UJ A language that has no

Hey UJ A language that has no future? Are you kidding!!! If you mean that the C# programming language is tied to the .NET platform then you would be correct, if you mean the C# programming language is tied to the Windows platform you would be correct to a degree. While almost all .NET developers are writing their code, and deploying their solutions, upon the Windows platform; the .NET platform has been extended to the UNIX and Linux world with Mono. With C++ you are compiling your code with direct assumptions about the hardware upon which the resultant executable will run. It is therefore necessary for C++ code to be compiled against the lowest common denominator. With managed code environments such as .NET and even the Java virtual machine, it is possible for a Just-in Time (JIT) compiler to discover the actual hardware upon which it is executing and then tune the machine code it generates accordingly. Given this, it is possible for managed applications to out-perform their unmanaged counter-parts... In some respects this is no different to the argument that some may have had when C and C++ were relatively new programming languages. Why not just write everything in assembler? Within 10 feet of my desk is another developer at Intel who lives and breathes assembler programming although he recognizes the developer productivity gains in code in higher-level languages such as C, C++, and C#. Regards, Doug


Pages