effective c# 50 specific ways to improve your c# item 18~19 2012/08/15 1

34
Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 2012/08/15 1

Upload: rodney-cummings

Post on 05-Jan-2016

215 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Effective C# 50 Specific Ways to Improve Your C#

Item 18~19

Effective C# 50 Specific Ways to Improve Your C#

Item 18~19

2012/08/152012/08/15

1

Page 2: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

AgendaAgenda

• Item 18: Implement the Standard Dispose PatternItem 18: Implement the Standard Dispose Pattern• Item 19: Prefer Defining and Implementing Interfaces to InheritanceItem 19: Prefer Defining and Implementing Interfaces to Inheritance

Page 3: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

IMPLEMENT THE STANDARD DISPOSE PATTERN IMPLEMENT THE STANDARD DISPOSE PATTERN

Item 18:Item 18:

Page 4: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

How to write your own resource-management codeHow to write your own resource-management code• How to write your own resource-management code How to write your own resource-management code

when you create types that contain resources other when you create types that contain resources other than memory than memory

Answer:Answer:A standard pattern is used throughout the .NET A standard pattern is used throughout the .NET Framework for disposing of nonmemory resourcesFramework for disposing of nonmemory resources

Page 5: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

.NET Framework for disposing of nonmemory resources.NET Framework for disposing of nonmemory resources

• IDisposable IDisposable – The standard dispose idiom frees your unmanaged resourcesThe standard dispose idiom frees your unmanaged resources– The root base class in the class hierarchy should implement the The root base class in the class hierarchy should implement the

IDisposable interface to free resources. IDisposable interface to free resources.

• Finalizer defensivelyFinalizer defensively– The only way you can guarantee that nonmemory resources The only way you can guarantee that nonmemory resources

get freed properly is to create a finalizerget freed properly is to create a finalizer– It works with the Garbage CollectorIt works with the Garbage Collector

Page 6: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Garbage CollectorGarbage Collector

• It immediately removes from memory any garbage It immediately removes from memory any garbage objects that do not have finalizersobjects that do not have finalizers

• All objects that have finalizers remain in memory. These All objects that have finalizers remain in memory. These objects are added to a finalization queueobjects are added to a finalization queue

• Garbage Collector spawns a new thread to run the Garbage Collector spawns a new thread to run the finalizers on those objectsfinalizers on those objects

• After the finalizer thread has finished its work, the After the finalizer thread has finished its work, the garbage objects can be removed from memorygarbage objects can be removed from memory

So objects that need finalization stay in memory for far So objects that need finalization stay in memory for far longer than objects without a finalizerlonger than objects without a finalizer

Page 7: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

IDisposableIDisposable

• The standard way to inform users and the runtime The standard way to inform users and the runtime system that your objects hold resources that must be system that your objects hold resources that must be released in a timely mannerreleased in a timely manner

• The IDisposable interface contains just one method:The IDisposable interface contains just one method:

public interface IDisposable {

void Dispose( ); }

Page 8: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

IDisposable (Cont.)IDisposable (Cont.)

• Freeing all unmanaged resources.Freeing all unmanaged resources.• Freeing all managed resources (this includes unhooking Freeing all managed resources (this includes unhooking

events).events).• Setting a state flag to indicate that the object has been Setting a state flag to indicate that the object has been

disposeddisposed• Suppressing finalizationSuppressing finalization

– GC.SuppressFinalize(this)GC.SuppressFinalize(this)

Page 9: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

IDisposable (Cont.)IDisposable (Cont.)

• Provide the mechanism for clients to release all Provide the mechanism for clients to release all managed resources that you hold in a timely fashionmanaged resources that you hold in a timely fashion

• Give clients a standard way to release all unmanaged Give clients a standard way to release all unmanaged resourcesresources

Page 10: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

IDisposable (Cont.)IDisposable (Cont.)Public class MyResourceHog: IdisposablePublic class MyResourceHog: Idisposable{{

[System.Runtime.InteropServices.DllImport("Kernel32")][System.Runtime.InteropServices.DllImport("Kernel32")]private extern static Boolean CloseHandle(IntPtr handle);private extern static Boolean CloseHandle(IntPtr handle);private bool private bool _alreadyDisposed _alreadyDisposed = false;= false;~MyResourceHog()~MyResourceHog(){{

Dispose(false);Dispose(false);}}

public void Dispose()public void Dispose(){{

Dispose(true);Dispose(true);GC.SuppressFinalize(true);GC.SuppressFinalize(true);

}}

protected virtual void Dispose(bool isDisposing)protected virtual void Dispose(bool isDisposing){{

if(if(_alreadyDisposed _alreadyDisposed ))return;return;

if(isDisposing)if(isDisposing){{

//TODO: free managed resources here//TODO: free managed resources here component.Dispose();component.Dispose();

}}// TODO: free unmanaged resources here// TODO: free unmanaged resources here CloseHandle(handle);CloseHandle(handle); handle = IntPtr.Zero;handle = IntPtr.Zero; _alreadyDisposed = true;_alreadyDisposed = true;

}}}}

Page 11: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

IDisposable (Cont.)IDisposable (Cont.)

Public class DerivedResourceHog: MyResourceHogPublic class DerivedResourceHog: MyResourceHog{{

[System.Runtime.InteropServices.DllImport("Kernel32")][System.Runtime.InteropServices.DllImport("Kernel32")]private extern static Boolean CloseHandle(IntPtr handle);private extern static Boolean CloseHandle(IntPtr handle);

private bool private bool _disposed _disposed = false;= false;protected overried void Dispose(bool isDisposing)protected overried void Dispose(bool isDisposing){{

if (_disposed)if (_disposed)return;return;

if (isDisposing)if (isDisposing){{

//TODO: free managed resources here//TODO: free managed resources here component.Dispose();component.Dispose();

}}// TODO: free unmanaged resources here// TODO: free unmanaged resources here CloseHandle(handle);CloseHandle(handle); handle = IntPtr.Zero;handle = IntPtr.Zero;base.Dispose(isDisposing);base.Dispose(isDisposing);_disposed = true;_disposed = true;

}}}}

Page 12: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Dispose and finalize defensivelyDispose and finalize defensively

• The most important recommendation for any method The most important recommendation for any method associated with disposal or cleanupassociated with disposal or cleanup– You should be releasing resources onlyYou should be releasing resources only– Do not perform any other processing during a dispose Do not perform any other processing during a dispose

methodmethod

Page 13: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Dispose and finalize defensively(Cont.)Dispose and finalize defensively(Cont.)

• The object has been finalized, so the Garbage Collector now The object has been finalized, so the Garbage Collector now believes there is believes there is no need to call its finalizer againno need to call its finalizer again

• The The GC will not remove GC will not remove from memory any objects that are from memory any objects that are reachable only by objects in the finalizer queuereachable only by objects in the finalizer queue

• It might have already finalized them. If so, they are It might have already finalized them. If so, they are almost almost certainly no longer usablecertainly no longer usable

public class BadClasspublic class BadClass{{

private readonly ArrayList _finalizedList;private readonly ArrayList _finalizedList;private string _msg;private string _msg;public BadClass(ArrayList badList, string msg)public BadClass(ArrayList badList, string msg){{

_finalizedList = badList;_finalizedList = badList;_msg = (string)msg.Clone();_msg = (string)msg.Clone();

}}

~BadClass()~BadClass(){{

_finalizedList.Add(this);_finalizedList.Add(this);}}

}}

Page 14: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

SummarySummary

• Follow the standard Follow the standard DisposeDispose idiom. That will make life idiom. That will make life easier for you, for the users of your class, and for those easier for you, for the users of your class, and for those who create derived classes from your types.who create derived classes from your types.

Page 15: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Chapter 3. Expressing Designs with C#Chapter 3. Expressing Designs with C#

• The recommendations in this chapter will help you pick The recommendations in this chapter will help you pick the most natural expression for your designs. This will the most natural expression for your designs. This will enable you to create software that is easier to enable you to create software that is easier to maintainmaintain, , easier to easier to extendextend, and easier to , and easier to useuse..

Page 16: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

PREFER DEFINING AND IMPLEMENTING INTERFACES TO INHERITANCEPREFER DEFINING AND IMPLEMENTING INTERFACES TO INHERITANCE

Item 19:Item 19:

Page 17: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classesInterface VS Abstract classes

• InterfaceInterface– They cannot contain any concrete data members. You are They cannot contain any concrete data members. You are

declaring the contract that must be supported by all types that declaring the contract that must be supported by all types that implement an interface.implement an interface.

• Abstract classAbstract class– Any of the elements can be virtual, abstract, or nonvirtualAny of the elements can be virtual, abstract, or nonvirtual

An abstract base class can provide an implementation for any An abstract base class can provide an implementation for any concrete behavior; concrete behavior; interfaces cannot.interfaces cannot.

Page 18: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)interface InterFace1{

string Method1();int Method2();bool Method3();

}

(Abstract Class)public abstract class AbstractClass{

public abstract string Method1();public abstract int Method2();public bool Method3(){

bool a = false;return false;

}}

Page 19: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• InterfaceInterface– A class can add multiple interfacesA class can add multiple interfaces

• Abstract classAbstract class– A class only can inherit a abstract classA class only can inherit a abstract class

The two models can be mixed to reuse implementation code while supporting multiple interfaces

Page 20: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)using System;using System.Runtime.InteropServices;namespace System.Collections{ [Serializable] [ComVisible(true)] public abstract class CollectionBase : IList, ICollection, IEnumerable {

…}

}

namespace System.Collections{ [ComVisible(true)] public interface IList : ICollection, Ienumerable

{…

}}

Page 21: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• InterfaceInterface– means "behaves like.“means "behaves like.“– Have more chances to reuse code because unrelated types Have more chances to reuse code because unrelated types

can implement interfacescan implement interfaces

• Abstract classAbstract class– means "is a,“means "is a,“– Belonging to the inheritance structure, and must be the parent Belonging to the inheritance structure, and must be the parent

classclass

Page 22: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)public class Employeepublic class Employee{{

public string Namepublic string Name{{

get{return string.Format("{0}, {1}", _last, _first);}get{return string.Format("{0}, {1}", _last, _first);}}}

}}

public class Customerpublic class Customer{{

public string Namepublic string Name{{

get{return _customerName;}get{return _customerName;}}}

}}

public class Vendorpublic class Vendor{{

public string Namepublic string Name{{

Get{return _vendorName;}Get{return _vendorName;}}}

}}

Page 23: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• How to modify itHow to modify it

Page 24: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

public interface IContactInfopublic interface IContactInfo{{

string Name { get; }string Name { get; }PhoneNumber PrimaryContact { get; }PhoneNumber PrimaryContact { get; }PhoneNumber Fax { get; }PhoneNumber Fax { get; }Address PrimaryAddress { get; }Address PrimaryAddress { get; }

}}

public class Employee : IContactInfopublic class Employee : IContactInfo{{

……}}

public class Vendor : IContactInfopublic class Vendor : IContactInfo{{

……}}

public class Customerpublic class Customer : IContactInfo: IContactInfo{{

……}}

• How to modify itHow to modify it

Page 25: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• Different usageDifferent usage– interface interface 裡所有被宣告的裡所有被宣告的 propertyproperty 、、 method method 都必需要被繼都必需要被繼承且實作才能使用,你沒辦法直接承且實作才能使用,你沒辦法直接 new new 一個一個 interfaceinterface ,必需,必需 new new 出繼承了該出繼承了該 interface interface 並實作的並實作的 classclass ,再從那上面取得,再從那上面取得(Query)(Query) 該該 interfaceinterface

– abstract class abstract class 你可以不用實作,因為你可以你可以不用實作,因為你可以 new new 一個一個 abstract class abstract class                 

Page 26: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)public class IntList : System.Collections.CollectionBasepublic class IntList : System.Collections.CollectionBase{{

protected override void OnInsert(int index, object value)protected override void OnInsert(int index, object value){{

trytry{{

int newValue = System.Convert.ToInt32(value);int newValue = System.Convert.ToInt32(value);Console.WriteLine("Inserting {0} at position {1}",Console.WriteLine("Inserting {0} at position {1}",index.ToString(), value.ToString());index.ToString(), value.ToString());Console.WriteLine("List Contains {0} items",Console.WriteLine("List Contains {0} items",this.List.Count.ToString());this.List.Count.ToString());

}}catch(FormatException e)catch(FormatException e){{

throw new ArgumentException(throw new ArgumentException("Argument Type not an integer“,"value", e);"Argument Type not an integer“,"value", e);

}}}}protected override void OnInsertComplete(int index, object value)protected override void OnInsertComplete(int index, object value){{

Console.WriteLine("Inserted {0} at position {1}",Console.WriteLine("Inserted {0} at position {1}",index.ToString(), value.ToString());index.ToString(), value.ToString());Console.WriteLine("List Contains {0} items",Console.WriteLine("List Contains {0} items",this.List.Count.ToString());this.List.Count.ToString());

}}}}

Page 27: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

public class MainProgrampublic class MainProgram{{

public static void Main()public static void Main(){{

IntList l = new IntList();IntList l = new IntList();IList il = l as IList;IList il = l as IList;il.Insert(0,3);il.Insert(0,3);il.Insert(0, "This is il.Insert(0, "This is bad");bad");

}}}}

Page 28: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

public void PrintCollection( public void PrintCollection( IEnumerableIEnumerable collection ) collection ) { {

foreach( object o in collection ) foreach( object o in collection ) Console.WriteLine( "Collection contains {0}", o.ToString( ) ); Console.WriteLine( "Collection contains {0}", o.ToString( ) );

}}

public void PrintCollection( public void PrintCollection( CollectionBaseCollectionBase collection ) collection ) { {

foreach( object o in collection )foreach( object o in collection ) Console.WriteLine( "Collection contains {0}", o.ToString( ) );Console.WriteLine( "Collection contains {0}", o.ToString( ) );

} }

• ReusableReusable

Page 29: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• The second method is far less reusable.The second method is far less reusable.– It cannot be used with Arrays, ArrayLists, DataTables, It cannot be used with Arrays, ArrayLists, DataTables,

Hashtables, ImageLists, or many other collection classes.Hashtables, ImageLists, or many other collection classes.

Benefit : Coding the method using interfaces as its parameter types is far more generic and far easier to reuse.

Page 30: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• Limit the capabilities of the users of your classLimit the capabilities of the users of your class

public DataSet TheCollection public DataSet TheCollection { {

getget { {

return _dataSetCollection;return _dataSetCollection; }}

} }

For example : User wants to get dataset infomationFor example : User wants to get dataset infomation

Page 31: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• At some point, you might change from using a DataSet At some point, you might change from using a DataSet to exposing one DataTable, using a DataViewto exposing one DataTable, using a DataView

• The DataSet class provides numerous methods to The DataSet class provides numerous methods to change the data it contains. Users of your class could change the data it contains. Users of your class could delete tablesdelete tables, , modify columnsmodify columns, or , or replace every objectreplace every object in the DataSet.in the DataSet.

Page 32: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• How to limit the capabilitiesHow to limit the capabilities– return the interface you intend clients to usereturn the interface you intend clients to use

using System.ComponentModel;using System.ComponentModel;public IListSource TheCollection public IListSource TheCollection { {

getget { { return _dataSetCollection as IListSource;return _dataSetCollection as IListSource; } }

} }

Page 33: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

Interface VS Abstract classes (Cont.)Interface VS Abstract classes (Cont.)

• How to limit the capabilitiesHow to limit the capabilities– return the interface you intend clients to usereturn the interface you intend clients to use

IListSource lets clients view items through the GetList() methodIListSource lets clients view items through the GetList() method

public interface IListSourcepublic interface IListSource{{

bool ContainsListCollection { get; }bool ContainsListCollection { get; }IList GetList();IList GetList();

}}

Page 34: Effective C# 50 Specific Ways to Improve Your C# Item 18~19 2012/08/15 1

SummarySummary

• 適時使用適時使用 inheritanceinheritance 以及以及 interfaceinterface 有效增加設計的伸有效增加設計的伸縮性縮性