Friday, November 14, 2008

New features in C#4.0 (3)

Optional and Named Parameters
Optional parameter is a long-standing request from the community that made it to C# 4.0. By itself, the feature is definitely useful but in conjunction with the mission to make COM Interop easier, there's even more value to it.
Optional Parameters
(1) The syntax
C# 4.0 can both declare and consume optional parameters. Here's a sample of a very simple method that declares a parameter as optional:
public static class OptionalDemoLib
public static void SayHello(string s = "Hello World!")
This means you can either call Do with one argument or without an argument, in which case the default value is used:
public static class OptionalDemo
public static void Main()
OptionalDemoLib.SayHello(); OptionalDemoLib.SayHello("Hello Bart!");
Notice all optional parameters need to come at the end of the argument list.
(2) The implementation
How does it work? Let's start by taking a look at the definition side. Here's the IL corresponding to the declaration of SayHello above:

Two things are relevant here. First of all, the parameter is decorated with the [opt]. Second, the method body contains a .param directive. It turns out both of those primitives have been supported in the CLI since the very beginning. Let's dive a little deeper using the CLI specification, partition II:

15.4 Defining methods
opt specifies that this parameter is intended to be optional from an end-user point of view. The value to be supplied is stored using the .param syntax ($

15.4.1 Method body
.param `[` Int32 `]` [ `=` FieldInit ] Store a constant FieldInit value for parameter Int32. The .param directive
This directive stores in the metadata a constant value associated with method parameter number Int32, see $22.9. (...) Unlike CIL instructions, .param uses index 0 to specify the return value of the method, index 1 to specify the first parameter of the method, ...

22.9 Constant : 0x0B
The Constant table is used to store compile-time, constant values for fields, parameters, and properties. The Constant table has the following columns: - Type ... - Parent ... - Value (an index into the Blob heap) Note that Constant information odes not directly influence runtime behavior, although it is visible via Reflection. Compilers inspect this information, at compile time, when importing metadata, but the value of the constant itself, if used, becomes embedded into the CIL stream the compiler emits. There are no CIL instructions to access the Constant table at runtime.
Default parameter value must be a compile-time constant.

Named Parameters
(1) The syntax

Assume the following simple subtraction method is defined:
static int Substract(int a, int b)
return a - b;
The typical way to call this method is obviously by specifying the parameters in order, like Subtract(5, 3). However, with named parameters it's possible to write the following:
public static void Main()
Console.WriteLine(Substract(b: 3, a: 5));
Ultimately this translates into a call to Subtract(5, 3). Typically named parameters are used where optional parameters appear in the target method, but you're not interested in lots of those:
static void Bar(int a = 1, string b = null,bool c = false)
// ...
static void Bar(int a = 1, string b = null, bool c = false){ // ...}
Now assume you're only interested in the last parameter, without the named parameter feature you'd have to write Bar(1, null, ...) but now you can go ahead and write:
Bar(c: true);
Bar(c: true);
You might wonder why the syntax uses a colon (:) instead of an assignment equals character (=). The answer is straightforward: assignments have a value and can be used everywhere a value is expected:
bool c = false;
Bar(c: true);
bool c = false;Bar(c = true);
This will assign true to the local variable c and feed that value in as the first argument of Bar. So colon is the way to go.
(2) The implementation
It should be clear that the implementation only affects the call site, not the caller. Here's how the Main method from above looks like:
First of all, notice the names of parameters don't appear in the call site in any way (they never have, that's not the way IL works). Ultimately we simply call Subtract with the parameters supplied in the right order. But how we get there is important to take a closer look at:
IL_0001: ldc.i4.3
IL_0002: stloc.0
IL_0003: ldc.i4.5
IL_0004: stloc.1
IL_0005: ldloc.1
IL_0006: ldloc.0 IL_0001: ldc.i4.3
IL_0002: stloc.0
IL_0003: ldc.i4.5
IL_0004: stloc.1
IL_0005: ldloc.1
IL_0006: ldloc.

The thing to notice here are the mirrored stloc (store to local variable) versus ldloc (load from local variable) instructions. And ldc.i4.num is used to push num on the stack as Int32. On lines IL_0002 and IL_0004 values are stored to variables 0 and 1, while on lines IL_0005 and IL_0006 they're read out in reverse order. What's happening here is that during the run-time processing of a function member invocation, the expressions or variable references of an argument list are evaluated in order, from left to right. Obviously, the complier has to do something to keep the order correct.
New features in C#4.0 (2)

Co- and Contra-variance
Within the type system of a programming language, an operator from types to types is covariant if it preserves the ordering, ≤, of types, which orders types from more specific ones to more generic ones; it is contra variant if it reverses this ordering. If neither of these applies, the operator is invariant.
This distinction is important in considering argument and return types of methods in class hierarchies. In object-oriented languages such as C++, if class B is a subtype of class A, then all member functions of B must return the same or narrower set of types as A; the return type is said to be covariant. On the other hand, the member functions of B must take the same or broader set of arguments compared with the member functions of A; the argument type is said to be contra variant.
Let’s take the following codes as an example.
string[] objs = new string[3];
static void Process(object[] objs)
objs[0] = new ArgumentException();
You can code this in C# and compile it successfully because array in .net is covariance. But apparently, it’s not safe.
But if you do this:
List<string> strList = new List();
IEnumerable<object> test3 = strList;
You will get a compile error, because until now C# generics are invariance. In C# 4.0, it provides us a safe co- and contra-variance.public interface IReader
T Read();
Through the out keyword, you can allow the type argument T only to be output by the methods declared on the interface.
Contra variance is also supported through the in keyword. When this is used the type argument can only be used for arguments.
public interface IWriter{ void Write(T thing);}
Section II 9.5 in the CLI specification covers this and the only difference from C# 4.0 is that + is used to denote covariance and - is used to denote contra variance.
Variant type parameters can only be declared on interfaces and delegate types, due to a restriction in the CLR. Variance only applies when there is a reference conversion between the type arguments. For instance, an IEnumerable<object> is not an IEnumerable because the conversion from int to object is a boxing conversion, not a reference conversion.

Thursday, November 13, 2008

New features in C#4.0 (1)

Dynamic Programming
The major theme for C# 4.0 is dynamic programming. Increasingly, objects are “dynamic” in the sense that their structure and behavior is not captured by a static type or at least not one that the compiler knows about when compiling your program. Some examples include:
a. objects from dynamic programming languages, such as Python or Ruby
b. ordinary .NET types accessed through reflection
c. objects with changing structure, such as HTML DOM objects
In order to clarify this, I copy a description about dynamic programming language from Wiki:

Dynamic programming language is a term used broadly in computer science to describe a class of high-level programming languages that execute at runtime many common behaviors that other languages might perform during compilation, if at all.

C# 4.0 features a new dynamic keyword that allows you to mix in a bit of late-bound code in the midst of your otherwise statically typed code in an extensible way. This helps cleanup the string-based programming mess that is a characteristic of late-bound code.
The dynamic keyword can be used when declaring a variable, method return type, or parameter. It is used to declare that the static type of the thing is dynamic. When a variable is marked as being dynamic, C# won’t bother to resolve calls made on that object at compile-time: instead it will delay all method resolution to run time, but will use exactly the same algorithm as it would have used, so that overload resolution works correctly. Not only method calls, but also field and property accesses, indexer and operator calls and even delegate invocations can be dispatched dynamically.
Runtime Lookup
At runtime a dynamic operation is dispatched according to the nature of its target object d:
COM objects
If d is a COM object, the operation is dispatched dynamically through COM IDispatch. This allows calling to COM types that don’t have a Primary Interop Assembly (PIA) and relying on COM features that don’t have a counterpart in C #, such as indexed properties and default properties.
Dynamic objects
If d implements the interface IDynamicObject d itself is asked to perform the operation. Thus by implementing IDynamicObject a type can completely redefine the meaning of dynamic operations. This is used intensively by dynamic languages such as IronPython and IronRuby to implement their own dynamic object models. It will also be used by APIs, e.g. by the HTML DOM to allow direct access to the object’s properties using property syntax.
Plain objects
Otherwise d is a standard .NET object, and the operation will be dispatched using reflection on its type and a C# “runtime binder” which implements C#’s lookup and overload resolution semantics at runtime. This is essentially a part of the C# compiler running as a runtime component to “finish the work” on dynamic operations that was deferred by the static compiler.
Dynamic Language Runtime
An important component in the underlying implementation of dynamic lookup is the Dynamic Language Runtime (DLR), which is a new API in .NET 4.0. The DLR from Microsoft is an ongoing effort to bring a set of services that run on top of the CLR and provides and unifies language services for several different dynamic languages. These services include:
A dynamic type system, to be shared by all languages utilizing the DLR services.
a. Dynamic method dispatch
b. Dynamic code generation
c. Hosting API
The core of DLR includes Expression Trees, Dynamic Dispatch, and Call Site Caching. Expression Trees is introduced in LINQ; in C#4.0, it grows up to support statements. Dynamic Dispatch is about dispatching dynamic invocation to different binders, which allows us to communicate with different technologies. Call site caching is for efficiency. If the call is used many times, it just needs to do the resolution one time and cache the result then.
By having several dynamic language implementations share a common underlying system, it should be easier to let these implementations interact with one another. For example, it should be possible to use libraries from any dynamic language in any other dynamic language. In addition, the hosting API allows interoperability with statically typed .NET languages like C#. And the DLR will be used to implement dynamic languages like Python and Ruby on the .NET Framework. The DLR services are currently used in the development versions of IronRuby, a .NET implementation of the Ruby language, and the upcoming IronPython 2.0.

IDynamicObject interface
The basis of the dynamic resolution is the IDynamicObject interface, shared with the Dynamic Language Runtime. You can customize the dynamic process by implementing IDynamicObject interface, it can help you participate in the resolution of how method calls and property accesses are resolved. This has on it methods like Invoke which the compiler will call to allow the object itself to participate in method resolution. As well as allowing easy interaction with other dynamic languages such as IronPython and IronRuby this also has the benefit of making COM Interop much more natural. Rather than having to resort to Reflection, using dynamic typing will allow natural-looking code all the way.
public abstract class DynamicObject : IDynamicObject
public virtual object GetMember(GetMemberBinder info);
public virtual object SetMember(SetMemberBinder info, object value);
public virtual object DeleteMember(DeleteMemberBinder info);

public virtual object UnaryOperation(UnaryOperationBinder info);
public virtual object BinaryOperation(BinaryOperationBinder info, object arg);
public virtual object Convert(ConvertBinder info);

public virtual object Invoke(InvokeBinder info, object[] args);
public virtual object InvokeMember(InvokeMemberBinder info, object[] args);
public virtual object CreateInstance(CreateInstanceBinder info, object[] args);

public virtual object GetIndex(GetIndexBinder info, object[] indices);
public virtual object SetIndex(SetIndexBinder info, object[] indices, object value);
public virtual object DeleteIndex(DeleteIndexBinder info, object[] indices);

public MetaObject IDynamicObject.GetMetaObject();

var & dynamic
Please pay attention to the difference between var and dynamic. In C#3.0, there is a new keyword var. Local variables can be given an inferred "type" of var instead of an explicit type. The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement. The inferred type may be a built-in type, an anonymous type, a user-defined type, or a type defined in the .NET Framework class library.
But if the operand is dynamic, you can get the following benefits:
Member selection is deferred to run-time;
Actual type is substituted for dynamic at run-time;
Static result type of operation is dynamic.

Tuesday, November 04, 2008

What WCF client does ... (1)

Recently, I am curious about what WCF client really does when creating proxy object (ClientBase) or use the ChannelFactory directly.
If service reference is added by using the Visual Studio directly, it will automatically create a service client for you, it implements the service contract and inherits from the ClientBase; the generic type TChannel, it is not the IChannel, it is the service contract class. The following diagram is the class diagram for ClientBase.

It is just a snapshot; actually, there are many other members and methods. I only show you two important members: ChannelFactoryRef and EndpointTrait. When you create the client object, in the ClientBase class, the constructor will create one EndpointTrait object, it is used to create ChannelFactory. After that, the ClientBase is going to initialize the ChannelFactoryRef object.
Indeed, there is a cache called factoryRefCache of type ChannelFactoryRefCache, it is initialized in the static constructor of the ClientBase. When it initializes the ChannelFactoryRef object, it tries to get the object from the cache first, but if the state of the object isn’t opened, that means the object cannot be used, it will remove it from the cache and create a new object; else it uses it and adds one more reference. So, multiple clients for the same service may use the same ChannelFactory.
Let’s see what is going to happen when it needs to create a new object. It uses the EndpointTrait object to create the ChannelFactory object, and passes it to the ChannelFactoryRef constructor. You may have some imagination already; the ChannelFactoryRef is just a reference counter class for the ChannelFactory. After that, the ClientBase delegates all the work to the inner ChannelFactory object.
What is the job of the ChannelFactory? It creates the service endpoint first; then, it needs to configure this service endpoint. I use a diagram to show you the process.

From the diagram, it searches the configuration file first, if there is such a file, it read the configuration from it (LoadChannelBehaviors); if not, it uses some common configuration (LoadCommonClientBehaviors). In the LoadBehaviors() method, it gets all the IEndpointBehavior objects. Behavior is the most useful extensible point in WCF, IEndpointBehavior allows you to achieve the extensibility in client. If you want to apply you behavior to the client, you need to add your IEndpointBehavior to the IEndpointBehavior collection of ServiceEndpoint before it calls the ChannelFactory.Open() method.
Now, we need to use ChannelFactory.CreateChannel(), here is what happens.

It ensures the communication state is opened first. If the state isn’t opened, it calls Open(), in this step, it initializes the channel and applies some configuration (call opening()), let’s see what happens in detail.

ComputeContractRequirements() method is used to inject into the ContractDescription, it collects some information from it, such as the session mode, whether the operation is one-way etc. . In the BuildProxyBehavior() method, it gets the service endpoint’s contract description; then, based on the operation descriptions of the contract, it determines which operation type should be built. If the operation is initiated by the server, then it builds the dispatch operation (BuildDispatchOperation), because it acts as a receiver; otherwise, it builds a proxy operation (BuildProxyOperation), because it acts as a sender. In both methods, it adds the operation into the one collection of the ClientRuntime. The next step is to apply the client behavior, which is why I say you should add your IEndpointBehavior to the collection before you open it. In the BuildOperations() method, the IOperationBehavior will be applied according to their operation type: ApplyClientBehavior or ApplyDispatchBehavior. The ComputeRequiredChannels() uses the results from the ComputeContractRequirements() to determine which channel type it needs. Then, it compares these requirements with the Binding. If something mismatch, it throws exception. That’s all what happens before it opens the channel.
In order to get the service client, it creates a ServiceChannel object, CreateProxy() method creates the service client, the ServiceChannelProxy inherits the RealProxy, which is in the Remoting. The client uses the client to communicate with the service. WCF client runtime will actually intercept every WCF service call by injecting a TransparentProxy and ServiceChannelProxy between WCF service call site and underlying the channel stack. The reason WCF implements the client runtime the way it is that WCF needs to differ between normal method invocation and WCF service invocation on service proxy objects.
OK, the channel is prepared; we are ready to invoke the service, we can call the service just as invoking local method through the client. It is something like RPC or RMI, but there are many differences, I will explain what happens in this process in future.