1. Trang chủ
  2. » Công Nghệ Thông Tin

Lập trình .net 4.0 và visual studio 2010 part 6 pdf

7 385 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 7
Dung lượng 1,04 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

• 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.. The following will not compile for the pr

Trang 1

.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

you couldn’t do.

For those that are already comfortable with the concept of variance (stop looking so smug) here is

the short version of what has changed in NET 4.0:

• You can now mark parameters in generic interfaces and delegates with the out

keyword to make them covariant, and with the in keyword to make them

contravariant (In and Out in VB.NET)

• The in/out keywords have been added to some commonly used generic interface

and delegate types to now enable them to support safe co- and contravariance (for

example, IEnumerable<out t> and Action<in t>)

If this means nothing to you, read on Variance is a confusing subject, and I suspect you can have a happy development career without it ever really affecting you It is only applicable in a rare number of situations

Trang 2

Don’t feel bad if you have never heard of variance I hadn’t either, before researching this chapter

At WebDD09 conference in the UK, I asked who was familiar with variance in a room of 120 developers

to find just 3 people put their hand up

The Long Version for Everyone Else

To really understand variance, we need to go back in time to somewhere around the year 2000 Was the world a happier place? Who knows But what’s important for our discussions is that Java was pretty big around that time, and Microsoft wanted to lure Java developers over to C# To ease the transition between the two languages, Microsoft brought some controversial functionality from Java to NET and

made arrays co-variant Right, why is this bad?

Bad Arrays of Animals and Elephants

To demonstrate why co-variant arrays are bad, create a new console application called

Chapter3.Variance

1 Now create two classes, Animal and Elephant Note that Elephant inherits from Animal - this is important:

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

Trang 3

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 iinv a ria nt The following

will not compile for the previously stated reasons:

List<Animal> Animals = new List<Animal>();

//This will work fine as we can be sure Elephant has all Animal's properties

Animals.Add(new Elephant());

List<Elephant> Elephants = new List<Elephant>();

//This will not compile

Elephants.Add(new Animal());

This is further illustrated in Figure 3-2

Figure 3-2 Generic lists and variants, or why elephants are mean

So, What’s the Problem?

Well, some folk found that NET would stop them from writing code and modeling situations that are

safe For example, the following did not work prior to NET 4.0:

Trang 4

IList<Elephant> elephants = new List<Elephant>();

IEnumerable<Animal> animals = elephants;

Here, the exception is:

Cannot implicitly convert type

'System.Collections.Generic.IList<Chapter3.Elephant>' to

'System.Collections.Generic.IEnumerable<Chapter3.Animal>' An explicit conversion exists (are you missing a cast?)

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>

Trang 5

• Action<in T, >

• Predicate<in T>

• Comparison<in T>

• EventHandler<in T>

Example of Contravariance

Let’s say we want to create a common class that will sort animals by weight It would be great if we could use this same class to weigh anything that had a base class of Animal, but as you can guess the code we will write won’t work in VS2008

We will add Weight and Name properties to the Animal class so we can easily identify individual Animal instances

1 Modify the Animal class so it now looks like:

public class Animal

{

public int Weight { get; set; }

public string Name { get; set; }

public Animal()

{ }

public Animal(string InputName, int InputWeight)

{

Name = InputName;

Weight = InputWeight;

}

}

2 Now modify the Elephant class to the following:

public class Elephant : Animal

{

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:

Trang 6

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:

static void Main(string[] args)

{

WeightComparer objAnimalComparer = new WeightComparer();

List<Animal> Animals = new List<Animal>();

Animals.Add(new Animal("elephant", 500));

Animals.Add(new Animal("tiger", 100));

Animals.Add(new Animal("rat", 5));

//Works

Animals.Sort(objAnimalComparer);

List<Elephant> Elephants = new List<Elephant>();

Elephants.Add(new Elephant("Nellie", 100));

Elephants.Add(new Elephant("Dumbo", 200));

Elephants.Add(new Elephant("Baba", 50));

//Doesn't work prior to net 4

Elephants.Sort(objAnimalComparer);

Elephants.ForEach(e=> Console.WriteLine(e.Name + " " + e.Weight.ToString())); }

5 Compile the code, and you should find that the elephants are sorted by weight; however, if you try this code in VS2008, you will find it will not compile

Trang 7

Further Reading

Variance is a difficult subject, so for more information please refer to the following blogs and book:

http://blogs.msdn.com/charlie/archive/2008/10/28/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx

• http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/

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 languages (next) as optimizations can be performed on code

Ngày đăng: 01/07/2014, 21:20

TỪ KHÓA LIÊN QUAN