hf

导航

 

The Different Kinds of Type Members

A type can define zero or more of the following kinds of members:

  • Constants
  • Fields
  • Instance constructors
  • Type constructors
  • Methods
  • Operator overloads:     not CLS
  • Conversion operators:  not CLS
  • Properties
  • Events
  • Types

All the members defined in the source code cause the compiler to emit some metadata .

Type Visibility

public or internal(default)

Friend Assemblies

Friend assemblies can access all of an assembly’s internal types as well as these type’s internal members .

InternalsVisibleTo attribute:[assembly:InternalsVisibleTo("Wintellect, PublicKey=12345678...90abcdef")]

Member Accessibility

 

CLR Term C# Term Description
Private private

defining type,nested type

Family protected

defining type,nested type,
derived types (regardless of assembly)

Family and Assembly

(not supported)

defining type,nested type,
derived types defined in the same assembly

Assembly internal defining assembly
Family or Assembly protected internal

nested type, defining assembly,
derived type (regardless of assembly)

Public public any assembly

For any member to be accessible, it must be defined in a type that is visible .

In C#, if you do not explicitly declare a member’s accessibility, the compiler usually(except interface) defaults to selecting private   .

When a derived type is overriding a member defined in its base type, the C# compiler requires that the members have the same accessibility . This is not a CLR restriction ,the CLR allows a member’s accessibility to become less restrictive but not more restrictive .

Static Classes

Static classes(as abstract sealed in metadata)have only static members and, in fact, the classes exist simply as a way to group a set of related members together .

Structures (value types) can not be static .

Restrictions on a static class:

  • The class must be derived directly from System.Object because deriving from any other base class makes no sense since inheritance applies only to objects, and you cannot create an instance of a static class .
  • The class must not implement any interfaces since interface methods are callable only when using an instance of a class .
  • The class must define only static members (fields, methods, properties, and events) .
  • The class cannot be used as a field, method parameter, or local variable because all of these would indicate a variable that refers to an instance, and this is not allowed .

Partial Classes, Structures, and Interfaces

This feature is offered entirely by the C# compiler ; the CLR knows nothing about partial classes, structures, and interfaces .

The partial keyword tells the C# compiler that the source code for a single class, structure, or interface definition may span one or more source code files . There are three main reasons why use  Partial Classes:Source control ,Splitting a class or structure into distinct logical units within a single file ,Code spitters.

Components, Polymorphism, and Versioning

Here are some attributes of a component:

  • A component (an assembly in  .NET) has the feeling of being “published .”
  • A component has an identity (a name, version, culture, and public key) .
  • A component forever maintains its identity .
  • A component clearly indicates the components it depends upon (reference metadata tables) .
  • A component should document its classes and members .
  • A component must specify the security permissions it requires . (CAS)
  • component publishes an interface (object model) that won’t change for any servicings .

How the CLR Calls Virtual Methods, Properties, and Events

Properties and events are actually implemented as methods.

The CLR offers two IL instructions for calling a method:

  • The call IL instruction can be used to call static, instance, and virtual methods . The call instruction is frequently used to call a virtual method nonvirtually .
  • The callvirt IL instruction can be used to call instance and virtual methods, not static methods .Because of null check, this instruction executes slightly more slowly than the call instruction .

Regardless of whether call or callvirt is used to call an instance or virtual method, these methods always receive a hidden this argument as the method’s first parameter .

When designing a type, you should try to minimize the number of virtual methods you  define :

  • First, calling a virtual method is slower than calling a nonvirtual method .
  • Second,  virtual methods cannot be inlined by the JIT compiler, which further hurts performance .
  • Third, virtual methods make versioning of components more brittle.
  • Fourth, when defining a base type, it is common to offer a set of convenience overloaded methods . If you want these methods to be polymorphic, the best thing to do is to make the most complex method virtual and leave all of the convenience overloaded methods nonvirtual .

Using Type Visibility and Member Accessibility Intelligently

When defining a new type, compilers should make the class sealed by default so that the class cannot be used as a base class . As:

  • Versioning:When a class is originally sealed, it can change to unsealed in the future  without breaking compatibility . However, once a class is unsealed, you can never change it to sealed in the future as this would break all derived classes .
  • Performance:Calling a virtual method doesn’t perform as well as calling a nonvirtual method because the CLR must look up the type of the object at runtime in order to determine which type defines the method to call . However, if the JIT compiler sees a call to a virtual method using a sealed type, it can produce more efficient code by calling the method nonvirtually .
  • Security and predictability:A class must protect its own state and not allow itself to ever become corrupted .

Here are the guidelines I follow when I define my own classes:

  • When defining a class, I always explicitly make it sealed unless I truly intend for the class to be a base class that allows specialization by derived classes .
  • Inside the class, I always define my data fields as private and I never waver on this .
  • Inside the class, I always define my methods, properties, and events as private and nonvirtual .
  • When things get too complicated, make more types .

Dealing with Virtual Methods When Versioning Types

new,virtual,override...

posted on 2010-07-13 16:49  hf  阅读(287)  评论(0)    收藏  举报