log in

C# 4.0

Luke Breuer
2009-11-26 03:06 UTC

Session notes from the 2008 MS PDC 10/29/08
Four major parts of C#4:
  • dynamically typed objects
  • optional and named parameters
  • improved COM interoperability
  • co- and contra- variance for interface and delegate types
Channel 9 Meet the C# 4.0 Design Team
Main focuses:
  1. declarative programming
  2. dynamic programming
  3. concurrency

A major impetus for the dynamic abilities of C# 4.0 is to interoperate with dynamic languages running on the CLR (see DLR).

Languages embedded in programs are almost always dynamic. Part of the problem is that using the C# compiler inside another program is clunky. Since scripts in other programs need to be executed on the fly, they would need to be compiled on the fly as well. Embedded languages need to be easy to host as well. The actual dynamic nature of a language isn't required for it to be easily embeddable.

People typically associate:
  • dynamic languages with loose typing
  • static languages with strong typing

This doesn't have to be; LINQ Expression trees can be dynamically created, but can be compiled and when they are, type checking is most definitely strong.

Anders believes the meta-programming capabilities of Ruby is what makes it so popular, not the dynamic nature itself. Now, allowing such meta-programming is harder to do with static languages.
Channel 9 Deep inside C# 4.0
Biggest thing is the dynamic keyword. Interacting with dynamic languages using a static language is painful. C#4.0 needed a

dynamic is actually a static type.
The DLR is a regular assembly, currently in System.Core.

When the compiler compiles access to dynamic types, it gathers as much static information it can glean and stores it in one or more DLR objects. The compiler is not simply emitting dumb Reflection calls.

Each dynamic operation has a callsite, which is initialized lazily, upon first execution. It has a Target method which accepts object[] and is what actually does the dispatching. The DLR has a cache so that if a given dynamic method is called with the same arguments over and over, the cost is reduced to a delegate invocation.

The C# runtime binder gives you more power in method resolution than one would probably implement manually, such as implicit conversions and method resolution precedence. The C# runtime binder is basically a portion of the C# compiler that has been ported to runtime.

You can write an "expando" object which, upon receiving a property/method access/call that does not exist, creates it on the fly.
Eric Lippert
Spent a lot of time thinking about the far-off future, which is off-limits for public discussion. He also put work into covariance and contravariance, a brief overview was given, but interested people should check out his blog series on the issue.
Named and optional arguments
C# 4.0 uses the same metadata as VB.NET, so the two can interoperate with optional arguments easily.

Naming is done with :obj.M(a:1, q:"hi")

There were gotchas that prevented this feature from being implemented before. It massively complicates the overload resolution algorithm.

Here's a tricky situation (notice the evil swapping of parameter names):
class B {
    public virtual void M(int x, int y) {}
class D : B {
    public override void M(int y, int X) {}
D d = new D();
d.M(x:1, y:2);
B b = d;
b.M(x:1, y:2);
The compiler takes the most derived version of a method call that it can determine at compile time, and does overload resolution on that. This means that calling M with named arguments on class D will result in the arguments being passed one way, but calling M on class B will result in the arguments being swapped.

When using named parameters not in the order of method declaration and using method calls as the arguments, the compiler will actually declare temporary variables to store the return values of the methods. This is because the lexical ordering of the method calls must be preserved runtime.
C# 4.0 makes calling COM methods easier than before. In addition to getting named and optional arguments, it also allows one to pass non-ref variables (such as literals) to COM method calls if one does not need the value returned in that ref variable. (This is implemented by the compiler automatically creating temporary variables.)
BCL 4.0
The Future of C# (PDC talk)
  • imperative vs. declarative
  • dynamic vs. static

Discussion of C# 4.0 starts at 14:20; previous to that was a review of C# 1.0-3.0, with a bit of discussion about how VB.NET and C# are co-evolving.

Concurrency is discussed, but the only actual implementation appears to be PLINQ.

Invoking methods on different languages/paradigms requires different code for each. C#'s dynamic functionality utilizes binders to make invoking these methods all the same.

dynamic is emitted as System.Object with an attribute that denotes dynamic semantics.

By implementing IDynamicObject, an object can participate in method/property/etc. resolution. One can also inherit from DynamicObject to get some basic capabilities.

Named arguments must follow positional arguments. There is none of this:
obj.Something("a", 3, , , , 4);

Named and optional arguments, together with dynamic, allow for using MS Office automation (and other COM functionality) like it was supposed to be used.
  • variance is restricted to interface and delegate types only
  • the technical term is "statically checked definition-site variance"
  • value types are always invariant
  • ref and out parameters need invariant type
After C# 4.0
Modern approach to metaprogramming.

The current C# compiler is C++; rewriting it to C# has been happening for about a year (as of Nov. '08). In the process, MS will "open the box", giving finer grained access to the compiler. A REPL (read evaluate print loop) will become trivial.
C# 4.0 - Questions and reasons behind the answers
Example code: http://code.msdn.microsoft.com/csharpfuture
Why dynamic?
There are plenty of environments that are not static. Dynamic languages, COM (it is not meant to be invoked statically, seen by painful C# 2.0-style COM invocation), XML without XSDs, etc. C#'s dynamic functionality is meant to unify these environments and present the programmer with a single "interface". C# 4.0's dynamic functionality could be compared to LINQ and what it did with data sources.
Named and optional parameters
The platform has had support for these from day one — VB.NET needed this. This has actually been a top issue for the C# team for versions 2.0 and 3.0.

VS2010's intellisense is aware of named parameters and optional parameter.

This probably won't make it into VS2010, but Anders would like to see special coloring of dynamic calls.

You can omit the reference the C# binder assembly, which essentially opts you out of using dynamic.
Stands for "no primary interop assemblies". The idea is that instead of having to carry around metadata describing all COM functionality for some "library", the compiler will only include metadata for methods/properties/types that are actually being used.
Why not infer covariance and contravariance? Strictly speaking, this can be inferred, but one could end up with unintended co- and contra- variance. At some stage in the development of a library, the compiler might infer variance that was never meant. Code written that targets this library could be dependent on this variance, forcing constraints that were never intended and limit what the library developers actually intended.

in and out are restrictions, which only allow the use of an interface/delegant in input positions or output positions. It doesn't really make sense to allow both. Doing this would result in the need for runtime type checks, which just isn't something the C# team wants to do.
Wikipedia on C# 4.0