很好用的工具函式String.Format
除了用來把數值轉成字串,把時間轉成字串,或者以特殊的格式來展現字串之外
還能夠進行文字對齊,自動填滿空格
一般常用的
1.數值轉換
String.Format( "{0:#######.##", 123.456} )輸出為123.46(自動四捨五入)
String.Format( "{0:#######.00", 123.456} )輸出為123.46(自動四捨五入)
String.Format( "{0:#######.0000", 123.456} )輸出為123.4560(後面自動補零)String.Format( "{0:000###.0000", 123.456} )輸出為000123.4560(後面自動補零)
還可搭配逗號來分隔千位、或數字分群,太細的不談
簡單的說,#跟0都可以將輸出定位,而對#來說
在小數點的部分,如果#的數量比數字位數少,就可以顯示統一格式在小數第幾位,而0的話,會有自動補0的功能(其他數字也可以)
如果要將 0.523 顯示為 0.5,必須要用
String.Format( "{0:###0.0000", 0.523} )輸出為0.5,否則如果用
String.Format( "{0:###.0000", 0.523} )則輸出為 .5
2.字串對齊
以上是數值轉換的部分
而如果要對齊的話,則要注意的是Format()的第二個參數必須是字串,不能為數字
比方
String.Format( "{0,9}", StrFreeSize )當中,StrFreeSize 必須是字串,不能是數值,表示,如果StrFreeSize 的長度不足9則會在字串的前端補上空白。
String.Format( "{0,-9}", StrFreeSize )當中,StrFreeSize 必須是字串,不能是數值,表示,如果StrFreeSize 的長度不足9則會在字串的後端補上空白。
我喜歡設計,我喜歡創造,我喜歡美 不論軟體設計,不論介面設計,不論產品規劃設計,我都很有興趣 一直希望能能用這份專長,好好發揮在職場上。讓我做的快樂。 不論寫程式,或是做美工,我都很喜歡,希望我可以有機會雙線。兩種都很擅長。
2011年9月8日 星期四
DataGridView如果Disble會影響Scroll無法正常運作
與Single-Thread或Multi-Thread無關,只要將DataGridView的Enable屬性設定成Disable,則他的ScrollBar也會一併Disable,且同時失去了「在RowAdded之後,會自動控制ScrollBar」的特性。也就是,如果把DataGridView設定為Disable的之後,如果Rows.Add(),會變成僅資料一直增加,但Scroll卻無對應的變更。
DataGridView的RowEnter事件注意事項
DataGridView的RowEnter()事件有個需要注意的地方
就是這個事件並不會被滑鼠右鍵所觸發,雖然滑鼠右鍵點選在某個ROW,但是那個格子並不會顯示為Selected狀態,所以此事件也不會被觸發,所以如果需要在滑鼠右鍵也進行一些狀態判斷,一定要另外寫在MouseDown()事件當中,不可以只寫在RowEnter()
通常是在操作者用滑鼠右鍵呼叫出ContextMenuStrip時,使用了選單的「編輯」或「刪除」動作,但如果僅把的現在選到那個Row的判斷部分寫在RowEnter(),就會出錯了,因為根本不會呼叫到RowEnter()的
完整的C#多國語言解決方案(二)- 字串多國語言
檔案增加好了之後程式怎麼撰寫?請看:
假設此專案的Namespace名稱為MultiLanguageTest
假設把語言包取名為LanguagePack
假設LanguagePack.en.resx裡面有新增一個StringTest001的字串。內容是:"我是中文的字串"
假設LanguagePack.zh-TW.resx裡面有新增一個StringTest001的字串。內容是:"I am English"
利用ResourceManager來取得對應文化的resx檔案,然後利用GetString()告訴ResourceManager你要取得那個字串,如此,就會根據你的OS來抓取正確的語言檔.resx
ResourceManager Rm = new ResourceManager( "MultiLanguageTest.LanguagePack", Assembly.GetExecutingAssembly( ) );
MessageBox.Show( Rm.GetString( "StringTest001" ) );
「這樣測試過後,只能看到中文的字串,因為我用的是中文的作業系統啊,怎麼知道這樣寫對不對?」在你的Program.cs 的main()裡加上這個Thread.CurrentThread.CurrentUICulture = new CultureInfo( "en" ); ,執行之後,你就可以讓程式強制在英文的語言文化來呈現了。
加上這行之後,編譯可能看到「Thread不存在目前內容中」、「CultureInfo不存在目前內容中」的錯誤訊息,Using引用進來就好了。
完整的C#多國語言解決方案(一)- 畫面多國語言
新增一個C#專案,並選擇 [ Windows Form應用程式 ],將原本預設的 Form1更改設定為FormMain,可看到畫面如下
為了測試,我們在Form上面放上四個原件,一個Lable,名稱為Lbl_Test,一個ListBox,名稱為LstBx_Test,一個PictureBox,名稱為PBox_Test,一個按鈕,名稱為Btn_Test。
將Form的Localizable改為True,此Form就會具有多國語言的特質,然後若把Language改為中文,並且更改視窗內任何原件的位置或Text,之後存檔,就會看到多了一個檔案:FormMain.zh-TW.resx,位置跟文字的資訊就會被儲存在這個語系檔中。如下圖
接下來再把Language改為英文,並且更改視窗內任何原件的位置或Text,之後存檔,就會看到多了一個檔案:FormMain.en.resx,位置跟文字的資訊就會被儲存在這個語系檔中。如下圖
如何能控制系統現在要顯示哪一種語系的應用程式外觀呢?可以不用設定,OS就會自動決定出了你的語系,比方你安裝台灣中文版的Windows通常你的語系跟使用地區就會是台灣,安裝過程也有讓你設定使用地區,這些就會決定了語系,當然,為了測試或特殊需求,你也可以在Program.cs當中撰寫以下幾行程式:
CultureInfo CI = new CultureInfo( "zh-TW" );
System.Threading.Thread.CurrentThread.CurrentUICulture = CI;
CultureInfo就是設定文化語系的Class,用他設定zh-TW或en即可決定要使用的語系國家,之後將此設定到CurrentThread即可將此程式指定為該語系了。經過以上的設定過後,專案將會有中文與英文兩個版面,而根據被指定要顯示中文或英文語系來顯示不同的Text String與物件位置(各國語言文字所需要的長寬不同的關係)。
那圖片的部分能不能透過以上的步驟來設定兩種以上語系的圖片,然後讓應用程式根據語系,來呈現不同的圖片呢?答案是不行。圖片的控制要自己來。這是最麻煩的地方,多語系如果要有不同的圖,就是要多花很多功夫。
而如果你有訊息要顯示在...比方對話框中,或者是其他跟Form、Panel無關的地方能不能透過這種設定方式,來讓不同語系之下,顯示不同的Text String呢?答案是不行。難道就這麼束手無策了嗎?也不是的,跟圖片不同的是,有特別的解決方法,請看以下的作法介紹:
而如果你有訊息要顯示在...比方對話框中,或者是其他跟Form、Panel無關的地方能不能透過這種設定方式,來讓不同語系之下,顯示不同的Text String呢?答案是不行。難道就這麼束手無策了嗎?也不是的,跟圖片不同的是,有特別的解決方法,請看以下的作法介紹:
2011年9月7日 星期三
C#記憶體與資源的釋放與管理
研讀了好多好多文章,然後得到一些心得
如果有人看了覺得不對,麻煩歡迎您告訴我
首先,看看記憶體回收機制
這兩篇文章中提到
從 Managed 堆積 (Heap) 為該物件配置記憶體。只要在 Managed 堆積中有位址空間可用,Runtime 就會繼續為新物件配置記憶體。但是,記憶體畢竟不是無限的。到最後,記憶體回收行程還是必須進行回收以釋放某些記憶體。記憶體回收行程的最佳化引擎會依據所做的配置決定進行回收的最佳時機。當記憶體回收行程進行回收時,它會檢查 Managed 堆積中應用程式已不再使用的物件,並且執行必要作業以回收它們的記憶體。
在 Managed 執行階段環境中,記憶體回收堆積 (Heap) 會管理所有類別物件。這個堆積會監視物件的存留期 (Lifetime),並且只有在程式的任何部分都不參考物件時才加以釋出。這樣可以確保這些物件不會遺漏 (Leak) 記憶體,並可確保對物件的參考永遠有效。
這樣我的心得是只要程式當中的變數或成員在他生命週期結束的時候,在GC(Garbage Collection,C#的資源回收車)定時巡邏的時候,就有機會被釋放出來(據說不會很快釋放,要巡邏好幾趟確認)。而有別於C++的delete指令可以直接把記憶體釋放,C#以這個資源回收機制,來達到安全、效能、並且讓開發人員無須擔憂記憶體管理。
但我們經常在網路上看到不少文章,要我們對資源進行釋放
using 陳述式是一個非常基本的 C# 語法,相信在實務開發上經常會使用到,如果沒使用過的人可能代表你對 .NET 的記憶體管理的 Sense 不太夠,很有可能寫出資源耗盡的 .NET 程式碼。
雖然 .NET 有內建強大的記憶體管理機制(GC),但開發人員還是不能完全依賴 .NET 來處理一些無法釋放的資源,例如:Handles, Unmanaged Resources, …。
C#提供了與C++一樣語法的解構子,當object消失時,.Net framework 會執行解構子,我們可於此時加入程式進行資源回收,與Java相同的是,什麼時候object會消失? 這由VM決定,並非在object變成null時,VM即會立刻執行解構子並回收object。
看了都會覺得害怕,擔心自己寫的程式會不斷的耗盡資源,而且還真的有發生。但是詳細看一下,他們所指的,大多是指:無法釋放的資源(Unmanaged Resources),好,再來看看是否真的如此。先從解構子來看起吧,根據官方文件說法,是這樣的:
程式設計人員無法控制呼叫解構函式的時間,因為這是由記憶體回收行程所決定的。記憶體回收行程會檢查不再被應用程式使用的物件。如果它將物件視為符合解構資格,便會呼叫解構函式 (如果存在),並且回收用來儲存該物件的記憶體。當程式結束時,解構函式也會被呼叫。
☆解構函式是用來解構類別的執行個體。
☆結構中無法定義解構函式。它們只能與類別一起使用。
☆一個類別只能有一個解構函式。
☆解構函式不能被繼承或多載。
☆解構函式不能被呼叫。它們會被自動叫用。
☆解構函式不使用修飾詞或參數。
☆解構函式會隱含呼叫物件之基底類別 (Base Class) 上的 Finalize
也就是說,不是在你把物件設定為NULL或是生命週期一結束,就會呼叫解構子,要等GC認定符合資格才行,那該信任GC嗎?我們會不會很快就把資源耗盡?我們繼續參考以下非官方文章:
基本的原則是當該變數「不再有效」時,便會被視為garbage,具體的情況則包括超出該變數的有效範圍(ex:離開了對應的大括號的區域變數)、 將變數指定為null、重新指向其他物件(而原先指向的物件已無法被取得)、重新初始化…等,這時原先變數佔有的空間都會被CLR視為garbage而等待回收。若變數為數值型別,則當其超出有效範圍時,CLR會直接回收它在Stack上所佔用的空間;若變數為參考型別,則CLR會先回收它在Stack上佔用的空間,而將Heap上的空間視為garbage,等待GC回收。若參考型別的變數在其有效範圍內重新初始化,則原先所指向的物件亦會被視為garbage。然而,被視為garbage的變數,並不是馬上就被GC回收,而是根據GC內的演算法,依變數被判定的generation而有不同。在Managed Heap上的物件會被CLR分為三個generation:0、1、2,數字越大表示存活時間越長。這樣的設計乃是建構在「只壓縮部份的Heap會比一次壓縮整個Heap來得有效率」的事實上,因此將物件分成不同的層級,在回收時針對不同層級做回收,是.NET Framework考量效率後所採用的方法。程式中常會應用到的區域物件與暫時物件因都屬於gen 0,故可確保被回收的頻率最高,對一般不會用到大量暫時物件的程式而言,不需擔心資源的浪費。
也就是說一般大多情況我們是該相信GC的,但是如果我們的程式需要用到很多資源呢?繼續看下去
「若是程式員希望在某個時間點確保Managed資源被回收,應該怎麼做?」「若是類別中含有Unmanaged資源,又該如何釋放?」對於這二個問題的回答,在這裡便開始要提到程式員如何撰寫明確釋放資源的函式了。在C++中,程式員撰寫類別的Destructor來達成類別資源的釋放,而在C#中,同樣有類似效果的函式有Finalize()與Dispose()。Dispose()與Finalize()最大的不同,在於Dispose()是明確地在「程式員呼叫」與「using語句區塊結束時」二種情況下被呼叫的。也就是說,當程式員想確保某個類別中的Unamaged資源會在某個特定位置被釋放掉時,他便可以實作IDisposable介面中的Dispose()函式;而為了提供程式員在操作常用的暫時物件上不會忘記呼叫Dispose(),C#中提供了using陳述式,確保在小括弧中的變數,在離開using區塊時,其Dispose()會被明確地呼叫。當一個物件的Dispose()被呼叫後,亦即標示了這個物件為無效,則在第一次的GC回收行程中便會被回收到。值得一提的是,即使某個物件的Dispose()已經被呼叫過了,該物件的Finalize()仍然有可能再被GC給呼叫到,這是為了避免當Dispose()失敗時可能產生的資源浪費。然而,若Dispose()成功地執行了,則應該避免再讓GC去呼叫Finalize(),否則會造成程式效率的低落。
也就是說資源的釋放,可以交給GC,如果要自己來釋放,就要實作Dispose()
而關於Dispose()的實作方式,就參考這兩篇文章了
把Unmanaged Resources,或是你想要早點自己釋放的Managed Resources寫在Dispose(),就行了。
綜合心得:
1.如果僅用了Managed資源,GC可以自動幫我們釋放記憶體,如果我們需要自己提早釋放,則可以實作出Dispose()函式。
2.如果使用了Unmanaged資源,一定要寫Dispose()函式,才能自己釋放,否則只能等程式停止才會釋放。
3.官方說寫Destructor()但是裡面如果是空的,對Managed Resource來說是沒有幫助的,反而減低效能,所以要寫出Destructor(),就要把裡面的內容實作出來才有意義。
4.Dispose()的內容,參考MSDN的作法,寫一個Dispose( bool )的函式,如果參數是true,是call by program (程式設計師),就釋放Unmanaged Resources與Managed Resources。而如果是false,這是call by C#(C#機制自動呼叫的),這時候,因為Managed Resources已經被釋放了,所以就避開,不要再次呼叫Managed Resources的Dispose(),不然會多耗費效能的。
管理問題?
昨天我的工作指派人來找我
談了將近一小時
*內容:
有個案子的CODING(除了面對客戶之外的部份)要全部交給我,除了有一塊比較不相干的部份會切出去;工作指派人直接告訴我要做什麼什麼,要站在不同的角度先規劃等等...?
*感想:
嗯?好像少了什麼,他有徵求我的同意嗎?我有說我願意接嗎?他接下了經理指派給他的專案,但不代表我也要接;除此之外,對方告訴我的需求全都模擬兩可,檔案格式可能是這樣也可能不是這樣,進一步詢問,他也不確定,偏偏很多檔案都是不同格式的,每個都不確定要怎麼做?就是在PARSER檔案的程式,卻連檔案格式都不確定,還要我自己去想像各種檔案格式以及各種檔案格式會發生的狀況???現在是怎樣,光空想就有辦法做出來是嗎
以上
是用負面情緒的字眼描述出來的事實
*背景?
聽說一開始(可能在年初專案剛開時),案子因為沒有人接,所以分配給一位經理,所以那位經理是這個專案的負責人;在上禮拜(或上上禮拜?),我的工作指派人加入那這個專案,於是乎開始派一些程式給我寫;在我一開始碰這個案子時,就覺得這個案子的每一個需求都模擬兩可,因為站在幫忙寫CODE的最低階工程師立場,我只能盡量詢問,沒想到越問越模糊不清,我只好就我知道的部份分析、規劃程式架構,心裡抱著不踏實、搖搖晃晃的感覺,寫出了一個可以PARSER的程式,結果工作指派人一看,又說檔案可能沒有先後順序,所以要改,但也有可能是有先後順序的....在這個案子裡非常非常多這種狀況,幾乎每個需求都建立在不確定的感覺上,讓人完全感覺不到踏實。(難道我是在雲端工作嗎?我不是已經離開了)
談了將近一小時
*內容:
有個案子的CODING(除了面對客戶之外的部份)要全部交給我,除了有一塊比較不相干的部份會切出去;工作指派人直接告訴我要做什麼什麼,要站在不同的角度先規劃等等...?
*感想:
嗯?好像少了什麼,他有徵求我的同意嗎?我有說我願意接嗎?他接下了經理指派給他的專案,但不代表我也要接;除此之外,對方告訴我的需求全都模擬兩可,檔案格式可能是這樣也可能不是這樣,進一步詢問,他也不確定,偏偏很多檔案都是不同格式的,每個都不確定要怎麼做?就是在PARSER檔案的程式,卻連檔案格式都不確定,還要我自己去想像各種檔案格式以及各種檔案格式會發生的狀況???現在是怎樣,光空想就有辦法做出來是嗎
以上
是用負面情緒的字眼描述出來的事實
*背景?
聽說一開始(可能在年初專案剛開時),案子因為沒有人接,所以分配給一位經理,所以那位經理是這個專案的負責人;在上禮拜(或上上禮拜?),我的工作指派人加入那這個專案,於是乎開始派一些程式給我寫;在我一開始碰這個案子時,就覺得這個案子的每一個需求都模擬兩可,因為站在幫忙寫CODE的最低階工程師立場,我只能盡量詢問,沒想到越問越模糊不清,我只好就我知道的部份分析、規劃程式架構,心裡抱著不踏實、搖搖晃晃的感覺,寫出了一個可以PARSER的程式,結果工作指派人一看,又說檔案可能沒有先後順序,所以要改,但也有可能是有先後順序的....在這個案子裡非常非常多這種狀況,幾乎每個需求都建立在不確定的感覺上,讓人完全感覺不到踏實。(難道我是在雲端工作嗎?我不是已經離開了)
訂閱:
文章 (Atom)

