C# 4.0: What’s next

Since I have talked before about Visual Studio 2010 and Dynamic Typing, it is now time to talk about the upcoming C# 4.0 which we are expecting soon.

To understand how C# evolved and what is the paradigm of C# 4.0, let’s get a quick overview of previous versions.

In 1998 the C# began as a simple, modern, object-oriented, and type-safe programming language for the .NET platform. Since launched in the summer of 2000, 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 addition of:

  • Implicitly Typed Local Variables.
  • Extension Methods.
  • Lambda Expressions.
  • Object and Collection Initializers.
  • Anonymous types.
  • Implicitly Typed Arrays.
  • Query Expressions and Expression Trees.

Although C# is an object-oriented programming, but C# 3.0 included some capabilities of functional programming to enable 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.

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.

Essentially the C# 4.0 language innovations include:

  • Dynamically Typed Objects.
  • Optional and Named Parameters.
  • Improved COM Interoperability.
  • Safe Co-variance and Contra-variance.

To show these features, I’ll show some examples posted by Doug Holland on his The C# Programming Language Version 4.0 blog post…

Dynamically Typed Objects

In C# today you might need to get an instance of a 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);

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

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

In the above example we are declaring a variable, calc, whose static type is 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.

Optional and Named Parameters

Another major benefit of using C# 4.0 is that the language now supports optional parameters (like C and C++) and named parameters.

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.

In C# 4.0 a 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: 1024);

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

Improved COM Interoperability

When you work with COM interop methods, you had to pass a reference to Missing.Value for unneeded parameters, like 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);

Now, in C# 4.0 you can only write:

doc.SaveAs(filename);

Notice that you are able to omit the ref modifier although the use of the ref modifier is still required when not performing COM interoperability.

Also it was necessary to 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.

Safe Co-variance and Contra-variance

Co-variance means that an instance of a subclass can be used when an instance of a parent class is expected, while Contra-variance means that an instance of a super class can be used when an instance of a subclass is expected. When neither is possible, it is called Invariance.

Since version 1.0 arrays in .NET has been co-variant meaning that an array of string can be assigned to an array of object.

string[] strings = new string[] { "Hello" };
object[] objects = names;

Unfortunately arrays in .NET are not safely co-variant. Since objects variable was an array of string the following will succeed.

objects[0] = "Hello World";

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

objects[0] = 1024;

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

List strings= new List();
List<object> objects = strings;

For the Liskov Substitution Principle (LSP) to be achieved, methods of a derived class need to have contra-variant inputs and co-variant outputs.

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

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

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

Given that an IEnumerable collection is read only, there is no ability specified within the interface to insert new elements, it is safe to treat a more derived element as something less derived. With the out contextual keyword we are contractually affirming that IEnumerable<out T> is safely co-variant. We can now write the following code without a compiler error:

IEnumerablestrings = GetStrings();
IEnumerable<object> objects = strings;

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

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

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

IComparer objectComparer = GetComparer();
IComparer stringComparer = objectComparer;

It is important to notice that co-variance in IEnumerable<object> refers to the fact that its Current property can return a string instead of an object as output, while contra-variance in IComparer<string> refers to the fact that its Compare method can accept an object instead of a string as input.

Advertisements

Dynamic Typing

In my last post, I talked about Duck Typing and I said it is one of the principle of Dynamic Typing, but don’t have to be in a dynamically typed language.

In order to discuss Dynamic Typing, we need to go thorough other typing systems and know the differences between them

Implicit Typing (or Type Inference) [C# 3.0 and later]:

It is one of the forms of Latent Typing as well as Duck Typing and Dynamic Typing. Let’s see this example

var test = 5; // test is an integer

Here, you don’t have to specify the type as the Compiler can infer from the statement that the variable will hold an integer. That’s why it cannot be used if declaration and assignment are not on the same statement…

var test; // Compilation error
test = 5;

Implicit typing is used mainly when the developer wants to use the result of a function, or an expression (as in LINQ) without the need to specify its type, as the compiler already knows the type. Also, if Explicit casting is used, there is no need for explicit typing…

var test = (int) cmd.ExecuteScalar();

Dynamic Typing [Ruby, Python, and C# 4.0]

It is another form of Latent Typing, but unlike Implicit typing, type is deduced at runtime, so, there is no type checking at compile time. The support for dynamic typing is introduced in C# 4.0 to support API calls into dynamic type languages, or the use of other non-typed data, like XML.

XElement element = XElement.Parse(@"
    <FirstName>John</FirstName>
    <LastName>Smith</LastName>
    </Person>");
dynamic personXml = new DynamicXml(element);
personXml.FirstName = "Bob";

It is important to know that once a variable type is defined at runtime, it cannot be redefined later as another type. i.e. Dynamic Typing is not Weak Typing

Weak Typing (or Loose Typing) [Javascript, VB 6.0]

In javascript, this code is valid

var x = new Array(); // Any array
x[0] = "One"; // First element is a string, other elements can be any type
x[1] = "two";
x[2] = "three";
alert(x.length); // return 3
x = x.join(""); // Now x is a string not an Array
alert(x.length); // now return 11 (string length)

Weak typing is antonym to Strong Typing, while Dynamic Typing is antonym to Static Typing.

Here are some good related articles about typing systems by Bruce Eckel (author of Thinking in C++ and Thinking in Java):

Strong Typing vs. Strong Testing
About Latent Typing
How to Argue about Typing
I’m Over It

Duck Typing

While browsing the net, I found that Typemock Isolator 5.1.1 has been released, which is a mocking framework that I should try one day.

What I’m interested in is its ability to “swap” calls between real and fake objects even if they don’t implement the same interface, like this:

var duck = new Duck(); // The real, untestable class, with a Talk() method
var dummy = new Dummy(); // The fake, testable class, with another Talk() method
Isolate.Swap.CallsOn(duck).WithCallsTo(dummy);
Assert.AreEqual("Quack", dummy.Talk()); // Then the dummy is a duck

I guess the Isolate class is “borrowed” from Ruby, but anyway, it makes testing easier.

This can be possible by applying the concept of “Duck Typing” which was named as James Whitcomb Riley said


If it walks like a duck and quacks like a duck, I would call it a duck

 

So, regardless of the properties and methods of both the dummy and the real duck, a dummy can be considered a duck if it satisfies the properties and methods of a real duck in the current context, or in other words; it does not have to inherit from a duck nor satisfy all behavior of a real duck, but only what we need right now [Talk()]

Duck typing is a principle of Dynamic Typing (Which I plan to blog about next), and it is a heavily used in Dynamic Languages like Python, Ruby.

It is sometimes used in Static Languages, and may be more often than we expect. Here is a blog about Duck Notation in C# in which we find out that iterators in a foreach statement use duck typing. Also in BOO you can define a variable as duck.

Currently there is an open source project to enable duck-typing in C#, and also it is planned to be in the upcoming C# 4.0