CHAPTER 3 LANGUAGE AND DYNAMIC CHANGES
45
.NET optional and named parameters make this much easier:
var betterWay = WordApplication.Documents.Open(file, ReadOnly: true, Visible: true);
betterWay.Activate();
The new dynamic functionality (which we will look at shortly) can also make your code more
readable by allowing you to infer many casting operations. For example, the compiler can now work out
the type of object you are using (duck typing) allowing code such as
((Excel.Range) excel.Cells[1, 1]).Value2 = "Excell-ent!";
… to be rewritten as:
excel.Cells[1, 1].Value = "Excell-ent!";
Not hugely different, but much more readable.
We’re Out of PIA
Another COM-related change worth mentioning is that you no longer need PIA files. In previous
versions of Visual Studio, when a COM component was referenced, Visual Studio would create an
additional assembly to describe the COM DLL to the CLR (a PIA or Primary Interop Assembly).
Unfortunately, these PIA files could get pretty large as they described every method of the COM
object even if you were not using them. In VS2010 to stop Visual Studio generating PIA files simply set
the Embed Interop Types property to True in Solution Explorer.
Variance
Variance has changed in .NET 4.0. At the 2008 PDC Anders Hejlsberg (lead architect of C#) summarized
the changes to variance as:
(Allowing) you to do things in your code that previously you were surprised
public class Animal { }
public class Elephant : Animal { }
2. Enter the following code:
class Program
{
public class Animal { }
public class Elephant : Animal { }
static void Main(string[] args)
{
Animal[] animals = new Elephant[10];
animals[0] = new Animal();
}
}
3. Compile your code.
Everything should be fine but now run the application. An exception will be thrown on the second line:
Attempted to access an element as a type incompatible with the array
Whoa, but the compiler let us do this, and then complains about a type exception. What gives?
• We are allowed to put Elephants in an Animal array, because Elephant inherits from
Animal and it will also have all the properties of Animal.
• Animals, however, will not necessarily have features specific to Elephants (such as
trunks, tusks, and an enviable memory), so the reverse is not true.
• This exception occurs because our Animals array actually consists of Elephants, so is
essentially an Elephant array.
CHAPTER 3 LANGUAGE AND DYNAMIC CHANGES
47
Code that compiles but throws type exceptions at runtime is bad news, so when Generics were
introduced, Microsoft was not going to have this problem so made Generics i
invariant
There is no reason this shouldn’t work, as the code is safe. By using the IEnumerable interface,
Animals are only ever returned in the output position, and you cannot do any reassignment. So the new
variance changes are very much fixing a problem that should never have existed.
Out
The previous example works in .NET 4.0 because the IEnumerable<T> interface now has the out keyword
in its parameter list, which enables us to use a more specific class (Elephant) when a more general class
(Animal) should be used. The out keyword tells the compiler that Animal can only ever be returned (in the
output position), which keeps the compiler happy, because IEnumerable contains no way for you to add
objects to it after IEnumerable is declared. This avoids the problems discussed previously and ensures
type safety.
The term for this is covariance, and it allows an item to be treated as its supertype. For example,
IEnumerable<string> can also be IEnumerable<object> (note that variance only applies to reference types
so will not affect integer for example).
Contravariance, which we will look at shortly, is the exact opposite. It allows a type like
Action<Object> to be treated as a subtype Action<String>.>.
You can add the out modifier to your own interfaces and delegates. It has also been added to the
following generic intefaces:
• IEnumerable<out T>
• IEnumerator<out T>
• IQueryable<out T>
Contravariance
Related to covariance is contravariance. Contravariance is the opposite to covariance, and allows you to
use a more general class when a specific class should be used. Contravariance uses the In modifier to
specify the parameter can only occur in the input position. You can add the In modifier to your own
interfaces and delegates, and it has been added to the following generic interfaces and delegates:
• IComparer<in T>
• IEqualityComparer <in T>
• Func<in T, , out R>
CHAPTER 3 LANGUAGE AND DYNAMIC CHANGES
public Elephant(string InputName, int InputWeight) : base(InputName, InputWeight)
{
}
}
3. To weigh all our animals, we will create a new class called WeightComparer that will implement
the IComparer interface; implementing the IComparer interface will then enable us to use the
Sort() method on the list object. Create the WeightComparer class with this code:
CHAPTER 3 LANGUAGE AND DYNAMIC CHANGES
50
public class WeightComparer : IComparer<Animal>
{
public int Compare(Animal x, Animal y)
{
if (x.Weight > y.Weight) return 1;
if (x.Weight == y.Weight) return 0;
return -1;
}
}
ICOMPARER
IComparer accepts two parameters and will return an integer representing whether one object is greater,
equal, or less than the other. In our example:
0 if
x.weight equals y.weight
1 if
x.weight is more than y.weight
-1 if
x.weight is less then y.weight
4. We will now add some animals to sort so alter the Main method to the following:
•
default.aspx
• Skeet, Jon. (2008) C# in depth. Manning Publications.
Dynamic Enhancements
The new dynamic functionality in .NET 4.0 allows us to work with types not known at compile time in an
intuitive and easy to read way. Many of you may be wondering what can the dynamic changes do for
you. The dynamic changes allow us to do the following:
• Write more readable code with fewer casting operations.
• Create new languages to utilize the .NET Framework, such as IronPython and
IronRuby. Additionally, .NET’s dynamic architecture allows these languages to
automatically benefit from future framework advances.Utilize other dynamic
languages and their libraries.
• Utilize other dynamic languages and their libraries from C# and VB.NET.
• Introduce customization/scripting and debugging/querying functionality within
our applications.
• Work with COM objects more easily. Microsoft Office COM is going to be around
for some time whether you like it or not.
• Many other cool uses we haven’t thought of yet.
Can’t We Do This Kind of Thing Already in .NET?
.NET has a number of classes and methods for working with types not known at compile time, such as
reflection and expression trees. However, if you have spent much time with these technologies, you will
known that they can make for some clunky and difficult to read code. As I will show you, the dynamic
enhancements can make your life much easier.
Before we look at how to use the dynamic enhancements, we need to understand the difference
between statically and dynamically typed languages.
Static Languages
In a statically typed language, such as C# or C, the compiler checks you are using types correctly at
compile time. Compilation will fail, for example, if you assign a string to an integer or misspell a variable
name. Statically typed languages can catch simple syntax errors and typos during development and as
the compiler knows the types it will be working with static languages generally run quicker then dynamic