Effective C# 50 Specific Way to Improve Your C# Item 30,31 Scott68.Chang.
-
Upload
diana-parsons -
Category
Documents
-
view
220 -
download
4
Transcript of Effective C# 50 Specific Way to Improve Your C# Item 30,31 Scott68.Chang.
Effective C#50 Specific Way to Improve Your C#
Item 30,31
Effective C#50 Specific Way to Improve Your C#
Item 30,31
Scott68.Chang
AgendaAgenda
• Chapter 4. Creating Binary Components
• Item 30: Prefer CLS-Compliant Assemblies
• Item 31: Prefer Small, Simple Functions
Chapter 4. Creating Binary Components
.Net and CLR.Net and CLR
• The .NET environment is designed to support applications that consist of multiple binary components. – upgrade those components independently, – installing and upgrading one assembly in a multi-assembly
application.• The CLR loader
– determine what file gets loaded (strong- and weak-named assemblies)
– determines whether the assembly is already loaded into the current application context.
– search and load assembly
Loader searches sequence Loader searches sequence
• loader searches a set of predefined directories:– The application directory.
Ex: /FrameworkV2– The culture directory.
Ex: /FrameworkV2/en-US– The assembly subdirectory.
Ex1: /FrameworkV2/[assemblyname] Ex2: /FrameworkV2 /[culture]/[assemblyname]
– The private binpath. This is a private directory defined in the application config file.
Ex1: [binpath] Ex2: [binpath]/[assemblyname]
Strong NameStrong Name
• A strong name consists of four items:– text name of the assembly– version number – culture attribute– public key token
• Benefit:– components will be less likely to be replaced by malicious
components. – use config files to map the requested version to a new,
improved version of a component.
Sample: Strong NameSample: Strong NameIn assemblyInfo.cs
[assembly: AssemblyTitle("My Assembly")][assembly: AssemblyDescription ("This is the sample assembly")]#if DEBUG[assembly: AssemblyConfiguration("Debug")]#else[assembly: AssemblyConfiguration("Release")]#endif[assembly: AssemblyCompany("My company")][assembly: AssemblyProduct("It is part of a product")][assembly: AssemblyCopyright("Insert legal text here.")][assembly: AssemblyTrademark("More legal text")][assembly: AssemblyCulture(“en-US”)][assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyDelaySign(false)][assembly: AssemblyKeyFile("")][assembly: AssemblyKeyName("")]
Assembly Configuration Information Assembly Configuration Information
• use the application config file to upgrade one application and then use a publisher policy file to upgrade a component shared by many applications.– machine.config
<dependentAssembly> <assemblyIdentity name="MyAssembly" publicKeyToken="a0231341ddcfe32b" culture="neutral" /> <bindingRedirect oldVersion="1.0.1444.20531" newVersion="1.1.1455.20221" /></dependentAssembly>
Item 30: Prefer CLS-Compliant Assemblies
Common Language Subsystem (CLS)Common Language Subsystem (CLS)
• Fully interact with other objects regardless of the language .
• Define a set of basic language features needed by many applications.
CLS-compliant assemblyCLS-compliant assembly
• Two rules to create a CLS-compliant assembly, – Rule1. the type of all parameters and return values from
public and protected members must be CLS compliant. – Rule2. any non-CLS-compliant public or protected member
must have a CLS-compliant synonym.
Rule1. CLS compliant memberRule1. CLS compliant member
• Add the CLSCompliant attribute to your assembly:– [ assembly: CLSCompliant( true ) ]
• Compiler enforces CLS compliance for the entire assembly
• CLS-compliant interfaces are required only for items that are exposed outside the assembly.– Compiler report an error if a public method or property that
is not compliant with CLS
Sample: incompliantSample: incompliant
// Not CLS Compliant, returns unsigned int:public UInt32 Foo( ){ return _foo;}
// Not CLS compliant, parameter is an unsigned int.public void Foo2( UInt32 parm ){}
Sample: PropertiesSample: Properties
// TheProperty is CLS compliant only if MyClass resides in a CLS-compliant assembly.public MyClass TheProperty{ get { return _myClassVar; } set { _myClassVar = value; }}
Rule2. CLS-compliant synonymRule2. CLS-compliant synonym
• The second rule is up to you: – make all public and protected operations are language-
agnostic. – make sure the polymorphism interface do not sneak a
noncompliant object.
Operator overloadingOperator overloading
• The CLS standard does not take a pro or con stance on the concept of operator overloading– not every language supports or allows operator
overloading.– it only defines a function name for each operator:
op_ function name Ex: op_equals, op_addis
Sample: overload an operatorSample: overload an operator
// Overloaded Addition operator, preferred C# syntax:public static Foo operator+( Foo left, Foo right){ // Use the same implementation as the Add method: return Foo.Add( left, right );}
// Static function, desirable for some languages:public static Foo Add( Foo left, Foo right){ return new Foo ( left.Bar + right.Bar );}
Non-CLS types sneaking into an interfaceNon-CLS types sneaking into an interface• Non-CLS types sneaking into an interface when you
use polymorphic arguments.– The end result is a type that some languages cannot use.
Sample: Hiding the non-compliant objectSample: Hiding the non-compliant object
// non-CLS types internal class BadEventArgs : EventArgs{ internal UInt32 ErrorCode;}
// Hiding the non-compliant event argument:public delegate void MyEventHandler(object sender, EventArgs args );
public event MyEventHandler OnStuffHappens;
// Code to raise Event:BadEventArgs arg = new BadEventArgs( );arg.ErrorCode = 24;
// Interface is legal, runtime type is not:OnStuffHappens( this, arg );
CLS-compliant class implements Non -CLS compliant InterfaceCLS-compliant class implements Non -CLS compliant Interface• All interfaces that you implement publicly must be
CLS compliant.– Hide a non-CLS compliant interface from your public
interface using explicit interface implementation.
Sample: CLS-compliant class Sample: CLS-compliant class
public interface IFoo2{ // Non-CLS compliant, Unsigned int void DoStuff( UInt32 arg1, string arg2 );}
public class MyClass: IFoo2{ // explicit interface implementation. // DoStuff() is not part of MyClass's public interface void IFoo2.DoStuff( UInt32 arg1, string arg2 ) { // content elided. }}
CLS compliantCLS compliant
• For any public or protected class, any type mentioned in these constructs must be CLS compliant:– Base classes– Return values for public and protected methods and
properties– Parameters for public and protected methods and indexers– Runtime event arguments– Public interfaces, declared or implemented
SummarySummary
• CLS 相容之物件可跨程式語言執行 (.NET)• 物件開發者須提供 CLS 相容之物件使其他使用者可以簡
單的開發出 CLS 相容之程式• 創建 CLS 相容的程式集的兩個規則:
– Public 與 Protected 成員的 Parameter 與回傳質都必須是 CLS 相容。
– 非 CLS 相容的 Public 與 Protected 成員必須存在 CLS 相容的相容物件。
Item 31: Prefer Small, Simple Functions
How the JIT compiler performs its workHow the JIT compiler performs its work
• Translate the IL (Intermediate Language, generated by C# compiler) into machine code
• The CLR invokes the JITer on a function-by-function basis– minimizes the startup cost to a reasonable level– minimize the amount of extraneous code– factoring code into more, smaller functions rather than
fewer larger functions
Sample: originalSample: original public string BuildMsg(bool takeFirstPath) { StringBuilder msg = new StringBuilder(); if (takeFirstPath) { msg.Append("A problem occurred."); msg.Append("\nThis is a problem."); msg.Append("imagine much more text"); } else { msg.Append("This path is not so bad."); msg.Append("\nIt is only a minor inconvenience."); msg.Append("Add more detailed diagnostics here."); } return msg.ToString(); }
Sample: optimizedSample: optimized
public string BuildMsg(bool takeFirstPath){ StringBuilder msg = new StringBuilder(); if (takeFirstPath) FirstPath(msg); else SecondPath(msg); return msg.ToString();}
private static void FirstPath(StringBuilder msg){ msg.Append("A problem occurred."); msg.Append("\nThis is a problem."); msg.Append("imagine much more text");}private static void SecondPath(StringBuilder msg){ msg.Append("This path is not so bad."); msg.Append("\nIt is only a minor inconvenience."); msg.Append("Add more detailed diagnostics here.");}
Enregistration Enregistration
• Smaller and simpler functions make it easier for the JIT compiler to support enregistration– Selecting which local variables can be stored in registers
rather than on the stack• For example:
– If a function has one loop, that loop variable will likely be enregistered.
– If a function with several loops, the JIT compiler must make some tough choices about enregistering loop variables.
InliningInlining
• The JIT compiler also makes decisions about inlining methods– Substitute the body of a function for the function call– No keyword to give a hint to the compiler that a method
should be inlined.– The small functions that are virtual or that contain try/catch
blocks cannot be inlined
Sample:Sample:
Original Optimized:
against with Item 1 public string _name;
// access:
string val = Obj._name;
// readonly name property:private string _name;public string Name{ get { return _name; }}
// access:string val = Obj.Name;
SummarySummary
• C# Compiler 與 JIT Compiler 會自動針對硬體特性選擇最適合的方法來執行程式,而我們只須負責撰寫小而簡單的函數。