• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            C++ Programmer's Cookbook

            {C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

            共9頁: 1 2 3 4 5 6 7 8 9 
            實際上,有些時候兩者是結合使用的。我見過BuilderFactory。在Java的DOM模型中就使用了BuilderFactory。

            Java 環境中,解析文件是一個三步過程:

            1、創建 DocumentBuilderFactory。 DocumentBuilderFactory 對象創建 DocumentBuilder。
            2、創建 DocumentBuilder。 DocumentBuilder 執行實際的解析以創建 Document 對象。
            3、解析文件以創建 Document 對象。

            關鍵代碼如下:

            import javax.xml.parsers.DocumentBuilder;
            import javax.xml.parsers.DocumentBuilderFactory;
            import java.io.File;
            import org.w3c.dom.Document;

            public class OrderProcessor {
            public static void main (String args[]) {
            File docFile = new File("orders.xml");
            Document doc = null;
            try {

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            doc = db.parse(docFile);

            } catch (Exception e) {
            System.out.print("Problem parsing the file: "+e.getMessage());
            }
            }
            }

            很有創意的!
            提供一個創建一組相關或無關對象的接口,而沒有指定具體的類.
            七、 在什么情況下使用建造者模式
            以下情況應當使用建造者模式:

            1、 需要生成的產品對象有復雜的內部結構。
            2、 需要生成的產品對象的屬性相互依賴,建造者模式可以強迫生成順序。
            3、 在對象創建過程中會使用到系統中的一些其它對象,這些對象在產品對象的創建過程中不易得到。

            使用建造者模式主要有以下效果:

            1、 建造模式的使用使得產品的內部表象可以獨立的變化。使用建造者模式可以使客戶端不必知道產品內部組成的細節。
            2、 每一個Builder都相對獨立,而與其它的Builder無關。
            3、 模式所建造的最終產品更易于控制。
            definition
            Separate the construction of a complex object from its representation so that the same construction process can create different representations.

            definition
            Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
            definition
            Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

            上面代碼開發過程中可以如此安排。1)由系統架構師設計好抽象產品和抽象工廠。2.1)多組并行開發具體產品和具體工廠。2.2)與此同時另外一組使用依賴注入技術開發主程序。在1的工作完成后2.1與2.2是可以并行的。按上面方案很可能產生3個Assembly。最后通過配置文件完成組裝。


            非常正確。 事實上,這個設計模式用在組件開發中是非常有用的,而且可以通過reflect并把具體的類名已經產生實例的參數傳入工廠來產生實例。 java和csharp都是通用的,在這個點上。
            想起這個題目,不得不由衷地佩服MS的細心度,我們想到了沒有想到的他都給我們想到了。讓我們盡可能的解放coding之苦。

              程序員,不得不在thinking 和coding之間進行痛苦的折磨,然而coding占去了我們的大量寶貴的時間。我們重復重復又重復著那些一輩子都不會忘掉的代碼,重復重復又重復的重復著那些被我們敲爛的代碼。

              發現這個還是一次偶然的機會,我自定義了一個Prop函數,結果在按下去的時候不小心碰到了Tab鍵結果出現了以下的代碼:

            private int myVar; public int MyProperty { get { return myVar;} set { myVar = value;} }

              熟悉的朋友應當已經發現這是一個標準的設置屬性的字段。為什么我輸入了Prop會自出來這些呢?帶著疑問找到了google大法,原來已經早就有人發現了:這是2005的一個特色之一:代碼段。

              代碼段是提供了將現成的代碼段插入到項目中的方法。它可以方便的把我們常用的一些代碼用"快捷鍵"的方式讓我們迅速的輸入到IDE中。這里我不知道怎么形容,暫且用快捷鍵來代替吧。

              具體的輸入方法:例如:我們輸入Prop然后回車,接著按著Tab幾秒鐘,IDE就會自動給我們添加上去代碼段所定義的代碼。而且支持可修改部分,我們可以方便的接著使用Tab來穿梭于各個可修改部分。

              有人會有疑問,這些代碼段怎么來的呢?IDE已經給我們自帶了一部分,我們也可以根據自己的偏好來進行自行創建。

              打開VS2005的 \VC#\Snippets\2052\Visual C# 目錄,我們會發現有一些以.snippet結尾的文件,這些就是系統給我們默認定義好的代碼段。我們用文本文檔打開,不難發現其實就是標準的XML文件。現對照if代碼段進行一些講解(對應文件為if.snippet)。看起代碼:

            <?xml version="1.0" encoding="utf-8"?>
            <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"
            <CodeSnippet Format="1.0.0">//以上是代碼段的一個標準格式 <Header>
            <Title>if</Title>
            //代碼段的說明部分,指定代碼段的標題。可以顯示在代碼段插入和代碼段管理器的代碼段說明部分。
            <Shortcut>if</Shortcut>
            //代碼段的快捷方式。就是輸入后按著Tab自動產生代碼
            <Description>if 語句的代碼段</Description>
            //指定代碼段內容的說明信息,它可以給我們在使用代碼段的時候提供工具提示,并且可以在代碼段管理器中提供說明
            <Author>Microsoft Corporation</Author>
            //版權信息
            <SnippetTypes>
            <SnippetType>Expansion</SnippetType>
            <SnippetType>SurroundsWith</SnippetType>
            </SnippetTypes>
            //以上部分指定vs如何插入代碼段。SurroundsWith允許代碼段放置在選定代碼快的周圍,而Expansion的值允許將代碼段插入光標所在的位置。
            </Header>
            <Snippet>
            //此處開始指定代碼的引用、導入、聲明代碼。主體部分
            <Declarations>
            //指定當前作為代碼段組成部分的文本和對象,對代碼段可以編輯部分。
            <Literal>//<Literal> 段定義可編輯的代碼段的文本。他用與標識對代碼快的替換。我們可以使用Tab來進行切換修改。可以按照函數的概念來理解。這里就是我們傳遞參數值
            <ID>expression</ID>
            //替代標識
            <ToolTip>要計算的表達式</ToolTip>//提示文本
            <Default>true</Default>//默認值
            </Literal>//若需多個,則可重復<Literal>代碼段。
            </Declarations>
            <Code Language="csharp">
            <![CDATA[if ($expression$) { $selected$ $end$ }]]>
            </Code>//看code部分代碼段。這里就是我們的核心部分。其中Language可以指定我們在用什么語言開發的時候使用此類代碼段。
            <! [CDATA[部分就是我們標準的C#語法了。if ($expression$)看清楚if()括號部分的代碼,這里就是使用到我們在<Literal>部分定義的替代標識了。以$開始和結束,由于我們在定義的時候制定了默認值為true,所以在使用代碼段的時候等價于if(true)。而括弧部分就是主體$selected$表示此處可以被選擇,$ end$表示代碼段結束。
            </Snippet>
            </CodeSnippet>
            </CodeSnippets>

              看,通過上邊的分析,代碼段是不是很簡單。我們在對照一下核心部分代碼:

              代碼段部分代碼:

            if ($expression$) { $selected$ $end$ }

              正常語句代碼:

            if (條件) { 代碼 }

              了解了這些知識,那么我們該如何創建自己的代碼段呢。最簡單的方法就是用記事本,當然要十分熟悉這些語句。另外IDE也給我們提供了創建文件的方法。

              [文件]→[新建文件] →[XML文件],重新命名為:mytest. Snippet,一定要以snippet結尾,否則以后沒有辦法使用此代碼段。參照上邊的講解,相信大家不難以葫蘆畫瓢來創建自己的代碼段。

              建立好了,我們該怎么使用呢?[工具]→[代碼段管理器] →[導入]即可。代碼段管理器可以方便的瀏覽現有的代碼段。我們也可以把自己做好的代碼段共享給別人,只要別人通過代碼段管理器就可以導入制訂好的代碼段。很方便。

              另外我們還可以創建VSI安裝文件來進行安裝使用。相信大部分人對VSI安裝文件都有所了解了,熟悉的初學者開發工具包就是利用VSI文件發布的。具體的方法請看我的后續文章。用好2005之創建安裝程序 (.vsi)

              通過以上介紹,相信大家會對代碼段有一個很清楚的了解。我們可以通過"代碼段管理器"方便的瀏覽已經存在的代碼段以及它們的含義。

              代碼段是預編寫的代碼片段,您可以隨時使用 Visual Studio 2005 將這些代碼片段插入到您的應用程序中。這些代碼段減少了鍵入重復代碼或搜索示例所用的時間,從而提高了工作效率。

              我們的口號是:只做對的,不做慢的。歡迎大家進行交流。

            單例模式的特點:

            單例類只能有一個實例。
            單例類必須自己創建自己的唯一實例。
            單例類必須給所有其它對象提供這一實例。
            單例模式應用:

            每臺計算機可以有若干個打印機,但只能有一個Printer Spooler,避免兩個打印作業同時輸出到打印機。
            一個具有自動編號主鍵的表可以有多個用戶同時使用,但數據庫中只能有一個地方分配下一個主鍵編號。否則會出現主鍵重復。
            在什么情形下使用單例模式:
            使用Singleton模式有一個必要條件:在一個系統要求一個類只有一個實例時才應當使用單例模式。反過來,如果一個類可以有幾個實例共存,就不要使用單例模式。

            注意:

            不要使用單例模式存取全局變量。這違背了單例模式的用意,最好放到對應類的靜態成員中。

            不要將數據庫連接做成單例,因為一個系統可能會與數據庫有多個連接,并且在有連接池的情況下,應當盡可能及時釋放連接。Singleton模式由于使用靜態成員存儲類實例,所以可能會造成資源無法及時釋放,帶來問題。
            sealed class Singleton
            {
            private Singleton();
            public static readonly Singleton Instance=new Singleton();
            }
            這使得代碼減少了許多,同時也解決了線程問題帶來的性能上損失。那么它又是怎樣工作的呢?

            注意到,Singleton類被聲明為sealed,以此保證它自己不會被繼承,其次沒有了Instance的方法,將原來_instance成員變量變成public readonly,并在聲明時被初始化。通過這些改變,我們確實得到了Singleton的模式,原因是在JIT的處理過程中,如果類中的static屬性被任何方法使用時,.NET Framework將對這個屬性進行初始化,于是在初始化Instance屬性的同時Singleton類實例得以創建和裝載。而私有的構造函數和readonly(只讀)保證了Singleton不會被再次實例化,這正是Singleton設計模式的意圖。
            非托管

            在.net 編程環境中,系統的資源分為托管資源和非托管資源。
            對于托管的資源的回收工作,是不需要人工干預回收的,而且你也無法干預他們的回收,所能夠做的只是了解.net CLR如何做這些操作。也就是說對于您的應用程序創建的大多數對象,可以依靠 .NET Framework 的垃圾回收器隱式地執行所有必要的內存管理任務。

            對于非托管資源,您在應用程序中使用完這些非托管資源之后,必須顯示的釋放他們,例如System.IO.StreamReader的一個文件對象,必須顯示的調用對象的Close()方法關閉它,否則會占用系統的內存和資源,而且可能會出現意想不到的錯誤。

            我想說到這里,一定要清楚什么是托管資源,什么是非托管資源了?

            最常見的一類非托管資源就是包裝操作系統資源的對象,例如文件,窗口或網絡連接,對于這類資源雖然垃圾回收器可以跟蹤封裝非托管資源的對象的生存期,但它不了解具體如何清理這些資源。還好.net Framework提供了Finalize()方法,它允許在垃圾回收器回收該類資源時,適當的清理非托管資源。如果在MSDN Library 中搜索Finalize將會發現很多類似的主題,這里列舉幾種常見的非托管資源:ApplicationContext,Brush,Component,ComponentDesigner,Container,Context,Cursor,FileStream,Font,Icon,Image,Matrix,Object,OdbcDataReader,OleDBDataReader
            ,Pen,Regex,Socket,StreamWriter,Timer,Tooltip 等等資源。可能在使用的時候很多都沒有注意到!

            關于托管資源,就不用說了撒,像簡單的int,string,float,DateTime等等,.net中超過80%的資源都是托管資源。

            非托管資源如何釋放,.NET Framework 提供 Object.Finalize 方法,它允許對象在垃圾回收器回收該對象使用的內存時適當清理其非托管資源。默認情況下,Finalize 方法不執行任何操作。默認情況下,Finalize 方法不執行任何操作。如果您要讓垃圾回收器在回收對象的內存之前對對象執行清理操作,您必須在類中重寫 Finalize 方法。然而大家都可以發現在實際的編程中根本無法override方法Finalize(),在C#中,可以通過析構函數自動生成 Finalize 方法和對基類的 Finalize 方法的調用。

            例如:

            ~MyClass()

            {

            // Perform some cleanup operations here.

            }

            該代碼隱式翻譯為下面的代碼。

            protected override void Finalize()

            {

            try

            {

            // Perform some cleanup operations here.

            }

            finally

            {

            base.Finalize();

            }

            }

            但是,在編程中,并不建議進行override方法Finalize(),因為,實現 Finalize 方法或析構函數對性能可能會有負面影響。一個簡單的理由如下:用 Finalize 方法回收對象使用的內存需要至少兩次垃圾回收,當垃圾回收器回收時,它只回收沒有終結器(Finalize方法)的不可訪問的內存,這時他不能回收具有終結器(Finalize方法)的不可以訪問的內存。它改為將這些對象的項從終止隊列中移除并將他們放置在標記為“準備終止”的對象列表中,該列表中的項指向托管堆中準備被調用其終止代碼的對象,下次垃圾回收器進行回收時,就回收并釋放了這些內存。
            re: c#的反射 夢在天涯 2006-04-19 12:16
            關于反射

            提綱:
            1、什么是反射
            2、命名空間與裝配件的關系
            3、運行期得到類型信息有什么用
            4、如何使用反射獲取類型
            5、如何根據類型來動態創建對象
            6、如何獲取方法以及動態調用方法
            7、動態創建委托


            1、什么是反射
            Reflection,中文翻譯為反射。
            這是.Net中獲取運行時類型信息的方式,.Net的應用程序由幾個部分:‘程序集(Assembly)’、‘模塊(Module)’、‘類型(class)’組成,而反射提供一種編程的方式,讓程序員可以在程序運行期獲得這幾個組成部分的相關信息,例如:

            Assembly類可以獲得正在運行的裝配件信息,也可以動態的加載裝配件,以及在裝配件中查找類型信息,并創建該類型的實例。
            Type類可以獲得對象的類型信息,此信息包含對象的所有要素:方法、構造器、屬性等等,通過Type類可以得到這些要素的信息,并且調用之。
            MethodInfo包含方法的信息,通過這個類可以得到方法的名稱、參數、返回值等,并且可以調用之。
            諸如此類,還有FieldInfo、EventInfo等等,這些類都包含在System.Reflection命名空間下。

            2、命名空間與裝配件的關系
            很多人對這個概念可能還是很不清晰,對于合格的.Net程序員,有必要對這點進行澄清。
            命名空間類似與Java的包,但又不完全等同,因為Java的包必須按照目錄結構來放置,命名空間則不需要。

            裝配件是.Net應用程序執行的最小單位,編譯出來的.dll、.exe都是裝配件。

            裝配件和命名空間的關系不是一一對應,也不互相包含,一個裝配件里面可以有多個命名空間,一個命名空間也可以在多個裝配件中存在,這樣說可能有點模糊,舉個例子:
            裝配件A:
            namespace N1
            {
            public class AC1 {…}
            public class AC2 {…}
            }
            namespace N2
            {
            public class AC3 {…}
            public class AC4{…}
            }
            裝配件B:
            namespace N1
            {
            public class BC1 {…}
            public class BC2 {…}
            }
            namespace N2
            {
            public class BC3 {…}
            public class BC4{…}
            }

            這兩個裝配件中都有N1和N2兩個命名空間,而且各聲明了兩個類,這樣是完全可以的,然后我們在一個應用程序中引用裝配件A,那么在這個應用程序中,我們能看到N1下面的類為AC1和AC2,N2下面的類為AC3和AC4。
            接著我們去掉對A的引用,加上對B的引用,那么我們在這個應用程序下能看到的N1下面的類變成了BC1和BC2,N2下面也一樣。
            如果我們同時引用這兩個裝配件,那么N1下面我們就能看到四個類:AC1、AC2、BC1和BC2。

            到這里,我們可以清楚一個概念了,命名空間只是說明一個類型是那個族的,比如有人是漢族、有人是回族;而裝配件表明一個類型住在哪里,比如有人住在北京、有人住在上海;那么北京有漢族人,也有回族人,上海有漢族人,也有回族人,這是不矛盾的。

            上面我們說了,裝配件是一個類型居住的地方,那么在一個程序中要使用一個類,就必須告訴編譯器這個類住在哪兒,編譯器才能找到它,也就是說必須引用該裝配件。
            那么如果在編寫程序的時候,也許不確定這個類在哪里,僅僅只是知道它的名稱,就不能使用了嗎?答案是可以,這就是反射了,就是在程序運行的時候提供該類型的地址,而去找到它。
            有興趣的話,接著往下看吧。

            3、運行期得到類型信息有什么用
            有人也許疑問,既然在開發時就能夠寫好代碼,干嘛還放到運行期去做,不光繁瑣,而且效率也受影響。
            這就是個見仁見智的問題了,就跟早綁定和晚綁定一樣,應用到不同的場合。有的人反對晚綁定,理由是損耗效率,但是很多人在享受虛函數帶來的好處的時侯還沒有意識到他已經用上了晚綁定。這個問題說開去,不是三言兩語能講清楚的,所以就點到為止了。
            我的看法是,晚綁定能夠帶來很多設計上的便利,合適的使用能夠大大提高程序的復用性和靈活性,但是任何東西都有兩面性,使用的時侯,需要再三衡量。

            接著說,運行期得到類型信息到底有什么用呢?
            還是舉個例子來說明,很多軟件開發者喜歡在自己的軟件中留下一些接口,其他人可以編寫一些插件來擴充軟件的功能,比如我有一個媒體播放器,我希望以后可以很方便的擴展識別的格式,那么我聲明一個接口:
            public interface IMediaFormat
            {
            string Extension {get;}
            Decoder GetDecoder();
            }
            這個接口中包含一個Extension屬性,這個屬性返回支持的擴展名,另一個方法返回一個解碼器的對象(這里我假設了一個Decoder的類,這個類提供把文件流解碼的功能,擴展插件可以派生之),通過解碼器對象我就可以解釋文件流。
            那么我規定所有的解碼插件都必須派生一個解碼器,并且實現這個接口,在GetDecoder方法中返回解碼器對象,并且將其類型的名稱配置到我的配置文件里面。
            這樣的話,我就不需要在開發播放器的時侯知道將來擴展的格式的類型,只需要從配置文件中獲取現在所有解碼器的類型名稱,而動態的創建媒體格式的對象,將其轉換為IMediaFormat接口來使用。

            這就是一個反射的典型應用。

            4、如何使用反射獲取類型
            首先我們來看如何獲得類型信息。
            獲得類型信息有兩種方法,一種是得到實例對象
            這個時侯我僅僅是得到這個實例對象,得到的方式也許是一個object的引用,也許是一個接口的引用,但是我并不知道它的確切類型,我需要了解,那么就可以通過調用System.Object上聲明的方法GetType來獲取實例對象的類型對象,比如在某個方法內,我需要判斷傳遞進來的參數是否實現了某個接口,如果實現了,則調用該接口的一個方法:

            public void Process( object processObj )
            {
            Type t = processsObj.GetType();
            if( t.GetInterface(“ITest”) !=null )

            }

            另外一種獲取類型的方法是通過Type.GetType以及Assembly.GetType方法,如:
            Type t = Type.GetType(“System.String”);
            需要注意的是,前面我們講到了命名空間和裝配件的關系,要查找一個類,必須指定它所在的裝配件,或者在已經獲得的Assembly實例上面調用GetType。
            本裝配件中類型可以只寫類型名稱,另一個例外是mscorlib.dll,這個裝配件中聲明的類型也可以省略裝配件名稱(.Net裝配件編譯的時候,默認都引用了mscorlib.dll,除非在編譯的時候明確指定不引用它),比如:
            System.String是在mscorlib.dll中聲明的,上面的Type t = Type.GetType(“System.String”)是正確的
            System.Data.DataTable是在System.Data.dll中聲明的,那么:
            Type.GetType(“System.Data.DataTable”)就只能得到空引用。
            必須:
            Type t = Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
            這樣才可以,大家可以看下面這個帖子:
            http://expert.csdn.net/Expert/topic/2210/2210762.xml?temp=.1919977
            qqchen的回答很精彩


            5、如何根據類型來動態創建對象
            System.Activator提供了方法來根據類型動態創建對象,比如創建一個DataTable:

            Type t = Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

            DataTable table = (DataTable)Activator.CreateInstance(t);

            例二:根據有參數的構造器創建對象
            namespace TestSpace {
            public class TestClass
            {
            private string _value;
            public TestClass(string value) {
            _value=value;
            }
            }
            }

            Type t = Type.GetType(“TestSpace.TestClass”);
            Object[] constructParms = new object[] {“hello”}; //構造器參數
            TestClass obj = (TestClass)Activator.CreateInstance(t,constructParms);

            把參數按照順序放入一個Object數組中即可

            6、如何獲取方法以及動態調用方法
            namespace TestSpace
            {
            public class TestClass {
            private string _value;
            public TestClass() {
            }
            public TestClass(string value) {
            _value = value;
            }

            public string GetValue( string prefix ) {
            if( _value==null )
            return "NULL";
            else
            return prefix+" : "+_value;
            }

            public string Value {
            set {
            _value=value;
            }
            get {
            if( _value==null )
            return "NULL";
            else
            return _value;
            }
            }
            }
            }

            上面是一個簡單的類,包含一個有參數的構造器,一個GetValue的方法,一個Value屬性,我們可以通過方法的名稱來得到方法并且調用之,如:

            //獲取類型信息
            Type t = Type.GetType("TestSpace.TestClass");
            //構造器的參數
            object[] constuctParms = new object[]{"timmy"};
            //根據類型創建對象
            object dObj = Activator.CreateInstance(t,constuctParms);
            //獲取方法的信息
            MethodInfo method = t.GetMethod("GetValue");
            //調用方法的一些標志位,這里的含義是Public并且是實例方法,這也是默認的值
            BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
            //GetValue方法的參數
            object[] parameters = new object[]{"Hello"};
            //調用方法,用一個object接收返回值
            object returnValue = method.Invoke(dObj,flag,Type.DefaultBinder,parameters,null);

            屬性與方法的調用大同小異,大家也可以參考MSDN

            7、動態創建委托
            委托是C#中實現事件的基礎,有時候不可避免的要動態的創建委托,實際上委托也是一種類型:System.Delegate,所有的委托都是從這個類派生的
            System.Delegate提供了一些靜態方法來動態創建一個委托,比如一個委托:

            namespace TestSpace {
            delegate string TestDelegate(string value);
            public class TestClass {
            public TestClass() {
            }
            public void GetValue(string value) {
            return value;
            }
            }
            }

            使用示例:
            TestClass obj = new TestClass();

            //獲取類型,實際上這里也可以直接用typeof來獲取類型
            Type t = Type.GetType(“TestSpace.TestClass”);
            //創建代理,傳入類型、創建代理的對象以及方法名稱
            TestDelegate method = (TestDelegate)Delegate.CreateDelegate(t,obj,”GetValue”);

            String returnValue = method(“hello”);

            上面第一個的exe必須放在第二個的bin\下


            secondDomain.ExecuteAssembly("AssemblyA.exe");調用其main()方法.
            re: .NET Framework Resource Management 夢在天涯 2006-04-14 16:22
            Finalize 和Dispose(bool disposing)和 Dispose() 的相同點:

            這三者都是為了釋放非托管資源服務的.

            Finalize 和 Dispose() 和Dispose(bool disposing)的不同點:

            Finalize是CRL提供的一個機制, 它保證如果一個類實現了Finalize方法,那么當該類對象被垃圾回收時,垃圾回收器會調用Finalize方法.而該類的開發者就必須在Finalize方法中處理 非托管資源的釋放. 但是什么時候會調用Finalize由垃圾回收器決定,該類對象的使用者(客戶)無法控制.從而無法及時釋放掉寶貴的非托管資源.由于非托管資源是比較寶貴了,所以這樣會降低性能.
            Dispose(bool disposing)不是CRL提供的一個機制, 而僅僅是一個設計模式(作為一個IDisposable接口的方法),它的目的是讓供類對象的使用者(客戶)在使用完類對象后,可以及時手動調用非托管資源的釋放,無需等到該類對象被垃圾回收那個時間點.這樣類的開發者就只需把原先寫在Finalize的釋放非托管資源的代碼,移植到Dispose(bool disposing)中. 而在Finalize中只要簡單的調用 "Dispose(false)"(為什么傳遞false后面解釋)就可以了.
            這個時候我們可能比較疑惑,為什么還需要一個Dispose()方法?難道只有一個Dispose(bool disposing)或者只有一個Dispose()不可以嗎?
            答案是:
            只有一個Dispose()不可以. 為什么呢?因為如果只有一個Dispose()而沒有Dispose(bool disposing)方法.那么在處理實現非托管資源釋放的代碼中無法判斷該方法是客戶調用的還是垃圾回收器通過Finalize調用的.無法實現 判斷如果是客戶手動調用,那么就不希望垃圾回收器再調用Finalize()(調用GC.SupperFinalize方法).另一個可能的原因(:我們知道如果是垃圾回收器通過Finalize調用的,那么在釋放代碼中我們可能還會引用其他一些托管對象,而此時這些托管對象可能已經被垃圾回收了, 這樣會導致無法預知的執行結果(千萬不要在Finalize中引用其他的托管對象).



            所以確實需要一個bool disposing參數, 但是如果只有一個Dispose(bool disposing),那么對于客戶來說,就有一個很滑稽要求,Dispose(false)已經被Finalize使用了,必須要求客戶以Dispose(true)方式調用,但是誰又能保證客戶不會以Dispose(false)方式調用呢?所以這里采用了一中設計模式:重載 把Dispose(bool disposing)實現為 protected, 而Dispose()實現為Public,那么這樣就保證了客戶只能調用Dispose()(內部調用Dispose(true)//說明是客戶的直接調用),客戶無法調用Dispose(bool disposing).


            范例如下:

            public class BaseResource: IDisposable
            {
            //析構函數自動生成 Finalize 方法和對基類的 Finalize 方法的調用.默認情況下,一個類是沒有析構函數的,也就是說,對象被垃圾回收時不會被調用Finalize方法
            ~BaseResource()
            {
            // 為了保持代碼的可讀性性和可維護性,千萬不要在這里寫釋放非托管資源的代碼
            // 必須以Dispose(false)方式調用,以false告訴Dispose(bool disposing)函數是從垃圾回收器在調用Finalize時調用的
            Dispose(false);
            }


            // 無法被客戶直接調用
            // 如果 disposing 是 true, 那么這個方法是被客戶直接調用的,那么托管的,和非托管的資源都可以釋放
            // 如果 disposing 是 false, 那么函數是從垃圾回收器在調用Finalize時調用的,此時不應當引用其他托管對象所以,只能釋放非托管資源
            protected virtual void Dispose(bool disposing)
            {

            // 那么這個方法是被客戶直接調用的,那么托管的,和非托管的資源都可以釋放
            if(disposing)
            {
            // 釋放 托管資源
            OtherManagedObject.Dispose();
            }


            //釋放非托管資源
            DoUnManagedObjectDispose();


            // 那么這個方法是被客戶直接調用的,告訴垃圾回收器從Finalization隊列中清除自己,從而阻止垃圾回收器調用Finalize方法.
            if(disposing)
            GC.SuppressFinalize(this);

            }

            //可以被客戶直接調用
            public void Dispose()
            {
            //必須以Dispose(true)方式調用,以true告訴Dispose(bool disposing)函數是被客戶直接調用的
            Dispose(true);
            }
            }

            上面的范例達到的目的:

            1/ 如果客戶沒有調用Dispose(),未能及時釋放托管和非托管資源,那么在垃圾回收時,還有機會執行Finalize(),釋放非托管資源,但是造成了非托管資源的未及時釋放的空閑浪費

            2/ 如果客戶調用了Dispose(),就能及時釋放了托管和非托管資源,那么該對象被垃圾回收時,不回執行Finalize(),提高了非托管資源的使用效率并提升了系統性能


            可以參考SqlConnection對象的New, Open, Close(內部調用Dispose())的使用經歷可以加深對他們的理解.謝謝!
            re: object 序列化 夢在天涯 2006-04-14 16:17
            NET的對象序列化真是好東西,以后要多多利用。

              在使用.NET的序列化時,碰到過一些問題,還好,有豐富的MSDN可查,沒有什么過不去的檻。在這里,把使用.NET序列化的經驗小結一下。
              1. 基本確認XmlSerializer使用UTF8對序列化的XML文檔編碼。
              2. XmlSerializer只序列化聲明為public的字段,屬性,或帶返回值的方法。
              3. 如果要序列化屬性,那么該屬性必須是可讀寫的,即必須包含get和set,而不能是readonly或writeonly。
              4. XmlAttribute,XmlAnyAttribute不能與XmlElement,XmlText,XmlAnyElement,XmlArray,XmlArrayItem一起使用。
              5. XmlRoot只能用于一個類,XmlType可用于所有類。
              6. 不同的類的XmlType不能相同,除非使用NameSpaces區分。

            相關鏈接:
              ● 在.NET中實現對象序列化
              ● 對象序列化:使用System.Xml.Serialization命名空間
              ● 對象序列化:使用XmlSerializer走完最后一步
            re: object 序列化 夢在天涯 2006-04-14 12:09
            class must have

            public members or getandset of properities,

            then it can be serialized.
            re: C#中重用c/c++舊模塊 夢在天涯 2006-04-03 08:39
            @sunmast
            ^_^,不好意思啊 !可以留下你的連接嗎?
            re: c#目錄瀏覽 夢在天涯 2006-03-10 08:47
            c++ 的目錄瀏覽 ,使用windows API ,c++的分類里file and directory里有!
            re: c#目錄瀏覽 夢在天涯 2006-03-10 08:45
            那位知道怎么把控制臺程序轉到windowsform程序,只需要引用forms dll嗎?
            re: CString詳細講解 夢在天涯 2006-03-03 17:31
            為什么不可以啊,數組是沒有什么要求的把!
            在mfc里已經有自己定義好的啊!
            加一條線到model中

            Line pline = new Line(new Point3d(10,10,0),new Point3d(100,100,0));
            Database db= Application.DocumentManager.MdiActiveDocument.Database;
            //DBTransMan tm=db.TransactionManager;
            using(Transaction trans=db.TransactionManager.StartTransaction())
            {
            BlockTable bt=(BlockTable)db.TransactionManager.GetObject(db.BlockTableId,OpenMode. ForRead,false);
            BlockTableRecord btr=
            (BlockTableRecord)db.TransactionManager.GetObject(bt[BlockTableRecord.ModelSpace],
            OpenMode.ForWrite,false);
            btr.AppendEntity(pline);
            db.TransactionManager.AddNewlyCreatedDBObject(pline,true);
            trans.Commit();
            }
            re: arx & c++ 常用函數代碼 夢在天涯 2006-02-17 09:03
            Finding the Active Viewports in Model Space

            // Set some viewport information.
            AcDbViewportTable* pViewportTable;
            if (db.getViewportTable(pViewportTable, AcDb::kForRead)
            == Acad::eOk)
            {
            // Find the first viewport and open it for write.
            AcDbViewportTableRecord *pRecord;
            if (pViewportTable->getAt(
            "*ACTIVE", pRecord,
            AcDb::kForWrite) == Acad::eOk)
            {
            pRecord->setCenterPoint(AcGePoint2d(0.5, 0.5));
            pRecord->setHeight(1.0);
            pRecord->setWidth(1.0);
            pRecord->close();
            }
            pViewportTable->close();
            }
            re: CString詳細講解 夢在天涯 2006-02-10 15:25
            CString 的長度有沒有限制啊?是不是不能太長啊
            ???
            re: uml 基本概念 夢在天涯 2006-02-10 11:38
            用例模型和用例圖
            類圖和對象圖
            交互圖:順序圖和合作圖
            行為圖:狀態圖和活動圖
            實現圖:構件圖和配置圖
            re: c++ file and directory 夢在天涯 2006-02-09 16:49
            -------------------------------------------------------------------
            、獲得當前應用程序路徑
            #include < windows.h >
            #include < string.h >

            HINSTANCE hInst;
            char szBuf[256];
            char *p;

            //拿到全部路徑
            GetModuleFileName(hInst,szBuf,sizeof(szBuf));

            //分離路徑和文件名。
            p = szBuf;
            while(strchr(p,'\\')) {
            p = strchr(p,'\\');
            p++;
            }
            *p = '\0';
            //路徑在szBuf理了。
            re: C++中DOM寫XML 夢在天涯 2006-02-08 20:50
            原程序對有些機器不能通過的原因:


            應該把IXMLDOMDocument3Ptr中的3改為2!

            還有雖然用了namespace MSXML2,但是還必須在每個用到的定義如IXMLDOMElementPtr 前加上MSXML2::,這樣便可以通過!



            有知道為什么的嗎?


            re: C++中DOM寫XML 夢在天涯 2006-01-23 17:01
            是啊,要看你裝的MSXML的版本啊,有的要用3,有的不用啊!
            好像是這樣啊!
            re: 簡單好用的讀寫ini文件的類 夢在天涯 2006-01-18 10:11
            我覺的也是的,但是我們的頭讓先用ini,不知道使用起來那個效率更好些啊!
            re: 簡單好用的讀寫ini文件的類 夢在天涯 2006-01-17 14:51
            恩,高!學習中!

            可不可以在每個section后加一行空行那?

            請高手指點!
            re: c++ file and directory 夢在天涯 2006-01-12 16:39
            也可以用searchpath()來找,是嗎?可惜就是沒有找到例子!
            那位有的話,貢獻一下啊,謝謝!
            微軟的2005對目前c++標注好多的都不支持!

            增加了安全機制!
            re: C++中DOM寫XML 夢在天涯 2005-12-29 16:09
            恩,太感謝拉!牛!

            為什么說有些節點不能是數字那?是所有的嗎?好像有的行啊!^_^!


            哦,想起來拉,節點的命名首字母不能是()。。。。。。。^_^!~

            但是element里的text,我們不用管它是中文還是英文,也不用管是身編碼嗎?只要我們在xml頭指定encoding=“”就可以了嗎?為什么有的時候加了encoding =“gb2312”,顯示仍然是亂麻那~???


            謝謝!
            re: C++中DOM寫XML 夢在天涯 2005-12-29 13:44
            為什么createelement(item)時,item不能是由數字轉換為的字符串!而且是有時可以有時不可,都發現好多次拉,難道時bug,還是英文版的緣故啊?
            re: 強烈不滿google mail 夢在天涯 2005-12-26 08:51
            我的也是不行啊,根本就打不開登陸頁面啊!真郁悶啊
            那啊!

            妳是說stl中的算法的速度慢嗎?

            但是對于一般的問題我覺的都可以滿足的吧!

            ^_^!~~·
            re: C++之AOP 夢在天涯 2005-12-15 16:53
            不明白啊,太高級拉!還的多多的學習啊
            re: 我是如何"crack"掉winrar的 夢在天涯 2005-12-15 16:48
            niu 牛啊!
            能不能說的詳細點啊,最好是有詳細的步驟啊!
            大家回很感謝你的啊!
            恩!是的啊,。net2003中有3個參數的版本啊,也可以自己定義一個比較函數,
            sort(XXX.begin(),XXX.end(), less_second);//less_second自定義函數
            unique(XXX.begin(),XXX.end(),equal_double);//equal_double自定義函數

            但是再.net2005中沒有啊,編譯不通過啊,好像有 4個參數的版本啊!不知道怎么用啊


            屏幕得到的點的坐標,取4位小數,比較!我的方法×10000,然后long啊!大家有沒有更好的方法啊 !



            謝謝 啊!
            re: OGRE粒子系統之在烈火中永生 夢在天涯 2005-12-14 18:44
            orge是作游戲的語言?跟什么語言類似啊?可不可以簡單描述一下啊,或與c++比較一下啊 !
            re: vc6函數調用淺析 夢在天涯 2005-12-14 18:41
            怎么反匯編啊?老大指點一下啊 !
            re: 有用但不常見的c++函數 夢在天涯 2005-11-07 08:49
            不需要的啊,你可以在你的windows上可以運行的啊 !
            樓上的樓上說的拷貝構造函數是不是每個節點都的重新new,啊?
            共9頁: 1 2 3 4 5 6 7 8 9 

            公告

            EMail:itech001#126.com

            導航

            統計

            • 隨筆 - 461
            • 文章 - 4
            • 評論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1804303
            • 排名 - 5

            最新評論

            閱讀排行榜

            人妻精品久久无码区| 国产精品成人久久久| 7国产欧美日韩综合天堂中文久久久久| 久久亚洲国产成人精品性色| 国产成人久久精品一区二区三区| 国产一级做a爰片久久毛片| 久久久久99精品成人片三人毛片 | 精品久久久久中文字幕日本| 日韩精品国产自在久久现线拍 | 久久久久亚洲精品日久生情| 久久精品国产亚洲av高清漫画| 亚洲国产精品久久久久久| 伊人久久大香线蕉AV色婷婷色| 99热成人精品免费久久| 久久久久99精品成人片直播| 超级碰碰碰碰97久久久久| 久久久久免费精品国产| 久久综合狠狠综合久久| 无码人妻久久一区二区三区蜜桃| 国产精品免费看久久久香蕉| 久久久久99精品成人片直播| 久久久这里有精品| 久久精品国产福利国产琪琪| 久久久无码人妻精品无码| 久久精品国产男包| 色诱久久av| 久久精品极品盛宴观看| 性高朝久久久久久久久久| 久久高清一级毛片| 91精品国产综合久久香蕉| 国产精品青草久久久久婷婷| 色偷偷偷久久伊人大杳蕉| 久久久亚洲AV波多野结衣| 无码国内精品久久综合88| 欧美久久久久久| 久久久国产精华液| 色妞色综合久久夜夜| 久久久久AV综合网成人 | 国产A级毛片久久久精品毛片| 91精品国产综合久久精品| 久久九九全国免费|