C# 4.0: COM Interop Improvements

Dynamic resolution as well as named and optional arguments greatly improve the experience of interoperating with COM APIs such as Office Automation Primary Interop Assemblies (PIAs). But, in order to alleviate even more COM Interop development, a few COM-specific features were also added to C# 4.0.

Ommiting ref

Because of a different programming model, many COM APIs contain a lot of reference parameters. These parameters are typically not meant to mutate a passed-in argument, but are simply another way of passing value parameters.

Specifically for COM methods, the compiler allows to declare the method call passing the arguments by value and will automatically generate the necessary temporary variables to hold the values in order to pass them by reference and will discard their values after the call returns. From the point of view of the programmer, the arguments are being passed by value.

This method call:

object fileName = "Test.docx";
object missing = Missing.Value;

document.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);

can now be written like this:

    Missing.Value, Missing.Value, Missing.Value,
    Missing.Value, Missing.Value, Missing.Value,
    Missing.Value, Missing.Value, Missing.Value,
    Missing.Value, Missing.Value, Missing.Value,
    Missing.Value, Missing.Value, Missing.Value);

And because all parameters that are receiving the Missing.Value value have that value as its default value, the declaration of the method call can even be reduced to this:


Dynamic Import

Many COM methods accept and return variant types, which are represented in the PIAs as object. In the vast majority of cases, a programmer calling these methods already knows the static type of a returned object form the context of the call, but has to explicitly perform a cast on the returned values to make use of that knowledge. These casts are so common that they constitute a major nuisance.

To make the developer’s life easier, it is now possible to import the COM APIs in such a way that variants are instead represented using the type dynamic which means that COM signatures have now occurrences of dynamic instead of object.

This means that members of a returned object can now be easily accessed or assigned into a strongly typed variable without having to cast.

Instead of this code:

((Excel.Range)(excel.Cells[1, 1])).Value2 = "Hello World!";

this code can now be used:

excel.Cells[1, 1] = "Hello World!";

And instead of this:

Excel.Range range = (Excel.Range)(excel.Cells[1, 1]);

this can be used:

Excel.Range range = excel.Cells[1, 1];

Indexed And Default Properties

A few COM interface features are still not available in C#. On the top of the list are indexed properties and default properties. As mentioned above, these will be possible if the COM interface is accessed dynamically, but will not be recognized by statically typed C# code.

No PIAs – Type Equivalence And Type Embedding

For assemblies indentified with PrimaryInteropAssemblyAttribute, the compiler will create equivalent types (interfaces, structs, enumerations and delegates) and embed them in the generated assembly.

To reduce the final size of the generated assembly, only the used types and their used members will be generated and embedded.

Although this makes development and deployment of applications using the COM components easier because there’s no need to deploy the PIAs, COM component developers are still required to build the PIAs.

C# 4.0: Dynamic Programming

The major feature of C# 4.0 is dynamic programming. Not just dynamic typing, but dynamic in broader sense, which means talking to anything that is not statically typed to be a .NET object.

Dynamic Language Runtime

The Dynamic Language Runtime (DLR) is piece of technology that unifies dynamic programming on the .NET platform, the same way the Common Language Runtime (CLR) has been a common platform for statically typed languages.

The CLR always had dynamic capabilities. You could always use reflection, but its main goal was never to be a dynamic programming environment and there were some features missing. The DLR is built on top of the CLR and adds those missing features to the .NET platform.

Dynamic Language Runtime

The Dynamic Language Runtime is the core infrastructure that consists of:

  • Expression Trees

    The same expression trees used in LINQ, now improved to support statements.

  • Dynamic Dispatch

    Dispatches invocations to the appropriate binder.

  • Call Site Caching

    For improved efficiency.

Dynamic languages and languages with dynamic capabilities are built on top of the DLR. IronPython and IronRuby were already built on top of the DLR, and now, the support for using the DLR is being added to C# and Visual Basic. Other languages built on top of the CLR are expected to also use the DLR in the future.

Underneath the DLR there are binders that talk to a variety of different technologies:

  • .NET Binder

    Allows to talk to .NET objects.

  • JavaScript Binder

    Allows to talk to JavaScript in SilverLight.

  • IronPython Binder

    Allows to talk to IronPython.

  • IronRuby Binder

    Allows to talk to IronRuby.

  • COM Binder

    Allows to talk to COM.

Whit all these binders it is possible to have a single programming experience to talk to all these environments that are not statically typed .NET objects.

The dynamic Static Type

Let’s take this traditional statically typed code:

Calculator calculator = GetCalculator();
int sum = calculator.Sum(10, 20);

Because the variable that receives the return value of the GetCalulator method is statically typed to be of type Calculator and, because the Calculator type has an Add method that receives two integers and returns an integer, it is possible to call that Sum method and assign its return value to a variable statically typed as integer.

Now lets suppose the calculator was not a statically typed .NET class, but, instead, a COM object or some .NET code we don’t know he type of. All of the sudden it gets very painful to call the Add method:

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

And what if the calculator was a JavaScript object?

ScriptObject calculator = GetCalculator();
object res = calculator.Invoke("Add", 10, 20);
int sum = Convert.ToInt32(res);

For each dynamic domain we have a different programming experience and that makes it very hard to unify the code.

With C# 4.0 it becomes possible to write code this way:

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

You simply declare a variable who’s static type is dynamic. dynamic is a pseudo-keyword (like var) that indicates to the compiler that operations on the calculator object will be done dynamically.

The way you should look at dynamic is that it’s just like object (System.Object) with dynamic semantics associated. Anything can be assigned to a dynamic.

dynamic x = 1;
dynamic y = "Hello";
dynamic z = new List<int> { 1, 2, 3 };

At run-time, all object will have a type. In the above example x is of type System.Int32.

When one or more operands in an operation are typed dynamic, member selection is deferred to run-time instead of compile-time. Then the run-time type is substituted in all variables and normal overload resolution is done, just like it would happen at compile-time.

The result of any dynamic operation is always dynamic and, when a dynamic object is assigned to something else, a dynamic conversion will occur.

Code Resolution Method
double x = 1.75;
double y = Math.Abs(x);


double Abs(double x)

dynamic x = 1.75;
dynamic y = Math.Abs(x);


double Abs(double x)

dynamic x = 2;
dynamic y = Math.Abs(x);     


int Abs(int x)

The above code will always be strongly typed. The difference is that, in the first case the method resolution is done at compile-time, and the others it’s done ate run-time.


The DLR is pre-wired to know .NET objects, COM objects and so forth but any dynamic language can implement their own objects or you can implement your own objects in C# through the implementation of the IDynamicMetaObjectProvider interface. When an object implements IDynamicMetaObjectProvider, it can participate in the resolution of how method calls and property access is done.

The .NET Framework already provides two implementations of IDynamicMetaObjectProvider:

  • DynamicObject : IDynamicMetaObjectProvider

    The DynamicObject class enables you to define which operations can be performed on dynamic objects and how to perform those operations. For example, you can define what happens when you try to get or set an object property, call a method, or perform standard mathematical operations such as addition and multiplication.

  • ExpandoObject : IDynamicMetaObjectProvider

    The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject.sampleMember, instead of more complex syntax like sampleObject.GetAttribute("sampleMember").

C# 4.0: Named And Optional Arguments

As part of the co-evolution effort of C# and Visual Basic, C# 4.0 introduces Named and Optional Arguments.

First of all, let’s clarify what are arguments and parameters:

  • Method definition parameters are the input variables of the method.
  • Method call arguments are the values provided to the method parameters.

In fact, the C# Language Specification states the following on §7.5:

The argument list (§7.5.1) of a function member invocation provides actual values or variable references for the parameters of the function member.

Given the above definitions, we can state that:

  • Parameters have always been named and still are.
  • Parameters have never been optional and still aren’t.

Named Arguments

Until now, the way the C# compiler matched method call definition arguments with method parameters was by position. The first argument provides the value for the first parameter, the second argument provides the value for the second parameter, and so on and so on, regardless of the name of the parameters. If a parameter was missing a corresponding argument to provide its value, the compiler would emit a compilation error.

For this call:

Greeting("Mr.", "Morgado", 42);

this method:

public void Greeting(string title, string name, int age)

will receive as parameters:

  • title: “Mr.”
  • name: “Morgado”
  • age: 42

What this new feature allows is to use the names of the parameters to identify the corresponding arguments in the form: name:value

Not all arguments in the argument list must be named. However, all named arguments must be at the end of the argument list. The matching between arguments (and the evaluation of its value) and parameters will be done first by name for the named arguments and than by position for the unnamed arguments.

This means that, for this method definition:

public void Method(int first, int second, int third)

this call declaration:

int i = 0;
Method(i, third: i++, second: ++i);

will have this code generated by the compiler:

int i = 0;
int CS$0$0000 = i++;
int CS$0$0001 = ++i;
Method(i, CS$0$0001, CS$0$0000);

which will give the method the following parameter values:

  • first: 2
  • second: 2
  • third: 0

Notice the variable names. Although invalid being invalid C# identifiers, they are valid .NET identifiers and thus avoiding collision between user written and compiler generated code.

Besides allowing to re-order of the argument list, this feature is very useful for auto-documenting the code, for example, when the argument list is very long or not clear, from the call site, what the arguments are.

Optional Arguments

Parameters can now have default values:

public void Method(int first, int second = 2, int third = 3)

Parameters with default values must be the last in the parameter list and its value is used as the value of the parameter if the corresponding argument is missing from the method call declaration.

For this call declaration:

int i = 0;
Method(i, third: ++i);

will have this code generated by the compiler:

int i = 0;
int CS$0$0000 = ++i;
Method(i, 2, CS$0$0000);

which will give the method the following parameter values:

  • first: 1
  • second: 2
  • third: 1

Because, when method parameters have default values, arguments can be omitted from the call declaration, this might seem like method overloading or a good replacement for it, but it isn’t.

Although methods like this:

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

allow to have its calls written like this:

OpenTextFile("foo.txt", Encoding.UTF8);
OpenTextFile("foo.txt", Encoding.UTF8, bufferSize: 4096);
    bufferSize: 4096,
    path: "foo.txt",
    detectEncoding: false);

The complier handles default values like constant fields taking the value and useing it instead of a reference to the value. So, like with constant fields, methods with parameters with default values are exposed publicly (and remember that internal members might be publicly accessible – InternalsVisibleToAttribute). If such methods are publicly accessible and used by another assembly, those values will be hard coded in the calling code and, if the called assembly has its default values changed, they won’t be assumed by already compiled code.

At the first glance, I though that using optional arguments for “bad” written code was great, but the ability to write code like that was just pure evil. But than I realized that, since I use private constant fields, it’s OK to use default parameter values on privately accessed methods.

C# 4.0: Covariance And Contravariance In Generics

C# 4.0 (and .NET 4.0) introduced covariance and contravariance to generic interfaces and delegates. But what is this variance thing?

According to Wikipedia, in multilinear algebra and tensor analysis, covariance and contravariance describe how the quantitative description of certain geometrical or physical entities changes when passing from one coordinate system to another.(*)

But what does this have to do with C# or .NET?

In type theory, a the type T is greater (>) than type S if S is a subtype (derives from) T, which means that there is a quantitative description for types in a type hierarchy.

So, how does covariance and contravariance apply to C# (and .NET) generic types?

In C# (and .NET), variance is a relation between a generic type definition and a particular generic type parameter.

Given two types Base and Derived, such that:

  • There is a reference (or identity) conversion between Base and Derived
  • Base Derived

A generic type definition Generic<T> is:

  • covariant in T if the ordering of the constructed types follows the ordering of the generic type parameters: Generic<Base> ≥ Generic<Derived>.
  • contravariant in T if the ordering of the constructed types is reversed from the ordering of the generic type parameters: Generic<Base> ≤ Generic<Derived>.
  • invariant in T if neither of the above apply.

If this definition is applied to arrays, we can see that arrays have always been covariant in relation to the type of the elements because this is valid code:

object[] objectArray = new string[] { "string 1", "string 2" };
objectArray[0] = "string 3";
objectArray[1] = new object();

However, when we try to run this code, the second assignment will throw an ArrayTypeMismatchException. Although the compiler was fooled into thinking this was valid code because an object is being assigned to an element of an array of object, at run time, there is always a type check to guarantee that the runtime type of the definition of the elements of the array is greater or equal to the instance being assigned to the element. In the above example, because the runtime type of the array is array of string, the first assignment of array elements is valid because string ≥ string and the second is invalid because string ≤ object.

This leads to the conclusion that, although arrays have always been covariant in relation to the type of the elements, they are not safely covariant – code that compiles is not guaranteed to run without errors.

In C#, variance is enforced in the declaration of the type and not determined by the usage of each the generic type parameter.

Covariance in relation to a particular generic type parameter is enforced, is using the out generic modifier:

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

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

Notice the convenient use the pre-existing out keyword. Besides the benefit of not having to remember a new hypothetic covariant keyword, out is easier to remember because it defines that the generic type parameter can only appear in output positions — read-only properties and method return values.

In a similar way, the way contravariance is enforced in relation a particular generic type parameter, is using the in generic modifier:

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

Once again, the use of the pre-existing in keyword makes it easier to remember that the generic type parameter can only be used in input positions — write-only properties and method non ref and non out parameters.

A generic type parameter that is not marked covariant (out) or contravariant (in) is invariant.

Because covariance and contravariance applies to the relation between a generic type definition and a particular generic type parameter, a generic type definition can be both covariant, contravariant and invariant depending on the generic type parameter.

public delegate TResult Func<in T, out TResult>(T arg);

In the above delegate definition, Func<T, TResult> is contravariant in T and convariant in TResult.

All the types in the .NET Framework where variance could be applied to its generic type parameters have been modified to take advantage of this new feature.

In summary, the rules for variance in C# (and .NET) are:

  • Variance in relation to generic type parameters is restricted to generic interface and generic delegate type definitions.
  • A generic interface or generic delegate type definition can be covariant, contravariant or invariant in relation to different generic type parameters.
  • Variance applies only to reference types: a IEnumerable<int> is not an IEnumerable<object>.
  • Variance does not apply to delegate combination. That is, given two delegates of types Action<Derived> and Action<Base>, you cannot combine the second delegate with the first although the result would be type safe. Variance allows the second delegate to be assigned to a variable of type Action<Derived>, but delegates can combine only if their types match exactly.

If you want to learn more about variance in C# (and .NET), you can always read:

Note: Because variance is a feature of .NET 4.0 and not only of C# 4.0, all this also applies to Visual Basic 10.

LINQ: Enhancing Distinct With The SelectorEqualityComparer

LINQ With C# (Portuguese)

On my last post, I introduced the PredicateEqualityComparer and a Distinct extension method that receives a predicate to internally create a PredicateEqualityComparer to filter elements.

Using the predicate, greatly improves readability, conciseness and expressiveness of the queries, but it can be even better. Most of the times, we don’t want to provide a comparison method but just to extract the comaprison key for the elements.

So, I developed a SelectorEqualityComparer that takes a method that extracts the key value for each element. Something like this:

public class SelectorEqualityComparer<TSource, Tkey> : EqualityComparer<TSource>
    where Tkey : IEquatable<Tkey>
    private Func<TSource, Tkey> selector;

    public SelectorEqualityComparer(Func<TSource, Tkey> selector)
        : base()
        this.selector = selector;

    public override bool Equals(TSource x, TSource y)
        Tkey xKey = this.GetKey(x);
        Tkey yKey = this.GetKey(y);

        if (xKey != null)
            return ((yKey != null) && xKey.Equals(yKey));

        return (yKey == null);

    public override int GetHashCode(TSource obj)
        Tkey key = this.GetKey(obj);

        return (key == null) ? 0 : key.GetHashCode();

    public override bool Equals(object obj)
        SelectorEqualityComparer<TSource, Tkey> comparer = obj as SelectorEqualityComparer<TSource, Tkey>;
        return (comparer != null);

    public override int GetHashCode()
        return base.GetType().Name.GetHashCode();

    private Tkey GetKey(TSource obj)
        return (obj == null) ? (Tkey)(object)null : this.selector(obj);

Now I can write code like this:

.Distinct(new SelectorEqualityComparer<Source, Key>(x => x.Field))

And, for improved readability, conciseness and expressiveness and support for anonymous types the corresponding Distinct extension method:

public static IEnumerable<TSource> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
    where TKey : IEquatable<TKey>
    return source.Distinct(new SelectorEqualityComparer<TSource, TKey>(selector));

And the query is now written like this:

.Distinct(x => x.Field)

For most usages, it’s simpler than using a predicate.

LINQ: Enhancing Distinct With The PredicateEqualityComparer

LINQ With C# (Portuguese)

Today I was writing a LINQ query and I needed to select distinct values based on a comparison criteria.

Fortunately, LINQ’s Distinct method allows an equality comparer to be supplied, but, unfortunately, sometimes, this means having to write custom equality comparer.

Because I was going to need more than one equality comparer for this set of tools I was building, I decided to build a generic equality comparer that would just take a custom predicate. Something like this:

public class PredicateEqualityComparer<T> : EqualityComparer<T>
    private Func<T, T, bool> predicate;

    public PredicateEqualityComparer(Func<T, T, bool> predicate)
        : base()
        this.predicate = predicate;

    public override bool Equals(T x, T y)
        if (x != null)
            return ((y != null) && this.predicate(x, y));

        if (y != null)
            return false;

        return true;

    public override int GetHashCode(T obj)
        // Always return the same value to force the call to IEqualityComparer<T>.Equals
        return 0;

Now I can write code like this:

.Distinct(new PredicateEqualityComparer<Item>((x, y) => x.Field == y.Field))

But I felt that I’d lost all conciseness and expressiveness of LINQ and it doesn’t support anonymous types. So I came up with another Distinct extension method:

public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, bool> predicate)
    return source.Distinct(new PredicateEqualityComparer<TSource>(predicate));

And the query is now written like this:

.Distinct((x, y) => x.Field == y.Field)

Looks a lot better, doesn’t it? And it works wit anonymous types.

Update: I, accidently, had published the wrong version of the IEqualityComparer<T>.Equals method,

CodeIt.Right Code File Header Template For StyleCop Rules

I like to use both StyleCop and CodeIt.Right to validate my code – StyleCop because it’s free and CodeIt.Right because it’s really good.

While StyleCop provides only validation, CodeIt.Righ provides both validation and correction of violations.

Unfortunately, CodeIt.Right’s supplied template for code file headers does not conform to StyleCop rules.

Fortunately, CodeIt.Right allows us to define our own template. Here’s the one I use:

<#@ template language="C#" #>
// <copyright file="<#= System.IO.Path.GetFileName(Context.DestinationFile) #>"
//            project="<#= Context.ProjectName #>"
//            assembly="<#= Context.AssemblyName #>"
//            solution="<#= Context.SolutionName #>"
//            company="<#= Context.GetGlobalProperty("CompanyName") #>">
//     Copyright (c) <#= Context.GetGlobalProperty("CompanyName") #>. All rights reserved.
// </copyright>
// <author id="<#= Context.GetGlobalProperty("UserID") #>"><#= Context.GetGlobalProperty("UserName") #></author>
// <summary></summary>

Defining Document Compatibility In Internet Explorer 8

The procedures to define document compatibility in Internet Explorer 8 are well documented here, but I’ve seem many developers and system administrators that are not aware of this.

Although you can (and should) define the document compatibility your web pages were designed to, if you don’t, Internet Explorer 8 and the Web Browser Control will default to these compatibility modes:




Internet Explorer 8 IE7 mode IE8 mode
Application hosting the Web Browser Control IE7 mode IE7 mode

If you notice the table above, by default, only Internet Explore 8 will present itself to the as Internet Explorer 8 and only to Internet sites.

The way Internet Explorer (and any other browser) presents itself the web servers is using its user agent string:


User Agent String

IE7 Mozilla/4.0 (compatible; MSIE 7.0; …; Trident/4.0; …)
IE8 Mozilla/4.0 (compatible; MSIE 8.0; …; Trident/4.0; …)

(If you are curious about the history of the user-agent string, read the History of the user-agent string)

Microsoft did this to keep compatibility with legacy applications used by enterprises (large and small) but this brings a few issues to development and testing.

If you are building a public web site for Internet Explorer 8, you might see the right thing on your development machine, but the quality assurance team will see the site as if it were an Internet Explorer 7 if the version they are testing is on the intranet. If the the web site you are developing is going to be accessed from an application hosting the Web Browser Control and you don’t test on that application, you are not going to see the same thing.

To know how is your browser presenting itself to the web server in the internet, there are several web sites that will show information about the user-agent string (like and it helps to have the same thing in your intranet. If you want to build such a web application using ASP.NET, you can use the UserAgent property of the HttpRequest class (or the Browser property for more detailed information).

This type of information is also available in Internet Explorer in the navigator object.

Giorgio Sardo has a few functions to detect Internet Explorer 8 but you might also want to develop a diagnostics page (or part) to show the web browser features, something like this:

<fieldset id="webBrowserInfo">
    <legend>Web Browser</legend>
    <table border="1">
            <td class="label" style="width: 100px"><label for="webBrowser$userAgent">userAgent</label> </td>
            <td class="value" colspan="3"><span id="webBrowser$userAgent"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$appVersion">appVersion</label></td>
            <td class="value"><span id="webBrowser$appVersion"></span></td>
            <td class="label"><label for="webBrowser$appMinorVersion">appMinorVersion</label></td>
            <td class="value"><span id="webBrowser$appMinorVersion"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$appCodeName" style="width: 600px">appCodeName</label></td>
            <td class="value" colspan="3"><span id="webBrowser$appCodeName"></span></td>
            <td class="label"><label for="webBrowser$appName">appName</label></td>
            <td class="value" colspan="3"><span id="webBrowser$appName"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$userLanguage">userLanguage</label></td>
            <td class="value"><span id="webBrowser$userLanguage"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$cpuClass">cpuClass</label></td>
            <td class="value"><span id="webBrowser$cpuClass"></span></td>
            <td class="label"><label for="webBrowser$systemLanguage">systemLanguage</label></td>
            <td class="value"><span id="webBrowser$systemLanguage"></span></td>
            <td class="label"><label for="webBrowser$platform">platform</label></td>
            <td class="value"><span id="webBrowser$platform"></span></td>
            <td class="label"><label for="webBrowser$browserLanguage">browserLanguage</label></td>
            <td class="value"><span id="webBrowser$browserLanguage"></span></td>
            <td class="label" style="width: 100px"><label for="webBrowser$cookieEnabled">cookieEnabled</label></td>
            <td class="value" colspan="5"><span id="webBrowser$cookieEnabled"></span></td>

<script type="text/javascript">
    document.getElementById("webBrowser$userAgent").innerHTML = window.navigator.userAgent;
    document.getElementById("webBrowser$appCodeName").innerHTML = window.navigator.appCodeName;
    document.getElementById("webBrowser$appMinorVersion").innerHTML = window.navigator.appMinorVersion;
    document.getElementById("webBrowser$appName").innerHTML = window.navigator.appName;
    document.getElementById("webBrowser$appVersion").innerHTML = window.navigator.appVersion;
    document.getElementById("webBrowser$browserLanguage").innerHTML = window.navigator.browserLanguage;
    document.getElementById("webBrowser$cookieEnabled").innerHTML = window.navigator.cookieEnabled;
    document.getElementById("webBrowser$cpuClass").innerHTML = window.navigator.cpuClass;
    document.getElementById("webBrowser$platform").innerHTML = window.navigator.platform;
    document.getElementById("webBrowser$systemLanguage").innerHTML = window.navigator.systemLanguage;
    document.getElementById("webBrowser$userLanguage").innerHTML = window.navigator.userLanguage;

C# Proposal: Compile Time Static Checking Of Dynamic Objects

C# 4.0 introduces a new type: dynamic. dynamic is a static type that bypasses static type checking.

This new type comes in very handy to work with:

Because static type checking is bypassed, this:

dynamic dynamicValue = GetValue();

is equivalent to this:

object objectValue = GetValue();

Apart from caching the call site behind the scenes and some dynamic resolution, dynamic only looks better. Any typing error will only be caught at run time.

In fact, if I’m writing the code, I know the contract of what I’m calling. Wouldn’t it be nice to have the compiler do some static type checking on the interactions with these dynamic objects?

Imagine that the dynamic object that I’m retrieving from the GetValue method, besides the parameterless method Method also has a string read-only Property property. This means that, from the point of view of the code I’m writing, the contract that the dynamic object returned by GetValue implements is:

string Property { get; }
void Method();

Since it’s a well defined contract, I could write an interface to represent it:

interface IValue
    string Property { get; }
    void Method();

If dynamic allowed to specify the contract in the form of dynamic(contract), I could write this:


dynamic(IValue) dynamicValue = GetValue();

This doesn’t mean that the value returned by GetValue has to implement the IValue interface. It just enables the compiler to verify that dynamicValue.Method() is a valid use of dynamicValue and dynamicValue.OtherMethod() isn’t.

If the IValue interface already existed for any other reason, this would be fine. But having a type added to an assembly just for compile time usage doesn’t seem right. So, dynamic could be another type construct. Something like this:


dynamic DValue
    string Property { get; }
    void Method();

The code could now be written like this;


DValue dynamicValue = GetValue();

The compiler would never generate any IL or metadata for this new type construct. It would only be used, at compile time, for static checking of dynamic objects. As a consequence, it makes no sense to have public accessibility, so it would not be allowed.

Once again, if the IValue interface (or any other type definition) already exists, it can be used in the dynamic type definition:


dynamic DValue : IValue, IEnumerable, SomeClass
    string Property { get; }
    void Method();

Another added benefit would be IntelliSense.

I’ve been getting mixed reactions to this proposal. What do you think? Would this be useful?

Free e-Book: Programming Windows Phone 7 Series by Charles Petzold