[Whidbey and Orcas]

Whidbey and Orcas

Tuesday, October 4, 2005

The next .NET version on the horizon, 3.0 code-named Orcas, is getting a lot of attention already. This article is on the bleeding edge, a work in progress.

Language Features

There are a number of new language features in Orcas. Both C# and VB.NET have many of them in common, while some features are just for one of them.

Feature Roadmap

Since VB.NET catches up on some C# Whidbey goodies, and others are quite important ground work for the new Orcas features, and even Whidbey is kind of new, let's summarize major new language features for both languages introduced in .NET 2.0 and announced for .NET 3.0:

GroupFeatureDescriptionC#VB
Declarations Implicitly Typed Locals Type inferrence on initialization expression Orcas Orcas
Implicitly Typed Arrays Type inferrence on array initializer Orcas *
Initialization Object Initializers Assigning to members in creation expression Orcas Orcas
Collection Initializers Requires ICollection<T>, which declares method Add(T) Orcas Orcas
Type System Generics Runtime parameterized types Whidbey Whidbey
Anonymous Types or Tuples Ad-hoc compiler-generated class types Orcas Orcas
Nullable Types Special compiler support for System.Nullable Whidbey Orcas
Methods and Delegates Iterators Stateful generator functions Whidbey -
Extension Methods Syntactic sugar for functions Orcas Orcas
Delegate Relexation Return type covariance, parameter contravariance Whidbey Orcas
Closures, Lambdas Nested Functions Named local subroutines Whidbey* Orcas
Anonymous Methods Without names Whidbey *
Lambdas Based on delegates Orcas *
Expression Tress Lambdas as data structures Orcas -
Language Integration Query Expressions Language-integrated SQL Orcas Orcas
XML Literals Language-integrated XML - Orcas
Late Binding Duck Typing Dynamic Interfaces - Orcas
Dynamic Identifiers Like Call-By-Name - Orcas

Lambda Expressions

Given to following declarations/definitions ...

delegate string CharDuplicator(char ch, int count);

string DuplicateChar(char ch, int count, CharDuplicator predicate){
    return predicate(ch, count);
}

char ch = '#';

... the method may be called like this in Whidbey ...

string result = DuplicateChar(
                    ch,
                    5,
                    delegate(char ch, int count){
                        return new string(ch, count);
                    }
                );

... which is equivalent to the following Orcas code:

string result = DuplicateChar(
                    ch,
                    5,
                    (char ch, int count) => {return new string(ch, count);}
                );

If there is only one statement, the body of the lambda may be an expression instead of a statement block:

(char ch, int count) => new string(ch, count)

The type of the parameters may be inferred from the context - unlike in anonymous methods:

(ch, count) => new string(ch, count)

If there are multiple parameters, as in this case, they need to be enclosed by parens. Otherwise, the following will suffice:

ch => new string(ch, sbyte.MaxValue);

If the delegate specifies no parameters at all, an empty parameter list, is used):

() => new string('#', sbyte.MaxValue);

Additional features are:

Language-Integrated Query

Data integration is acronymed LINQ (Language-INtegrated Query), and it promises general query capability build right into the framework as well as the languages.

Note that I didn't mention the Common Language Runtime: all CLR support needed, such as iterators and generics is available in Whidbey already, which means that you can build your own query operator library similiar to the one proposed for orcas. Let's look at the triad of runtime, class library, and language compilers:

Features used in Query Operators

Example: Query Operators for Conversion

Everett: none-type-safe delegate pointing to regular callback:

delegate object Converter(
    object arg
);

IEnumerable Convert(
    IEnumerable source,
    Converter converter
);

object TypeToTypeInfoEx(object arg){
    return new CTypeInfoEx((Type)arg);
}

void Test(){
    IEnumerable result = Convert(
                             aTypes,
                             new Converter(TypeToTypeInfoEx)
                         );
}

Whidbey: generic delegate type, anonymous method:

delegate TargetType Converter<SourceType, TargetType>(
    SourceType arg
);

IEnumerable<TargetType> Convert<TargetType>(
    IEnumerable<SourceType> source,
    Converter<SourceType, TargetType> converter
);

void Test(){
    IEnumerable<CTypeInfoEx> result = Convert<CTypeInfoEx>(
                                          aTypes,
                                          delegate(Type tp){
                                              return new CTypeInfoEx(tp)
                                          }
                                      );
}

Orcas: lambda expression:

delegate TargetType Converter<SourceType, TargetType>(
    SourceType arg
);

IEnumerable<TargetType> Convert<TargetType>(
    IEnumerable<SourceType> source,
    Converter<SourceType, TargetType> converter
);

void Test(){
    IEnumerable<CTypeInfoEx> result = Convert<CTypeInfoEx>(
                                          aTypes,
                                          tp => new CTypeInfoEx(tp)
                                      );
}

Orcas: like above, but with implicitly typed local, extension method and using the conventional Func delegate generic:

delegate TR Func<T0, TR>(T0 arg);

IEnumerable<TargetType> Convert<TargetType>(
    this IEnumerable<SourceType> source,
    Func<SourceType, TargetType> converter
);

void Test(){
    var result = aTypes.Convert(
                            tp => new CTypeInfoEx(tp)
                        );
}

Questions and Comments

API

Func family type parameter ordering convention (return type last):
- PRO VB syntax
- PRO lambdy syntax
- CON C# syntax

C#

VB.NET