發表文章

目前顯示的是 1月, 2010的文章

.Net Generic中的default(T)跟new T()

先來看一段.Net C#中的generic程式碼。 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestVS2008 { public class TestGeneric { public static T CreateGeneric<T>() where T : new () { return new T(); } public static T CreateGeneric_2<T>() { return default (T); } public static void Test() { int i = CreateGeneric< int >(); TestGeneric t = CreateGeneric<TestGeneric>(); TestGeneric t2 = CreateGeneric_2<TestGeneric>(); } } } 上面這段程式碼中,主要想要測試的是在使用泛型之下, new  T()跟default(T)的差別。 首先看到CreateGeneric_2<T>()這個函式,它針對所需的型別T並沒有加入任何的限制條件。任何型別都可以帶入這個函式來使用。所以當它需要傳回一個T型別的物件時,它只能用default(T)的方式來產生物件。這種方式對一般類別或是value型別都適用。當你的T型別為value型別時,就會傳回所有bit均為0的值。當你的T型別為一般類別時,則會傳回null值。 再來看CreateGeneric<T>()這個函式,它限定說所帶入的T型別需要有預設的建構子。當然value型別也是可以適用,而一般的類別則必須提供預設建構子(不帶有任何

ReaderWriterLock測試及自動釋放

在進行多執行緒模式的程式開發時,常常會需要針對會共同存取到的資料來進行同步化的動作。 同步化的方式,最常用到的應該是就Critical Section的方式了。 在C#中,要實作Critical Section的模式的話,可以使用Monitor類別,或是使用C#內建的關鍵字:lock。 不過,使用Critical Section模式的話,表示在任何一個時間下,只有一個執行緒可以來存取這項共用的資源。如果多數的執行緒只是要讀取其中的資料的話,不好意思,大家必項排隊等候這項資源才行。如果有這種情況發生的話,那多執行緒的程式設計方式,將無法為您的程式執行效能帶來太多的改善。因為,每個執行緒還是會需要去等候某項資源。 為了解決這個問題,C#中提供了一個ReaderWriterLock的物件。這種物件的特性就是在同一時間下,可以同時有多個執行緒來讀取某項共用資源。而當有其它的執行緒想要去寫入這項資源時,它也必須先排隊等候這項資源。一旦要寫入的執行緒取得資源的存取權限時,其它需要取得唯讀權限的執行緒,將全部被阻擋在外。要等到執行寫入資源的執行緒完成後,其它唯讀的執行緒才能再度取得資源。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace TestVS2008 { public class TestReadWriteLock { protected bool isStop = false ; protected ReaderWriterLock rwLock = new ReaderWriterLock(); public void StartTest() { isStop = false ; for ( int i = 0; i < 4; i++) { Thread t1 = new Thread( new ThreadStart(ReaderFunc));

SQL2008 怪訊息 -- [ 防止儲存需要重新建立資料表的變更 ]

圖片
最近下載了SQL 2008 Express來試玩。 沒想到一安裝完,只是新增一個資料庫,且新增一個資料表並儲存後,當下次要再新增資料表的欄位時,就出現:[ 防止儲存需要重新建立資料表的變更 ]這個錯誤訊息。 一開始以為是沒昇級到 SQL2008 SP1的原因,所以就去下載並昇級了SP1。而且提醒一下,要昇級時,就直接找SQL 2008 SP1來昇級就好了,不用找Express SP1。那個不是昇級用的,而是讓一開始還沒安裝過的人,一併安裝並昇級到SP1用的。 結果,昇級SP1後,還是會出現這個問題。只好再去找一下google大神了。才發現,原來微軟上 有這種錯誤訊息的說明 。大意是說,要請您使用SQL語法來變更資料表。而不要使用管理介面。 天啊,誰會特別用SQL語法來編更資料表的欄位啊。不都是透過管理介面的嗎。 所以只好往下看,原來在Manage Studio中有選項可以將這項警告關閉。不過,微軟官網上的說明好像有點問題,一直無法找到可設定的項目,只好一個個看過,原來是在[工具]->[選項]的「設計師」中才有如下圖的項目可設定。

C#矩陣(Matrix)運算函式庫

有時工作上會需要將Matlab的程式碼轉譯成C#版本。 在Matlab中,大部份都會使用到矩陣運算的功能。而這部份也要能轉譯成C#才行。 目前在CodeProject中有人提供一組不錯的 C#矩陣運算函式庫 ,有需要的人可以去下載來使用看看。

yield的使用及原理

圖片
不久前在點部落格看到有人在說明yield這個關鍵字的用法。 那位作者大致上只是說明yield該如何使用而已,而沒有提到它有什麼好處,以及它的運作原理。 今天突然想要研究yield的用法,就去google了一下。沒想到找到幾篇不錯的文章。趁機記錄下來以便查詢。 在這篇文章中,作者說明了 使用yield的呼叫流程 。基本上,一開始大家的作法都會是先將要傳回的資料整理成一份List,再傳回給外面呼叫的函式來使用。這樣的方式有些缺點: 要耗用一個List的變數及記憶體空間。 要花時間將資料放入到List中,傳回。 而在改用yield之後,可以避免掉以上的兩個缺點。改為傳回一個IEnumerator<>的變數,讓呼叫的函式來使用。因為是IEnumerator,所以事先不用複製一份,像是放在List中這樣傳回。 當然,您也是可以自己提供一個自己實作IEnumerator<>的物件傳回給呼叫端使用。不過,這樣等於您自己還在要寫一段程式碼。 使用yield之後,實作IEnumerator<> 的工作等於是編譯器會幫您在背後進行。至於編譯器所產生的程式碼可看這篇文章中, 作者用反組譯程式所看到的程式碼 那樣。 說到這裏,可能要來寫個範例,大家比較能知道其中的差異及效能上的差別。 程式碼如下: static void TestYield() { Random r = new Random(); List listData = new List(); for (int index = 0; index < 10000; index++) { listData.Add(r.Next()); } Stopwatch watch = new Stopwatch(); watch.Reset(); watch.Start();   // Get data by normal list for (int i = 0; i < 1000; i+

double NaN的判斷

最近在寫程式時,發現Math.Log()這個函式,如果第一個參數為負值時,就會傳回NaN的結果。 於是我想要判斷當傳回值是NaN時,就進行特別的處理。 我的程式碼如下: double d = Math.Log( -1,10); // 強迫傳回NaN的值。 if(  d == double.NaN ) { // 特別處理 } 結果發現,當d的值為NaN時,if()那行的判斷式卻不成立。真的很令人無法相信。 於是我又寫了另一段測試程式: double d = double.NaN; if(  d == double.NaN ) { // 特別處理 } 各位猜猜結果如何? 我都已經直接指定d 的值就是double.NaN了。可是在if()的判斷式中就是不成立。 後來,沒辦法,只好用如下的方式來解決了。 if( double.IsNaN( d ) ) { } 目前測試的結果,發現只有使用double.IsNaN()函式才能正確地判斷出NaN的值。