1.The Different Kinds of Type Members

  1.Constants:a symbol that identifies a never-changing data value.Constants are always associated with a type, not an instance of a type. Logically, constants are always static members

  2.Fields:represents a read-only or read/write data value.encourage you to make fields private so that the state of the type or object can’t be corrupted by code outside of the defining type.

    A field can be static, in which case the field is considered part of the type’s state

    A field can also be instance (nonstatic), in which case it’s considered part of an object’s state.

  3.Instance constructors:initialize a new object’s instance fields to a good initial state.

  4.Type constructors:initialize a type’s static fields to a good initial state

  5.Methods:

    a function that performs operations that change or query the state of a type (static method) or an object (instance method).

    Methods typically read and write to the fields of the type or object

  6.Operator overloads:is a method that defines how an object should be manipulated when certain operators are applied to the object.

    Because not all programming languages support operator overloading, operator overload methods are not part of the Common Language Specification (CLS).

  7.Conversion operators:is a method that defines how to implicitly or explicitly cast or convert an object from one type to another type.  

  8.Properties:is a mechanism that allows a simple, field-like syntax for setting or querying part of the logical state of a type (static property) or object (instance property) while ensuring that the state doesn’t become corrupt.

    Properties can be parameterless (very common) or parameterful (fairly uncommon but used frequently with collection classes).

  9.Events:Events are usually raised in response to a state change occurring in the type or object offering the event.

    An event consists of two methods that allow static or instance methods to register and unregister interest in the event.events typically use a delegate field to maintain the set of registered methods.

    A static event is a mechanism that allows a type to send a notification to one or more static or instance methods;An instance (nonstatic) event is a mechanism that allows an object to send a notification to one or more static or instance methods.

  10.Types: A type can define other types nested within it.used to break a large, complex type down into smaller building blocks to simplify the implementation.

 

compile the type just defined and examine the metadata in ILDasm.exe

  6.Type and Member Basics6.Type and Member Basics

 

 

metadata:

  1.it enables the seamless integration of languages, types, and objects.

  regardless of the source programming language you useuse, and this feature is what makes the CLR a common language run time.

  The metadata is the common information that all languages produce and consume, enabling code in one programming language to seamlessly access code written in a completely different programming language

  2.is the key to the whole Microsoft .NET Framework development platform;

  This common metadata format:is used by the CLR, which determines how constants, fields, constructors, methods, properties, and events all behave at run time.

 

2.Type Visibility

  1.public:A public type is visible to all code within the defining assembly as well as all code written in other assemblies

  2.internal:An internal type is visible to all code within the defining assembly, and the type is not visible to code written in other assemblies.

  If you do not explicitly specify either of these when you define a type, the C# compiler sets the type’s visibility to internal (the more restrictive of the two).

  6.Type and Member Basics

 

Friend Assemblies:

  question:In order for TeamB’s assembly to use TeamA’s types, TeamA must define all of their utility types as public. However, this means that their types are publicly visible to any and all assemblies; developers in another company could write code that uses the public utility types, and this is not desirable.

  answer:The CLR and C# support this via friend assemblies.

  1.is a way for TeamA to define their types as internal while still allowing TeamB to access the types.

  2.is also useful when you want to have one assembly containing code that performs unit tests against the internal types within another assembly.

  how?

  it can indicate other assemblies it considers “friends” by using the InternalsVisibleTo attribute defined in the System.Runtime.CompilerServices namespace.

  The attribute has a string parameter that identifies the friend assembly’s name and public key (the string you pass to the attribute must not include a version, culture, or processor architecture). Note that friend assemblies can access all of an assembly’s internal types as well as these type’s internal members.

  6.Type and Member Basics6.Type and Member Basics

  1.the C# compiler requires you to use the /out:<file> compiler switch when compiling the friend assembly (the assembly that does not contain the InternalsVisibleTo attribute).

  The switch is required because the compiler needs to know the name of the assembly being compiled in order to determine if the resulting assembly should be considered a friend assembly

  You would think that the C# compiler could determine this on its own because it normally determines the output file name on its own; however, the compiler doesn’t decide on an output file name until it is finished compiling the code.

  So requiring the /out:<file> compiler switch improves the performance of compiling significantly.

  2.if you are compiling a module (as opposed to an assembly) using C#’s /t:module switch, and this module is going to become part of a friend assembly, you need to compile the module by using the C# compiler’s /moduleassemblyname:<string> switch as well. This tells the compiler what assembly the module will be a part of so the compiler can allow code in the module to access the other assembly’s internal types.

 

3.Member Accessibility

indicates which members can be legally accessed from referent code.

 

how?

  1.The CLR defines the set of possible accessibility modifiers, but each programming language chooses the syntax and term it wants developers to use when applying the accessibility to a member.

  6.Type and Member Basics

 

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

  For example,if AssemblyA defines an internal type with a public method, code in AssemblyB cannot call the public method because the internal type is not visible to AssemblyB.

 

compiling?

  1.the language compiler is responsible for checking that the code is referencing types and members correctly(emitting the appropriate error message)

  2.the just-in-time (JIT) compiler also ensures that references to fields and methods are legal when compiling IL code into native CPU instructions at run time.(FieldAccessException,MethodAccessException)

  Verifying the IL code ensures that a referenced member’s accessibility is properly honored at run time.

 

In C#, if you do not explicitly declare a member’s accessibility, the compiler usually (but not always) defaults to selecting private (the most restrictive of them all). The CLR requires that all members of an interface type be public.

 

 

When a derived type is overriding a member defined in its base type, the C# compiler requires that the original member and the overriding member have the same accessibility.

However, this is a C# restriction, not a CLR restriction.

When deriving from a base class, the CLR allows a member’s accessibility to become less restrictive but not more restrictive.The reason a class cannot make a base class method more restricted is because a user of the derived class could always cast to the base type and gain access to the base class’s method. If the CLR allowed the derived type’s method to be less accessible, it would be making a claim that was not enforceable.

4.Static Classes

There are certain classes that are never intended to be instantiated.C# allows you to define non-instantiable classes by using the C# static keyword

特点:

1.These classes have only static members and

2.the classes exist simply as a way to group a set of related members together

使用范围:

This keyword can be applied only to classes, not structures (value types)

because the CLR always allows value types to be instantiated and there is no way to stop or prevent this.

restrictions:

1.The class must be derived directly from System.Object

  because deriving from any other base class makes no sense

  because inheritance applies only to objects, and you cannot create an instance of a static class.

2.The class must not implement any interfaces

  because interface methods are callable only when using an instance of a class.

3.The class must define only static members (fields, methods, properties, and events).

  Any instance members cause the compiler to generate an error.

4.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.

  If the compiler detects any of these uses, the compiler issues an error.

6.Type and Member Basics6.Type and Member Basics

compile the code above into a library (DLL) assembly and look at the result by using ILDasm.exe:

  1.defining a class by using the static keyword causes the C# compiler to make the class both abstract and sealed

  2.the compiler will not emit an instance constructor method into the type.

    Notice that there is no instance constructor (.ctor) method shown.

5.Partial Classes, Structures, and Interfaces

The partial keyword : the C# compiler that the source code for a single class, structure, or interface definition may span one or

more source code files.

the compiler combines all of a type’s partials together at compile time; the CLR always works on complete type definitions.

why use it?

  1.Source control

  Suppose a type’s definition consists of a lot of source code, and a programmer checks it out of source control to make changes.No other programmer will be able to modify the type at the same time without doing a merge later.

  Using the partial keyword allows you to split the code for the type across multiple source code files, each of which can be checked out individually so that multiple programmers can edit the type at the same time.

  2.Splitting a class, structure, or interface into distinct logical units within a single file

  create a single type that provides multiple features so that the type can provide a complete solution.

  To simplify my implementation, sometimes declare the same partial type repeatedly within a single source code file.

  (1)in each part of the partial type,  implement one feature with all its fields, methods, properties, events, and so on. This allows  to easily see all the members that provide a single feature grouped together, which simplifies my coding.

  (2) can easily comment out a part of the partial type to remove a whole feature from the type and replace it with another implementation

  3.Code spitters

  Starting with Visual Studio 2005, when you create a new form, user control, and so on, Visual Studio creates two source code files: one for your code and the other for the code generated by the designer.

   Because the designer code is in a separate file, you’ll be far less likely to accidentally edit it.

how use it?

  1.The partial keyword is applied to the types in all files.  

  2.all of the source code files for the type must use the same programming language, and they must all be compiled together as a single compilation unit.

  When the files are compiled together, the compiler combines the code to produce one type that is in the resulting .exe or .dll assembly file (or .netmodule module file).

  the partial types feature is completely implemented by the C# compiler; the CLR knows nothing about partial types at all.

6.Components, Polymorphism, and Versioning

question:software is much more complex and users demand.it is no longer feasible or even cost effective for application developers to write all of the code necessary for their application to work the way users expect. Today, applications consist of code produced by many different companies

answer:This code is stitched together using an object-oriented paradigm.

 

Component Software Programming (CSP) :

  is OOP brought to this level.

  a big part of CSP has to do with versioning().

 

attributes of a component:

  1.A component (an assembly in the .NET Framework) has the feeling of being “published".

  2.has an identity (a name, version, culture, and public key).

  3.forever maintains its identity (the code in an assembly is never statically linked into another assembly; .NET always uses dynamic linking).

  4.A component clearly indicates the components it depends upon (reference metadata tables).

  5.should document its classes and members.

  C# offers this by allowing in-source Extensible Markup Language (XML) documentation along with the compiler’s /doc commandline switch.

  6.must specify the security permissions it requires. The CLR’s code access security (CAS) facilities enable this.

  7.A component publishes an interface (object model) that won’t change for any servicings.

  servicing is a new version of a component whose intention is to be backward compatible with the original version of the component.

  a servicing version includes bug fixes, security patches, and possibly some small feature enhancements.

  But a servicing cannot require any new dependencies or any additional security permissions.

  

component versioning:

  a version number consists: a major part, a minor part, a build part, and a revision part.

    1.The major/minor parts are typically used to represent a consistent and stable feature set for an assembly ;

    has significant changes to it,and is therefore not intended to be backward compatible with the original assembly,

 

    2.the build/revision parts are typically used to represent a servicing of this assembly’s feature set.

    This indicates that the assembly is a servicing whose intention is to be backward compatible with the original component(fix a bug)

 

  Unfortunately, the CLR doesn’t treat version numbers this way. Today, the CLR treats a version number as an opaque value, and if an assembly depends on version 1.2.3.4 of another assembly, the CLR tries to load version 1.2.3.4 only (unless a binding redirection is in place).

 

question:how use version numbers to update a component’s identity to reflect a new version

answer:some of the features offered by the CLR and programming languages (such as C#) that allow developers to write code that is resilient to changes that may be occurring in components that they are using.

6.Type and Member Basics

  C# offers five keywords that you can apply to types and/or type members that impact component versioning. These keywords map directly to features supported in the CLR to support component versioning

 

Versioning issues:

  if the base class versions (changes) underneath the derived class, the behavior of the derived class changes as well, probably in a way that causes the class to behave improperly.

  This is particularly true in polymorphism scenarios in which a derived type overrides virtual methods defined by a base type.

7.How the CLR Calls Virtual Methods, Properties, and Events

Properties and events are actually implemented as methods.

 

Methods:

  1.performs some operation on the type (static methods) or an instance of the type (nonstatic methods).

  2.have a name, a signature, and a return type (that may be void)

  3.method has a different set of parameters or a different return type

 

how compile?

  6.Type and Member Basics

  1.When the compiler compiles this code.method definition table. Each entry has flags set indicating if the method is instance, virtual, or static.

  2.made correctly

 

 

two IL instructions for calling a method:

  1.The call IL instruction can be used to call static, instance, and virtual methods.

  method that the CLR should call.

  assumes that this variable is not null.

  the method, base types are checked for a matching method

  used to call a virtual method nonvirtually.

  2.The callvirt IL instruction can be used to call instance and virtual methods, not static methods.

  specify a variable that refers to an object.

  that the CLR should call.

  calls the method polymorphically.

  that the callvirt IL instruction executes slightly more slowly than the call instruction.

  Note that this null check is performed even when the callvirt instruction is used to call a
nonvirtual instance method.

 

使用:

1.why didn’t the C# compiler simply emit the call instruction instead callvirt IL?

  that the object being used to make the call is not null

   6.Type and Member Basics6.Type and Member Basics

using System;
public sealed class Program {
  public Int32 GetFive() { return 5; }
  public static void Main() {

    Program p = null;
    Int32 x = p.GetFive(); // In C#, NullReferenceException is thrown
  }
}

throwing the NullReferenceException.

  

virtual in the future.

by using the call instruction instead of the callvirt instruction.

  will be called nonvirtually, causing the application to produce unpredictable behavior.

  methods by using callvirt.

using a different programming language.

 

callvirt instruction.

6.Type and Member Basics

  ensure that the ToString method in the base type is called nonvirtually.

which obviously is not desired.

 

4.Compilers tend to use the call instruction when calling methods defined by a value type.

which causes the performance of the call to be faster

guarantees it can never be null, so a NullReferenceException will never be thrown.

  performance.

 

6.refers to the object being operated on.

 

建议:

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

  1.calling a virtual method is slower than calling a nonvirtual method.

  2.cannot be inlined by the JIT compiler, which further hurts performance.

  3.versioning of components more brittle

  4.convenience overloaded methods nonvirtual.

6.Type and Member Basics

8.Using Type Visibility and Member Accessibility Intelligently 

question:

by various companies.

  1.or she is using and the types defined within those components.

  2.create the component), and components tend to version with different schedules.

  3.And, of course, the developer of a derived class must trust the code that he is inheriting from a base class

how to design a type with these issues in mind?

answer:

  1.When defining a class.

of what C# and many other compilers default to today.

if you do not explicitly indicate a type’s visibility, the C# compiler defaults to internal.

virtual methods that my class inherits.

  2.C# does default to making fields private.

and open potential security holes.

internal. Even within a single assembly, it is too hard to track all code that references a field.

  especially if several developers are writing code that gets compiled into the same assembly.

  3.Fortunately, C# defaults to this as well.

 

vulnerability.

on the proper behavior of the derived class.

  4.types.

types that encapsulate discrete pieces of functionality.

defined in the über-type.

types should be defined at file or assembly scope and not be defined within another type.

I appreciate this rule, and I never define public nested types.

 

question:unsealed class?

answer:

  1.Versioning

  the future as this would break all derived classes

  versions or there is the potential of breaking derived types in the future.

   2.Performance

  at run time in order to determine which type defines the method to call.

  can’t possibly be a derived class if the class is sealed.

  6.Type and Member Basics

  3.Security and predictability

  become corrupted.

  and not private.

  derived class can decide whether to call the base class’s implementation.

  opens up potential security holes.

 

fields or state information for their application’s own use.

helper or convenience methods on the derived type to manipulate these additional fields.

tacking state onto an object by using the ConditionalWeakTable class.

 

9.Dealing with Virtual Methods When Versioning Types  

other versioning issues cause source code compatibility problems.you be very careful when adding or modifying members of a type if that type is used as a base type.

 

 6.Type and Member Basics6.Type and Member Basics

warning CS0108: 'CompanyB.BetterPhone.Dial()' hides inherited member 'CompanyA.Phone.Dial()'.

It’s a very nice feature of the compiler to warn you of this potential semantic mismatch. 

 

Dial in the BetterPhone class?

answer:Use the new keyword if hiding was intended

  6.Type and Member Basics

  new Dial method defined by BetterPhone.

  6.Type and Member Basics

  6.Type and Member Basics

  override keyword. Otherwise, add the new keyword.

  6.Type and Member Basics

  the new keyword tells the compiler to emit metadata, making it clear to the CLR that BetterPhone’s EstablishConnection method is intended to be treated as a new function. Phone’s and BetterPhone’s methods.

  6.Type and Member Basics

  method calls Phone’s EstablishConnection method—this is the expected behavior.

 

建议:

  EstablishConnection don’t confuse other developers.

警告:

  EstablishConnection.

the entire source code base, breaking source and binary compatibility.

pervasive change is undesirable, especially in any moderate-to-large project.

 

相关文章: