2009-08-12

感想-收拾殘局

要求自己一定要做個紀錄,其實還滿難堅持的
當然,能都把所經歷過的事情
詳細記錄下來,這樣是最好的,但事實卻不是那樣的稱心如意

今天,我想寫一些想法
寫程式也寫了一陣子了,不算長、也不算短的時間
常常會面臨到要去看別人程式
去維護"前人"寫的程式

好的程式,你一眼就可以很一目暸然
詳細的註解、功能清楚的劃分、物件導向的設計
以及最重要的一點[每段程式碼都是簡短的!]
今天,若是將幾百行程式碼放在你的面前
你要怎麼看?

正常來說,你必須從頭看到尾
所以會演變到你若要更動其中的程式
情況好,只要更動一小部份就好
但是萬一整個邏輯更動
就會發生[牽一髮而動全身]的窘境
聽到我這樣說,曾碰過這樣情形的人
應該已經會心一笑了!!
接下來你就會發現,你不是在維護程式
而是在重寫程式。。。

現在我寫程式都是掌握幾個要點
1.用物件的觀念來思考架構,但不急著動手去Coding,
詳細考慮過後,才會著手進行。
2.程式碼區段不超過30行以上,若是過長的程式區段
,會想辦法再抽離出來。
3.註解盡量詳細,若是Method的參數已經很明瞭
,就不需要註解。
4.要設想未來可能所發生的問題,
你無法實際掌握可能發生的情況,但你可以設法去猜測。
5.要愛用Namespace,程式碼中也多用region。
6.….等

會有這樣的想法,是因為今天我正在重寫
某位仁兄的程式碼,他的一個Method區段
就快300多行。。
他的程式碼是長這樣的

//Step1
....程式碼
//Step2
....程式碼
//Step3
....程式碼
//Step4
....程式碼
//Step5
....程式碼
//Step6
....程式碼
//Step7
....程式碼

看到這,是否已經可以體會我心中想說的?

Class 設計

這個網誌,也空了一段時間
因為之前為了準備考試,再加上工作的忙碌
回到家就幾乎不想再碰電腦(懶的打字 ^^")

只是,這樣並不是很好的習慣
有些事情真的要當下記錄下來。。。
看著之前所寫的紀錄,雖然有很多地方有誤
但這些紀錄讓我明瞭,曾經做了哪些事情
至少再走過同一段路時,可以提醒自己曾經做了哪些抉擇。
廢話少說。。紀錄一點心得

-----分隔線------
最近在撰寫程式的時候,開始漸漸使用Interface來設計物件

假設,我今天要設計Message Class(有許多類型)
遇到的一個小問題是:
今天若有多個不同種類的Message Class,
當然Member也一定會有所不同,我如何確保這些Message
維持在同一個規範下?

我想到的解決方法如下:
1.建立一個抽象類別當作是Message的基底類別。
你可以選擇實作成員,或是建立抽象成員
當繼承這個抽象類別時,也須遵守實作抽象成員。
例如:
建立抽象類別(MsgBase),
Message1繼承這個抽象類別並實作抽象成員


   1:      public abstract class MsgBase
   2:      {
   3:          public abstract string Name
   4:          {
   5:              get;
   6:              set;
   7:          }
   8:   
   9:          public string GetMessage()
  10:          {
  11:              return "My Message!";        
  12:          }
  13:      }
   1:      public class Message1:MsgBase
   2:      {
   3:          private string NameField;
   4:          public override string Name
   5:          {
   6:              get
   7:              {
   8:                  return NameField;
   9:              }
  10:              set
  11:              {
  12:                  NameField=value;
  13:              }
  14:          }
  15:      }

Message1這個Class則有(Name、GetMessage)這兩個成員,
藉由繼承的概念來規範。

2.利用Interface來規範。
當繼承Interface時,必須要實作Interface的成員
這樣也同樣可以規範出這個Class的框架。
而Interface的好處,則可以藉由操作Interface
來達到目的。

例如:
今天我得到一個Object,我不確定他是哪種Class
但我知道這個Object繼承了我所得知的Interface
可以藉由操作Interface的方式,同樣也可以達到效果。

   1:  ISerialize mySerialize=o as ISerialize
   2:  mySerialize.Serialize();

我亂寫到這,其實學習設計物件
經驗還不足,不過慢慢懂得一點點

介面導向設計(interface-oriented design)

前陣子,在最常逛的Blog裡
看到這篇文章
小朱的技術空間 - 邁向架構師的暖身運動(1):介面導向設計
剛看標題,我以為是我看錯了
介面導向設計??  不是物件導向設計嗎??

後來,看完整篇文章
我有點被打醒。。。
對阿~沒錯
介面導向設計。。。

我相信應該有人跟我有同樣的疑惑
在設計一個物件時,有需要或必要再設計Interface嗎?

對我這個新手來說,一開始接觸Interface時
我充滿了許多的疑惑?這是用來幹麻的??
Interface只是定義了成員的原型,又沒辦法直接在Interface上實作
對物件來說,這有其必要性嗎?

就在Coding的一小段時間裡,我漸漸了解了Interface
在一個複雜的物件中,Interface就有其存在的必要性
甚至在最近看的WCF中,也使用到Interface的特性

文章中提到,關於資料庫的CRUD (Create/Retrive/Update/Delete)
這是一個很基本的實例。
是的,每一個資料庫會使用到的基本功能會是這些
當你設計了關於Oracel資料庫的物件
那SQL Server呢?是不是也需要重新設計相同的功能(CRUD)
使用Interface可以實際的規範出這些原則
讓相似的功能,有了統一的規範

又因為C#在物件繼承中,可以繼承多個Interface
這就讓物件上的設計,藉由繼承多個Interface來完成功能實現
意思是你可能藉由繼承Interface而設計出複雜物件的架構
當然你還是需要去實作。。。

簡單寫到這,或許以後可以再補述。。。

2009-04-05

Web Service非同步練習

在撰寫程式時我會盡量避開多執行緒問題
前陣子因為程式需求,比較常用.Net的BackgroundWorker
這次在練習撰寫Web Server時遇到一個課題

若是今天Client端程式去呼叫Web Service
而Service卻需要較長時間運算,才能回傳結果回來
那在Client端的UI會整個hold在那
這是我們開發程式的人最不想看到的樣子
(除非使用者很有耐心的等待!
不然你可以想像到,隔著螢幕後有個人一直幹樵敲鍵盤)

在微軟出的MCTS:Distributed Application Development Training Kit這本書的Chapter 7裡有大致提到使用非同步的方式。

接下來我也只是根據練習,實做下去
首先我先定義一個Delegate

public delegate string DelegateHelloWorld(string Name);

接下來使用BeginInvoke來實作
localhost.Service locService=new WinClinetPolling.localhost.Service();
 
DelegateHelloWorld myDelegate = new DelegateHelloWorld(locService.HelloWorld);
 
 
IAsyncResult result=myDelegate.BeginInvoke(textBox1.Text,null,myDelegate);
 
 
label1.Text="程式處理中,請稍候。。。";
 
 
while(!result.IsCompleted)
 
{
 
    label1.Text+="。";
    
    Application.DoEvents();
    Thread.Sleep(1000);
 
}
 
label1.Text="完成"+myDelegate.EndInvoke(result);     


其中locServer是我建立的Web Server
提供一個帶參數Method名稱為HelloWorld
這個Method中,我執行了一段程式碼
Thread.Sleep(10000);
也就是說當我呼叫這個Method時
會延遲十秒鐘後,才會回傳值

利用Delegate的BeginInvoke方式
來進行Asynchronously

其實也可以直接使用Web Service提供的
Asnyc方式,直接呼叫HelloWorldAsync
當建立了新的Web Method後,會自動提供另一個Asnyc
原本我的Method-HelloWorld
會再提供一個Asnyc的HelloWorldAsync

proxy.HelloWorldAsync(textBox2.Text, null);
 
label2.Text = "開始處理。。。請稍候!";

之後我們在去訂閱這個Method的Completed事件

proxy.HelloWorldCompleted += new WinClinetPolling.localhost.HelloWorldCompletedEventHandler(proxy_HelloWorldCompleted);

在Completed事件中

private void proxy_HelloWorldCompleted(object sender, WinClinetPolling.localhost.HelloWorldCompletedEventArgs e)
{
 if (e.Cancelled)
 {
  label2.Text = "取消了。。。";
 }
 else if (e.Error != null)
 {
  throw e.Error;
 }
 else
 {
  label2.Text = e.Result;
 }
}

先簡單記錄下來。。。

Universal Time 轉換成 Local Time

最近在撈取資料庫資料時,遇到一個問題
在這些資料中,有一些關於Date的資料
但這些時間全部存的都是Universal Time
當我直接撈回Local端來呈現報表時,會遇到時間錯亂的狀況

接下來的程式部份,是參考公司裡林大哥的程式

public static string[] SPFDateFormats = new string[] { "yyyy/MM/dd-HH:mm:ss", "yyyy/MM/dd-HH:mm:ss:fff", "yyyy/MM/dd" };    

public static DateTime ToUniversalTime(string pstrServerDate)
 
{
 
    DateTimeFormatInfo provider = new DateTimeFormatInfo();
    provider.DateSeparator = "/";
    provider.TimeSeparator = ":";
    try
    {
    
    return DateTime.ParseExact(pstrServerDate, SPFDateFormats, provider, DateTimeStyles.None);
    }
    catch (Exception exception)
    {                
    
    return DateTime.ParseExact("9999/12/31-23:59:59:999", SPFDateFormats, provider, 
    
    DateTimeStyles.None);
    }
 
}

這樣轉出來就會是Local Time。
先大概記錄下來。。或許以後還會使用到

參考資料:
1.DateTimeStyles
2.DateTime.ParseExact
3.DateTimeFormatInfo

2009-03-24

ReaderWriterLock

最近在撰寫Web Service程式的時候,遇到一個問題,
就是在Web Service程式碼中雖然有用Try...Catch保護
但是卻沒將錯誤資訊記錄下來
所以導致在Server端發生錯誤,但卻感覺什麼事情都沒發生的情況

想到的解決方法是
1.將錯誤寫一個Txt檔案。
2.將錯誤寫進Event View裡。

我選擇第一個方式寫一個Txt檔案
我不曉得是否會發生程式同時寫入同一個檔案的問題
想到之前有聽到這個類別
ReaderWriterLock
一直沒有去實際嘗試看看,所以趁這個機會來嘗試一下

首先我建立了兩個Thread
Thread myThread1 = new Thread(new ThreadStart(WriteA));
 
Thread myThread2 = new Thread(new ThreadStart(WriteB));
myThread1.Start();
myThread2.Start();

模擬不同使用者在同一時間
寫入相同檔案的狀況。。。

private void WriteA()
 
{
 
    rwLock.AcquireWriterLock(10000);
 
    using (FileStream fs = new FileStream(@"C:\ReaderWriterLock.txt", FileMode.Append, FileAccess.Write))
 
    {                
 
    
    StreamWriter sw = new StreamWriter(fs);                               
    
    sw.WriteLine("A:" + DateTime.Now.ToString());
    
    sw.WriteLine();
    
    sw.Close();
    
    DelegateChangeLabel dclDelegate = new DelegateChangeLabel(ChangeLabelA);                
    
    label1.BeginInvoke(dclDelegate);
    
    Thread.Sleep(5000); 
    }
    rwLock.ReleaseWriterLock();
 
}
 
 
private void WriteB()
 
{
    rwLock.AcquireWriterLock(10000);
    using (FileStream fs = new FileStream(@"C:\testReaderWriterLock.txt",FileMode.Append,FileAccess.Write))
 
 
    {
    
    StreamWriter sw = new StreamWriter(fs);                               
    
    sw.WriteLine("B:" + DateTime.Now.ToString());
    
    DelegateChangeLabel dclDelegate = new DelegateChangeLabel(ChangeLabelB);
    
    label1.BeginInvoke(dclDelegate);
    
    sw.WriteLine();
    
    sw.Close();                
    }
    rwLock.ReleaseWriterLock();
 
}

rwLock是ReaderWriterLock物件
我利用ReaderWriterLock物件的AcquireWriterLock方法
去鎖定寫入檔案動作,直到ReleaseWriterLock方法
去釋放鎖定。。。

簡單的測試。。小小心得紀錄。

2009-03-10

Regex 檢驗機制的小嘗試

在撰寫程式的時候,我們大都會遇到關於字串解析的問題
譬如:所輸入的字串是否符合規定,
或是擷取字串其中某一小段,或是判別字串是否等於某個值

今天的小嘗試,所要做的就是去判別所輸入的字串
是否符合格式。。。所使用的是Regex這個類別

就已簡單判斷E-Mail輸入正不正確
程式碼如下:

 Regex r = new Regex(@"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$");
 
Match m=r.Match(tbxMail.Text);
 
if (m.Success)
 
  MessageBox.Show(m.Value);
 
else                
 
  MessageBox.Show("輸入Mail格式錯誤!");     

在建立Regex物件時,所傳入的建構式參數
是Regular Expression字串
(其實到現在為止,我還不知道這個字串該怎樣去拼湊)
所以我上網去找關於E-Mail的Regular Expression
簡單結果測試如下:
image
image 

參考資料:
MSDN: Regex 類別
RegExLib.com
Regular-Expressions.info

2009-03-09

MVC的小體驗

MVC
最近寫了一支小程式,為了專案上的便利性
必須同時要完成使用者該做的事項
有點像是使用者初始化的小功能
(當使用者使用我們系統時,就先幫他處理完該做的事項)

當時有點小時間,所以想嘗試看看MVC這個design pattern
因為需求並不多,只需要簡單做一些事情即可
設計的概念是這樣。。
View部分完全單純處理顯示資料進度與結果
所有的動作都集中在Model裡背景執行
Controller部分則利用Event來傳遞顯示的事件、觸發事件

當時我並未考慮太多,所以所有的動作都集中在Model
(同一個Class裡)

 image
但需求是會不斷變更的,結果剛開始幾個需求變更
我都還能輕鬆應付,因為只要變更Model
而View只要負責顯示就好。。。
接下來的功能需求,真的把我搞的快瘋掉

我不該將所有的功能都集中在一個Class裡設計
每個物件都應該有他自己的功能
即使只是一個小小的功能,他也應該是要分開出來
[集中]-只會讓我更難去維護

所以我花了一些時間
將原本的Model分開了許多小部份
 
image

將Model分開之後,原本複雜的Model
變的更簡潔易懂,也更容易進行維護
寫下小小心得,紀錄這件事情!

參考資料:
Topic: JSP 架構介紹 - Model1 , Model2 , and Model2x
The Model-View-Controller Design Pattern
Building Graphical User Interfaces
MVC#
Model-View-Controller Pattern

2009-02-23

C# – Recursion & XmlTextWriter

image

最近因為程式的需要,必須提供一個功能給使用者 就是能讓他們自己建立TreeNode 這個部分相當簡單。。 只要去指定每個TreeNode的ContextMenuStrip屬性

   1:  TreeNode tnAdd = new TreeNode(NodeName);
   2:  tnAdd.ContextMenuStrip = contextMenuStrip1;

只是使用者還需要一個功能 就是能將所建立的Tree整個備份下來 當然,我直覺想到的是XML格式 因為除了要儲存每個Node名稱外 也需要儲存相關Node的資訊(像是Folder資訊、Document資訊) 在這裡我使用兩個主要的方式
1.Recursion(遞迴)
2.XmlTextWriter物件
使用Recursion是因為我並不清楚 底下會長出多少個Node,也就是我不清楚要用多少個迴圈 來找出所有的Node,利用Recursion 可以讓我不需要知道,也可以一層一層找下去 在寫Xml檔案時,我使用XmlTextWriter物件

   1:  string strFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); 
   2:  strFolder=string.Format(@"{0}\{1}",strFolder,"DDA.xml"); 
   3:  //---Xml write---- 
   4:  using (XmlTextWriter xtw = new XmlTextWriter(strFolder, Encoding.UTF8)) 
   5:  { 
   6:    xtw.Formatting = Formatting.Indented;
   7:    xtw.WriteStartDocument();
   8:    xtw.WriteStartElement("List"); 
   9:    WriteElement(xtw, tvList.Nodes); 
  10:    xtw.WriteEndDocument(); 
  11:  }
  12:   
  13:  //---Recursion---- 
  14:  private void WriteElement(XmlTextWriter xtwThis, TreeNodeCollection tnCurrentNodes) 
  15:  { 
  16:    foreach (TreeNode thisNode in tnCurrentNodes) 
  17:    { 
  18:      xtwThis.WriteStartElement(thisNode.Text); 
  19:      if (thisNode.Nodes.Count>0) 
  20:      { 
  21:          WriteElement(xtwThis, thisNode.Nodes); 
  22:      } 
  23:    xtwThis.WriteEndElement();
  24:    } 
  25:  } 
  26:   

簡單寫下這些紀錄,可以供以後做參考用 在寫這支程式時,遇到一個小問題 就是我嘗試要在XML的主目錄下,建立多個Element 這會產生錯誤,在主目錄中只能增加一個Element 不曉得是不是這樣,先記錄下來。

參考資料
1.
http://chrisbalboa.wordpress.com/2007/10/02/aspnetxmltextwriter-demo-%E7%AF%84%E4%BE%8B/
2.
http://www.builder.com.cn/2007/0924/521705.shtml
3.
http://www.cnblogs.com/chen79/archive/2008/01/05/1027064.html

2009-02-18

Linq 基本語法 - Join

Join
The Join operator performs an inner equijoin on two sequences based on keys extracted from each element in the sequences.

public static IEnumerable<V> Join<T, U, K, V>(
this IEnumerable<T> outer,
IEnumerable<U> inner,
Func<T, K> outerKeySelector,
Func<U, K> innerKeySelector,
Func<T, U, V> resultSelector);


在這裡建立了兩個List
List ltUser = new List(20);
for (int i = 0; i < 20; i++)
{
  ltUser.Add(new User(i,"AA"));                
}
 
List ltUserInfo = new List(10);
for (int i = 0; i < 10; i++)
{
  ltUserInfo.Add(new UserInfo(i,"CC"));                
}

Linq語法如下:
var Users=ltUser.Join(ltUserInfo,
  a=>a.No,
  b=>b.No,
  (a,b)=>new{id=a.No,UserName=a.Name,Department=b.Department});
 
StringBuilder sb=new StringBuilder();
foreach (var item in Users)
{
  sb.AppendLine(item.ToString());                           
}
richTextBox1.Text=sb.ToString();

最後產生如下結果
image

最後產生的結果,有點像是Inner Join
其實最近有點懶散,並沒有很仔細去看這本書
今天就先練習到這。

Linq 基本語法 – Reverse

其實這一系列Linq基本語法
都有點像是在走馬看花,就大概看過有個印象
現在專案也並未運用到,就看看之後是否會使用這項技術
 

Reverse:
The reverse operator outputs a sequence of the same type as the input sequence but in the reverse order.

IEnumerable items = presidents.Reverse();
StringBuilder sb = new StringBuilder();
 
foreach (var item in items)
{
  sb.AppendLine(item);
}
 
richTextBox1.Text = sb.ToString();

最後得到如下結果:
image
其實Reverse就如解釋中所說的,只是反轉資料。

2009-02-17

Linq 基本語法 – OrderBy 與 OrderByDescending

這兩個使用方式都相當簡單

OrderBy:
The OrderBy operator allows an input sequence to be ordered based on a keySelector method that will return a key value for each input element, and an ordered output sequence, IOrderedEnumerable<T>, will be yielded in ascending order based on the values of the returned keys.

若繼續範例中的那個字串陣列

var nameObjs = presidents.OrderBy(s=>s);
StringBuilder sb = new StringBuilder();
 
foreach (var item in nameObjs)
{
  sb.AppendLine(item);                
}
richTextBox1.Text = sb.ToString();


可以得到如下結果:
 
image

OrderByDescending:
This operator is prototyped and behaves just like the OrderBy operator, except that it orders in descending order.

從上面的字義,可以很清楚了解到
其實OrderByDescending是降冪排序
而OrderBy是升冪排序

var nameObjs = presidents.OrderByDescending(s=>s);
StringBuilder sb = new StringBuilder();
 
foreach (var item in nameObjs)
{
  sb.AppendLine(item);                
}
 
richTextBox1.Text = sb.ToString();


最後產生如下結果:   
image

2009-02-12

Linq 基本語法 - Take

在開始寫這篇練習前,心裡有點感觸先寫下來
昨天正在網頁上搜尋Linq的資料時
看到DAVID DONG大大的網誌
http://studyhost.blogspot.com/2009/02/silverlight.html

他在文中提到-為了爭取到某一個案子,在時程評估的時候,就已經放棄架構了,我們給了客戶一個若要遵循架構就根本不可能達成的預計完成時間。

這樣的情況,在我開發的這短短不到兩年裡
也碰到了幾次。我是最底層的開發人員
也不是資工背景出身的人,做的也並不是SA的工作
(說穿了只是[程式勞工]或稱為[程式開發機])
而做的程式,往往送交給業主後
都面臨到到[程式大改]的情況
當我偶然的機會,聽到MVC架構時
我ㄧ直Push自己,能多遵循這樣的架構開發程式

MVC的好處,我不再多說明
要開發MVC必須要做點苦功,才能發揮它真正的效用
一開始的設計階段是滿痛苦的,你必須要捨棄一些方便性
有時也很想直接放棄這樣的架構,但我總認為時間是寶貴的
程式開發後的維護更是重要
並不希望程式開發出去後,再丟回來維護時
又因為需求變更,而讓程式又大改。

恩~廢話少說,繼續Linq學習紀錄。

---------------------------------------------------------------------
上一篇提到的那本書中
對於Take語法,有以下註解
The Take operator returns a specified number of elements from the input sequence
簡單來說Take就是選取前面幾個

IEnumerable items = presidents.Take(5);

像上面的例子,就是選取前面五個Element。

至於TakeWhile語法
The TakeWhile operator yields elements from an input sequence while some condition is true.
簡單來說,就是符合條件為True時則選擇
不符合條件即跳出。
IEnumerable items = presidents.TakeWhile(s => s.Length < 10);

像上面的例子來說,當長度大於10則"不再"去選擇

2009-02-11

Linq 基本語法-Select

在看Apress.Pro LINQ(作者Joseph C. Rattz,Jr.)這本書時
看到這段範例(稍微改寫過)
Example1
首先定義一個字串陣列presidents

string[] presidents = {"Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland",    
"Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield",    
"Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson",    
"Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley",    
"Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft",    
"Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"};

Select語法:
var nameObjs = presidents.Select((p,i) => new { Index=i, Name=p });
StringBuilder sb = new StringBuilder();
 
foreach (var item in nameObjs)
{
  string name = string.Format(@"{0}. {1}",item.Index+1,item.Name);
  sb.AppendLine(name);
}
 
richTextBox1.Text = sb.ToString();

最後產生的結果如下
image

Example2(SelectMany用法)

Employee[] employees = Employee.GetEmployeesArray();
EmployeeOptionEntry[] empOptions = EmployeeOptionEntry.GetEmployeeOptionEntries();
 
var employeeOptions = employees
.SelectMany(e => empOptions
.Where(eo => eo.id == e.id)
.Select(eo => new {
id = eo.id,
optionsCount = eo.optionsCount }));
 
foreach (var item in employeeOptions)
  Console.WriteLine(item);


其實看完這個範例,我還是依舊不懂
所以上網查了一下,看到這兩篇文章
http://www.tzwhx.com/newOperate/html/1/11/112/14415.html
http://www.cnblogs.com/aspnet2008/archive/2008/12/19/1357690.html
大概看了一下,好像是因為Linq語法並沒有SQL的Join
才會有SelectMany這個方法,我不確定先記錄下來!

2009-02-10

LINQ初體驗

最近聽到這個名詞LINQ(Language-Integrated Query)
簡單來說:會有這項技術產生,
也是因為現階段查詢語法過於繁雜。

就拿要處理簡單的XML資料來說,
處理資料的方式就有 XPath、XmlDocument物件、XQuery,
或是使用XSLT的方式 就連不同的資料庫,
雖然都是使用SQL語法 但各家廠商都不盡相同。

在這篇文章中提到
http://www.ithome.com.tw/itadm/article.php?c=44337 簡化大量的細節運作:將「如何(How)取得資料」,換成「要操作什麼(What)資料」:這意味著LINQ將存取最佳化交由專家來做,如:由DB引擎來最佳化存取資料。

其實這句話就已經說明了很詳細。 Linq好用的地方,我在此就不在詳述 畢竟依照我小嫩嫩程式的功力 不敢在高手面前耍大刀 我只想紀錄一下第一次使用的心得

首先先定義一個int 陣列

//--自訂一個Int陣列
int[] intArray=new int[]{2,4,5,6,4,2,7,8,8};
StringBuilder sb = new StringBuilder();
 
foreach (int intItem in intArray)
{
   if (intItem>5)
      sb.AppendLine(intItem.ToString());    
}
 
richTextBox1.Text = sb.ToString();



接下來則使用Linq語法查詢

////--利用Linq語法 Where找尋大於5 
 
IEnumerable selectItem = intArray.Where(i => i > 5);
StringBuilder sb = new StringBuilder(selectItem.Count());
 
foreach (int thisInt in selectItem)
{ 
  sb.AppendLine(thisInt.ToString());
}
richTextBox1.Text = sb.ToString();


其實這篇只是簡單的紀錄一下小小心得,
還有很多關於Linq的功能,還得繼續研究下去。

2009-02-08

DataTable - 每個Cell可以存放物件

這次在撰寫需求程式時,遇到一個狀況
就是我希望在UI的DataGridView控制項上
顯示我自訂的Table資料
可是這個Table中,我也希望能同時將其餘的資訊也保留進來
只是顯示的時候只顯示我要的欄位

這樣說好像有點模糊,譬如以下圖示
image
我希望的是當我顯示Document Name的時候
也同時將Document的所有相關資訊,存進這個自訂的Table
(每一個DataRow代表不同的Document資訊)
以方便讓我的程式去做資料的讀取
(DataGridView顯示方式,是去指定DataGridView.DataSource屬性)

其實,每個DataRow的Cell可以存放物件
不單單只可以存放字串
只是要注意的是,若要在DataGridView上顯示
必須要overrride ToString()這個Method

再這裡我自訂一個QVFDocInfo Class,然後override ToString()

這樣就可以在我指定DataSource時,只秀出我要的字串
也同時將我的自訂物件存進DataTable裡。

public class QVFDocInfo
{
  private string docName;
  
  public string DocName
  {
    get { return docName.Replace("_",""); }            
  }
 
  private string obid;
 
  public string Obid
  {
    get { return obid; }
  }
 
  private string latestorAll;
 
  public string LatestorAll
  {
    set { latestorAll = value; 
  }
  
  get { return latestorAll; }            
  }
 
 
  #region Constructor
  public QVFDocInfo(string docName, string obid)
  {
    this.docName = docName;
    this.obid = obid;
  }
 
  public QVFDocInfo(string docName, string obid,string LatestorAll)
  {
    this.docName = docName;
    this.obid = obid;
    this.latestorAll = LatestorAll;
  }
  #endregion        
 
  public override string ToString()
  {  
    return docName.Replace("_","");
  }
}

2009-02-02

if 判斷簡化寫法

private bool GetResult(object o)
 
{
 
    if (o==null)
 
 
    {
    
    return false;                
    }
    else
    {
    
    return true;
    }        
 
}
假設今天有這樣一個判斷Method
單純只是要判斷傳入的參數是否為Null
然後回傳一個bool值(true or false)
一般的寫法都應該會是上面那樣




其實可以簡化成以下寫法
private bool GetResult(object o)
 
{
 
    return o == null;            
 
}

程式碼是不是更簡單明瞭多了呢??


2009-02-01

Enum的小技巧

曾在瓶水相逢.Net的Blog中看到這篇文章
Enum 的設計與應用 - 簡易權限設計
當時看到這篇就對這篇印象很深
第一次看到Enum也可以這樣使用

今天一早,原本正看著Essential C# 3.0這本書時
又突然看到[FlagsAttribute]
上網查一下MSDN,又讓我想起那篇文章
因為之前時間不夠,並未實際測試
趁今天比較空閒時,寫了一個小程式來測試一下

[FlagsAttribute]
private enum UserPriority
{
  None = 0,
  Read = 1,
  Write = 2,
  Delete = 4
};
private void button1_Click(object sender, EventArgs e)
{
  richTextBox1.Text = string.Empty;
  StringBuilder sb = new StringBuilder();
 
  for (int i = 0; i < 8; i++)
  {
    sb.AppendFormat(@"UserPriority{0}: {1}",i, ((UserPriority)i).ToString());
    sb.AppendLine();                
  }
  richTextBox1.Text = sb.ToString();
}

測試結果如下所示:
 image
果然,印證了MSDN上的結果
Enum也可以使用AND、OR、XOR的運算
雖然有點多此一舉
(MSDN上已經詳細說明了,但還是想實際測試看看加深印象)