Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

C# ПІДРУЧНИКИ / c# / MS Press - Msdn Training Programming Net Framework With C#

.pdf
Скачиваний:
173
Добавлен:
12.02.2016
Размер:
16.87 Mб
Скачать

Module 6: Working with Types

29

 

 

 

Inheritance Considerations

Topic Objective

To explain the use of inheritance and the use of interfaces.

Lead-in

Interfaces are used only through inheritance.

! Multiple Inheritance

interface IFoo {void DoSomething1();} interface IFoo {void DoSomething1();} interface IBar {void DoSomething2();} interface IBar {void DoSomething2();} class MyObject : IFoo, IBar {...} class MyObject : IFoo, IBar {...}

! Deriving New Interfaces from Existing Ones

interface INewInterface : IFoo, IBar interface INewInterface : IFoo, IBar

{void DoSomething3();} {void DoSomething3();}

! Base Class Interfaces

*****************************ILLEGAL FOR NON-TRAINER USE******************************

Interfaces are used only through inheritance. There are several ways to group or partition functionality when you are using interfaces. You can use multiple inheritance to combine functionality from multiple interfaces. Interfaces also can inherit from other interfaces, allowing functionality to be partitioned into multiple groups.

Multiple Inheritance

In the .NET Framework common language runtime, a class must inherit from only one class. However, a class can inherit from zero or more interfaces in addition to inheriting from one class. Interfaces are the only type to allow multiple inheritance in the common language runtime. The following example shows how a class can inherit from two interfaces.

interface IFoo

{

void DoSomething1();

}

interface IBar

{

void DoSomething2();

}

class MyObject : IFoo, IBar

{

public void DoSomething1()

{

Console.WriteLine("DoSomething1 called");

}

public void DoSomething2()

{

Console.WriteLine("DoSomething2 called");

}

}

30

Module 6: Working with Types

Multiple inheritance is an important design consideration when you are choosing between abstract classes and interfaces. If two sets of functionality are designed into two abstract classes, a single class cannot inherit from both classes. However, if interfaces are used, a single class can inherit from both interfaces. If a specification of functions, properties, or events is likely to be used by many different kinds of classes, you should use an interface instead of an abstract class.

Deriving New Interfaces from Existing Ones

You can also create new interfaces by deriving from other interfaces. The following example shows how a new interface that is called INewInterface is created from the IFoo and IBar interfaces.

interface IFoo

{

void DoSomething1();

}

interface IBar

{

void DoSomething2();

}

interface INewInterface : IFoo, IBar

{

void DoSomething3();

}

class MyObject : INewInterface

{

public void DoSomething1()

{

Console.WriteLine("DoSomething1 called");

}

public void DoSomething2()

{

Console.WriteLine("DoSomething2 called");

}

public void DoSomething3()

{

Console.WriteLine("DoSomething3 called");

}

}

Module 6: Working with Types

31

 

 

 

Base Class Interfaces

If you derive a new class from a base class that implements an interface, you must decide if the derived class will also implement the interface. When an instance of the derived class is converted to the interface, the inheritance hierarchy is searched until a class that implements the interface is found. Then the interface methods are called on that class.

The following example shows what happens when interface methods are called on a derived class that does not implement the interface.

interface IFoo

{

void DoSomething1();

}

class Base : IFoo

{

public void DoSomething1()

{

Console.WriteLine("Base DoSomething1 called");

}

}

class Derived : Base

{

public new void DoSomething1()

{

Console.WriteLine("Derived DoSomething1 called");

}

}

class MainClass

{

public static void Main()

{

Derived d = new Derived(); IFoo i = (IFoo) d; d.DoSomething1(); i.DoSomething1();

}

}

This code generates the following output:

Derived DoSomething1 called

Base DoSomething1 called

In the preceding example, the base class DoSomething1 method is called when an IFoo variable is used. If this behavior is not the desired behavior, then the derived class must be modified to also inherit from the IFoo interface. Then, the derived class DoSomething1 method will be called when the IFoo variable is used.

32

Module 6: Working with Types

Explicit Interface Implementation

Topic Objective

To distinguish class accessibility and interface accessibility, and to explain when to use explicit interface implementation.

Lead-in

When you implement an interface in a class, the interface methods are exposed through the interface type, and the class type.

!Class vs. Interface Accessibility

!Use Explicit Interface Implementation

#When interface member names that are combined with class names are confusing

#When inheriting from multiple interfaces with same members

interface IFoo {void DoSomething();} interface IFoo {void DoSomething();} interface IBar {void DoSomething();} interface IBar {void DoSomething();} class MyObject : IFoo, IBar {

class MyObject : IFoo, IBar { void IFoo.DoSomething() void IFoo.DoSomething()

{Console.WriteLine("IFoo DoSomething called");} {Console.WriteLine("IFoo DoSomething called");}

void IBar.DoSomething() void IBar.DoSomething()

}}

{Console.WriteLine("IBar DoSomething called");} {Console.WriteLine("IBar DoSomething called");}

*****************************ILLEGAL FOR NON-TRAINER USE******************************

When you implement an interface in a class, the interface methods are exposed through the interface type and the class type.

The following example shows how an interface method can be called by both the class type and the interface type.

interface IFoo

{

void DoSomething();

}

class MyObject : IFoo

{

public void DoSomething()

{

Console.WriteLine("DoSomething called");

}

}

class MainClass

{

public static void Main()

{

MyObject o = new MyObject(); //Call method through class type o.DoSomething();

IFoo foo = (IFoo) o;

//Call method through interface type foo.DoSomething();

}

}

Module 6: Working with Types

33

 

 

 

You can use explicit interface implementation to prevent the class type from accessing the method. This technique is useful if the interface member names are likely to confuse a user of the class. Also, explicit interface implementation is mandatory if you inherit from multiple interfaces that have the same members.

To use explicit interface implementation, you prepend the name of the interface to the name of the member in your class definition. You should not use any access modifiers in the member definition. Access modifiers are not allowed because the explicit interface implementation is only accessible through the interface type.

The following example shows how explicit interface implementation can avoid conflicts between multiple interfaces with the same members.

interface IFoo

{

void DoSomething();

}

interface IBar

{

void DoSomething();

}

class MyObject : IFoo, IBar

{

void IFoo.DoSomething()

{

Console.WriteLine("IFoo DoSomething called");

}

void IBar.DoSomething()

{

Console.WriteLine("IBar DoSomething called");

}

}

class MainClass

{

public static void Main()

{

MyObject o = new MyObject(); IFoo foo = (IFoo) o;

IBar bar = (IBar) o; foo.DoSomething(); bar.DoSomething();

}

}

This code generates the following output:

IFoo DoSomething called

IBar DoSomething called

34

Module 6: Working with Types

" Managing External Types

Topic Objective

To provide an overview of the topics covered in this section.

Lead-in

The .NET Framework common language runtime is not an isolated system. Most programs will require some level of interaction with outside applications.

!Platform Invocation Services

!COM Interoperability

*****************************ILLEGAL FOR NON-TRAINER USE******************************

The .NET Framework common language runtime is not an isolated system. Most programs will require some level of interaction with outside applications. The common language runtime provides Platform Invocation Services for interacting with code in DLLs. Also, the common language runtime provides integration services to interact with COM objects.

Warning Using unmanaged external types is risky because the common language runtime cannot enforce security, manage memory, or provide code type safety verification checking for unmanaged code.

This module does not cover all aspects of Platform Invocation Services or COM Integration Services. For more information, see Module 15, “Interoperating Between Managed and Unmanaged Code,” in Course 2349B, Programming with the Microsoft .NET Framework (Microsoft Visual C# .NET) and “Interoperating with Unmanaged Code” in the .NET Framework SDK documentation.

Module 6: Working with Types

35

 

 

 

Platform Invocation Services

Topic Objective

To introduce the use of Platform Invocation Services to call external functions.

Lead-in

Platform Invocation Services, also known as PInvoke, allow managed code to interact with unmanaged code in existing DLLs.

!Also Known as PInvoke

!Use DllImport Attribute to Import an API Function from an External DLL

[DllImport("user32.dll", CharSet=CharSet.Ansi)]

[DllImport("user32.dll", CharSet=CharSet.Ansi)]

public static extern int MessageBox(int h, string m, public static extern int MessageBox(int h, string m,

string c, int type); string c, int type);

public static void Main()

public static void Main()

{

string pText = "Hello World!";

{

string pText = "Hello World!";

 

string pCaption = "PInvoke Test";

 

string pCaption = "PInvoke Test";

MessageBox(0, pText, pCaption, 0); }

MessageBox(0, pText, pCaption, 0); }

*****************************ILLEGAL FOR NON-TRAINER USE******************************

Platform Invocation Services, also known as PInvoke, allow managed code to interact with unmanaged code in existing DLLs. PInvoke provides the code that is needed to locate and invoke a function and to marshal parameters to and from the function.

To call an external function, you use the DllImport attribute to provide the name of the DLL and any other characteristics, such as the use of ANSI or Unicode strings by the DLL. After the function has been declared, you can call it from managed code.

The following example shows how to call the MessageBox API located in

User32.dll.

using System;

using System.Runtime.InteropServices;

class MainClass

{

[DllImport("user32.dll", CharSet=CharSet.Ansi)] public static extern int MessageBox(int h, string m,

string c, int type);

public static void Main()

{

string pText = "Hello World!"; string pCaption = "PInvoke Test"; MessageBox(0, pText, pCaption, 0);

}

}

For more information on PInvoke, see Module 15, “Interoperating Between Managed and Unmanaged Code,” in Course 2349B, Programming with the Microsoft .NET Framework (Microsoft Visual C# .NET) and “Interoperating with Unmanaged Code” in the .NET Framework SDK documentation.

36

Module 6: Working with Types

COM Interoperability

Topic Objective

To introduce COM interoperability.

Lead-in

COM interoperability allows managed code to create and call COM objects. It also allows COM objects to create and call .NET Framework objects.

!Exposing .NET Framework Classes to COM

#Must create COM Callable Wrapper

#Create CCWs by using Tlbexp.exe

#Register by using Regasm.exe

!Exposing COM Classes to the .NET Framework

#Must create Runtime Callable Wrapper

#Create RCWs by using Tlbimp.exe

*****************************ILLEGAL FOR NON-TRAINER USE******************************

COM interoperability allows managed code to create and call COM objects. It also allows COM objects to create and call .NET Framework objects.

Exposing .NET Framework Classes to COM

You can expose .NET Framework classes to COM by creating COM callable wrappers (CCW) for each .NET Framework class in your application. The CCW creates and manages standard COM elements, such as IUknown and other standard interfaces, GUIDs, IIDs, and reference counting. These elements allow COM objects to interoperate with your .NET Framework classes as if the

.NET Framework classes were real COM classes.

The .NET Framework classes that you write do not need to be aware of any COM elements. However, you can directly control some COM elements when necessary, by such means as specifying manual IIDs for your interfaces.

You can create CCWs for your .NET Framework classes by running the Type Library Exporter (Tlbexp.exe). You can also register your .NET Framework classes as COM classes by using the Assembly Registration Tool (Regasm.exe).

Module 6: Working with Types

37

 

 

 

Exposing COM Classes to the .NET Framework

Managed code can also create and call existing COM objects. You can accomplish this by creating a runtime callable wrapper (RCW) for each COM class that you want to access from managed code. Similar to the CCW, the RCW handles COM specific semantics, such as reference counting, QueryInterface for different IIDs, and marshaling. Your managed code can use COM interfaces as if they were managed interfaces and COM classes as if they were managed classes.

You can create RCWs by using the Type Library Importer (Tlbimp.exe).

For more information on COM Interopability, see Module 15, “Interoperating Between Managed and Unmanaged Code,” in Course 2349B, Programming with the Microsoft .NET Framework (Microsoft Visual C# .NET) and “Interoperating with Unmanaged Code” in the .NET Framework SDK documentation.

38

Module 6: Working with Types

Lab 6: Working with Types

Topic Objective

To introduce the lab.

Lead-in

In this lab, you will create a class that overrides methods in System.Object. You will also create an interface that must be implemented explicitly.

*****************************ILLEGAL FOR NON-TRAINER USE******************************

Objectives

After completing this lab, you will be able to:

!Create classes that override the GetHashCode, and equality methods and operators.

!Create classes that provide conversion operators.

!Implement an explicit interface in a class and use it from a client.

Lab Setup

Starter and solution files are associated with this lab. The starter files are in the folder <install folder>\Labs\Lab06\Starter, and the solution files are in the folder <install folder>\Labs\Lab06\Solution.

Prerequisites

Before working on this lab, you must have:

!Knowledge about how to use Microsoft Visual Studio® .NET for creating and working with console applications.

!Knowledge about the C# language.

!Knowledge about the System.Console namespace for interacting with the console.

Estimated time to complete this lab: 45 minutes

Соседние файлы в папке c#