COM Interop in c# 4.0
// Code simplified for this example
using Microsoft.Office.Interop;
using Microsoft.Office.Interop.Word;
object foo = "MyFile.txt";
object bar = Missing.Value;
object optional = Missing.Value;
Document doc = (Document)Application.GetDocument(ref foo, ref bar, ref optional);
doc.CheckSpelling(ref optional, ref optional, ref optional, ref optional);
There are (at least) three problems with the code above. First, you have to declare all your variables as objects and pass them with the ref keyword. Second, you can't omit parameters and must also pass the Missing.Value even if you are not using the parameter. And third, behind the scenes, you are using huge (in file size) interop assemblies just to make one method call.
C# 4.0 will allow you to write the code above in a much simpler form that ends up looking almost exactly like 'normal' C# code. This is accomplished by using some of the features already discussed; namely dynamic support and optional parameters.
// Again, simplified for example.
using Microsoft.Office.Interop.Word;
var doc = Application.GetDocument("MyFile.txt");
doc.CheckSpelling();
Named Parameters in C#4.0
In the last example, we saw that the following call was invalid:
Process( "foo", myArrayList ); // Invalid!
But if the boolean ignoreWS is optional, why can't we just omit it? Well, one reason is for readability and maintainability, but primarily because it can become impossible to know what parameter you are specifying. If you had two parameters of the same type, or if one of the parameters was "object" or some other base class or interface, the compiler would not know which parameter you are sending. Imagine a method with ten optional parameters and you give it a single ArrayList. Since an ArrayList is also an object, an IList, and an IEnumerable, it is impossible to determine how to use it. Yes, the compiler could just pick the first valid option for each parameter (or a more complex system could be used), but this would become impossible for people to maintain and would cause countless programming mistakes.
Named parameters provide the solution:
ArrayList myArrayList = new ArrayList();
Process( "foo", true ); // valid, moreData omitted
Process( "foo", true, myArrayList ); // valid
Process( "foo", moreData: myArrayList); // valid, ignoreWS omitted
Process( "foo", moreData: myArrayList, ignoreWS: false ); // valid, but silly
As long as a parameter has a default value, it can be omitted, and you can just supply the parameters you want via their name. Note in the second line above, the 'true' value for ignoreWS did not have to be named since it is the next logical parameter.
Optional Parameters in C#4.0
Support for optional parameters allows you to give a method parameter a default value so that you do not have to specify it every time you call the method. This comes in handy when you have overloaded methods that are chained together.
The Old Way
public void Process( string data )
{
Process( data, false );
}
public void Process( string data, bool ignoreWS )
{
Process( data, ignoreWS, null );
}
public void Process( string data, bool ignoreWS, ArrayList moreData )
{
// Actual work done here
}
The reason for overloading Process in this way is to avoid always having to include "false, null" in the third method call. Suppose 99% of the time there will not be 'moreData' provided. It seems ridiculous to type and pass null so many times.
// These 3 calls are equivalent
Process( "foo", false, null );
Process( "foo", false );
Process( "foo" );
The New Way
public void Process( string data, bool ignoreWS = false, ArrayList moreData = null )
{
// Actual work done here
}
// Note: data must always be provided because it does not have a default value