伯舍's profile艾伯舍 & delphi 情懷PhotosBlogListsMore Tools Help

艾伯舍 & delphi 情懷

IT人:了解IT技術背後的意義,才能樂在工作和生活.
謝謝您的瀏覽!
Please wait...
Sorry, the comment you entered is too long. Please shorten it.
You didn't enter anything. Please try again.
Sorry, we can't add your comment right now. Please try again later.
To add a comment, you need permission from your parent. Ask for permission
Your parent has turned off comments.
Sorry, we can't delete your comment right now. Please try again later.
You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
Complete the security check below to finish leaving your comment.
The characters you type in the security check must match the characters in the picture or audio.
DrKNwrote:
hello...
我剛學用delphi for php呢..
打算用來做project..
能一起討論嗎
Nov. 24
伯舍 艾wrote:
呵...歡迎來到我的網誌哦
 
久了就知道我是誰了唄....(保持低調)
Mar. 19
clh cwrote:
不好意思........無意間得到您的部落格
但我想不起來從哪裡得到的
請問........您哪位啊??吐舌頭
我是Panda
Mar. 19
大部分是讀C# 2008相關書籍,整理成delphi prism語法的筆記及摘錄,完整內容請查閱每篇文章最後段落的"資料來源"。
5/15/2009

欣賞<<貧民百萬富翁>>電影後的雜想

剛看完<<貧民百萬富翁>>這部影片,這部影片整體來講劇情串連緊張環環相扣,不要認真看待劇情,打發兩個小時,算是挺不錯看的電影。

電影一開場就採用了這類節目慣用的問題形式:「你要付出什麼代價才能找回一段失去的愛情?」答案有四個,一是:金錢;二是:運氣;三是:機智;四是:命中註定。整個劇情由這個問題出發, 賈默是出身寒微的貧民窟小子,在荒亂的幼年喪失母親,由於憐憫之心遇到了同樣遭遇的女主角拉媞卡,展開流浪四處拾荒為生的日子。有一天被惡魔收容,惡魔把收容來的幼童訓練會唱歌及會跳舞,用一種極端的手段傷害幼童,挖除幼童眼睛,放到街頭行藝乞討,當做搖錢樹。

賈默原本也是被選定的對象,惡魔逼迫哥哥薩利姆陷害弟弟,哥哥最後一刻良心發現,一起抵抗惡魔逃離控制,然而女主角拉媞卡並沒這麼幸運,在惡魔營裡,被塑造成一顆搖錢樹的舞者。

這樣的場景,讓我一度以為仿傚<<血鑽石>>手法,貧窮的人民,為了能富裕,就踐踏其它的貧民,用槍欺壓搜刮其他人的財務,甚至犧牲所有人都無所謂的悲哀。

劇情脫離現實和唯美才能使觀眾覺得好看,如果發生在一般人身上,愛戀的對象變成黑社會老大搖錢樹甚至最後成為黑幫老大的禁臠,有多少人有這個勇氣再去尋找她? 或是女主角已為別人老婆或已離婚且有小孩,有幾人能不顧一切地追求唯美的愛情?

就是這麼不可思議,所以故事的結局讓人驚嘆。幼年被生活遭遇所苦的主角賈默,在急智問答的電視節目中,一題答過一題,所有的題目剛好是他遭遇所深刻體驗,刻骨銘心的,所以能選對答案,然而被主持人一度懷疑是作弊得來的,被帶到警局逼供,主角才在不得已情況下,說出會答題的生活經驗,在主持人詢問的每一題,就演出主角在小時候的苦難遭遇。最後結局是獲得二千萬印度幣,女主角此時逃出黑社會的控制,來跟他會合,有情人終於從此過著美滿辛福的生活。

看電影最忌諱像我一樣認真,認真是自討苦吃。在看此部電影時,導演假設設定,我都想以現實狀況去檢定,結果是矛盾無趣的。一是主角在小時候遇到主角,就一見鍾情;二是當要脫離惡魔營時,女主角逃脫不成,男主角終日想解救她出來,到處詢問;三是,男主角不顧一切深入到惡魔地盤,讓男主角哥哥因挺他而走險殺掉惡魔,導致主角的哥哥變成惡魔,又投靠另一股黑社會;四是,當男主角好不容易找到女主角後,要帶離她脫離苦海,女主角不願意的原因是:沒有錢,要靠什麼而生活;五是,當女主角要重獲自由之身,主角的哥哥因為覺得以前強暴虧欠女主角,自願為她犧牲成全而火拼他老大。

你要付出什麼代價才能找回一段失去的愛情?在本劇中答案很明顯,是金錢和兄弟的犧牲成全,女人只不過是追求唯美愛情下的配合者。西方的世界感情觀通常是自我和感情至上,換作台劇的情節,一段感情往往被無形的社會規範或家庭觀念約束著,門當戶對才是適配,不是男女主角想怎麼樣就怎麼樣。

5/8/2009

最近兩三事

1.Windows 7 RC公開測試版(可用至明年6月),用VMWare在虛擬機裝好之後,有比Vista流暢,一些特效也有顯現,機器的評分1.0。加載了我們以delphi 7開發的公司資訊系統,比在vista時慘,出現rtl70.bpl記憶體存取錯誤,不知如何解決(5/13原來一時豬頭,使用忘了配置的物件,經測試,可正常執行無誤)。(vista裡只要設運行的資料夾有admin權限,UAC關閉即可),測了一下網路流傳的delphi 2010內測版,可正確無誤安裝及執行。只是這樣,其餘都還沒去進一步測試。

20090508

2.公司在尋求跟海外各點線上教學及會議的軟體,用web視訊廣播,在東南亞的點看到畫面都有十幾秒的延遲,且畫面無法高解析。測試skype mikoko外掛,效果有好一點,但海外的同事都要一個個協助(忘了按允許存取skype,這外掛就無法執行),有的經協助可以掛上,有的不行,有些要邀請好幾次,才能進入會議,畫面延遲約二秒,畫面清楚,但同時聲音及畫面,三四個點就不太順利,正在尋求其它的軟體或解決方案。

3.簡體字的網站流傳一則消息,說Anders Hejlsberg即將歸delphi團隊,不過我google一下確認消息,並沒搜尋到進一步消息,有的都是簡體中文,不知道是不是八卦謠言居多? (rumor: Anders Hejlsberg will leave Microsoft and join Embarcadero next month)
http://groups.google.com/group/pongba/browse_thread/thread/627c51a70f078442/
http://explore.twitter.com/flowerborn/status/1647302137

4/22/2009

Arrays 陣列

如果需要使用同一類型的多個物件,就可以使用陣列。陣列是一種資料結構,可以包含同一類型的多個元素。在宣告陣列時,應先定義陣列中元素的類型,其後是一個空方括號和一個變數名。

interface

type
 ConsoleApp = class
 public
  class method SimpleArrays;
  class method TwoDimArraysA;
  class method TwoDimArraysB;
  class method ThreeDimArrays;
  class method Jagged;
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 //SimpleArrays;
 //TwoDimArraysA;
 //TwoDimArraysB;
 ThreeDimArrays;
 console.ReadLine;
end;

class method ConsoleApp.SimpleArrays;
begin
 var myArray:Array[0..3] of integer:= [ 4, 7, 11, 2 ];
 var v1 := myArray[0]; // read first element
 var v2 := myArray[1]; // read second element
 myArray[3] := 44; // change fourth element
 for i:Integer := 0 to myArray.Length-1 do
 begin
  Console.WriteLine(myArray[i]);
 end;
 for each val in myArray do
 begin
  Console.WriteLine(val);
 end;
end;

class method ConsoleApp.TwoDimArraysA;
begin
 var twodim:Array[0..2,0..2] of integer:=new Array[0..2,0..2] of integer;
 twodim[0, 0] := 1;
 twodim[0, 1] := 2;
 twodim[0, 2] := 3;
 twodim[1, 0] := 4;
 twodim[1, 1] := 5;
 twodim[1, 2] := 6;
 twodim[2, 0] := 7;
 twodim[2, 1] := 8;
 twodim[2, 2] := 9;
 Console.WriteLine(twodim[1,2].ToString);
end;

class method ConsoleApp.TwoDimArraysB;
begin
 var twodim:Array[0..2,0..2] of integer:=[[1,2,3],[4,5,6],[7,8,9]];
 Console.WriteLine("rank of twodim: {0}", twodim.Rank);
end;

class method ConsoleApp.ThreeDimArrays;
begin
 var threedim:Array[0..2,0..1,0..1] of integer:=[[[1,2],[3,4]],[[5,6],[7,8]],[[1,2],[3,4]]];
 console.WriteLine(threedim[0,1,1].ToString);
end;

class method ConsoleApp.Jagged;
begin
 //?
end;

end.

參考資料來源Professional C# 2008 Page 123

4/21/2009

Defining and Implementing Interfaces 定義及實做介面

interface(介面)關鍵字使抽像的概念更深入了一層。我們可將其想像為一個「純」抽像類。它允許創建者規定一個類的基本形式:方法名、參數列表以及返回類型,但不規定方法主體。在C#介面不能含變數類型的成員。介面只提供一種形式,並不提供實施的細節。

介面這樣描述自己:「對於實現我的所有類,看起來都應該像我現在這個樣子」。因此,採用了一個特定介面的所有程式碼都知道對於那個介面可能會調用什麼方法。這便是介面的全部含義。所以我們常把介面用於建立類和類之間的一個「協議」。

下面開發一個遵循介面繼承規範的小例子來說明如何定義和使用介面。這個例子建立在銀行帳戶的基礎上。假定編寫程式碼,最終允許在銀行帳戶之間進行電腦轉賬業務。許多公司可以實現銀行帳戶,但它們都是彼此贊同表示銀行帳戶的所有類都實現介面IBankAccount。該介面包含一個用於存取款的方法和一個返回餘額的屬性。這個介面還允許外部程式碼識別由不同銀行帳戶執行的各種銀行帳戶類。我們的目的是允許銀行帳戶彼此通信,以便在帳戶之間進行轉賬業務,但還沒有介紹這個功能。

為了使例子簡單一些,我們把例子的所有程式碼都放在同一個原始檔案中,但實際上不同的銀行帳戶類會編譯到不同的程式集中,而這些程式集位於不同銀行的不同機器上。但那些內容對於這裏的例子來說過於複雜了。為了保留一定的真實性,我們為不同的公司定義不同的命名空間。

interface

type
 IBankAccount=interface
  method PayIn(amount:decimal);
  method Withdraw(amount:decimal):Boolean;
  property Balance:decimal read;
 end;
 SaverAccount=class(IBankAccount)
 private
  fbalance:Decimal;
 public
  method PayIn(amount:Decimal);
  method Withdraw(amount:Decimal):Boolean;
  property Balance:Decimal read fbalance;
  method ToString:String;override;
 end;
 GoldAccount=class(IBankAccount)
 private
  fbalance:Decimal;
 public
  method PayIn(amount:Decimal);
  method Withdraw(amount:Decimal):Boolean;
  property Balance:Decimal read fbalance;
  method ToString:String;override;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 var venusAccount:IBankAccount := new SaverAccount();
 var jupiterAccount:IBankAccount := new GoldAccount();
 venusAccount.PayIn(200);
 venusAccount.Withdraw(100);
 Console.WriteLine(venusAccount.ToString());
 jupiterAccount.PayIn(500);
 jupiterAccount.Withdraw(600);
 jupiterAccount.Withdraw(100);
 Console.WriteLine(jupiterAccount.ToString());
 console.ReadLine;
end;

method SaverAccount.PayIn(amount:Decimal);
begin
 fbalance:=fbalance+amount;
end;

method SaverAccount.Withdraw(amount:Decimal): Boolean;
begin
 if (fbalance >= amount) then
 begin
  fbalance:=fbalance-amount;
  result:=true;
  exit;
 end;
 Console.WriteLine("Withdrawal attempt failed.");
 result:=false;
end;

method SaverAccount.ToString: String;
begin
 Result:=String.Format("Venus Bank Saver: Balance = {0,6:C}", fbalance);
end;

//-----------GoldAccount-----------------------------------
method GoldAccount.PayIn(amount:Decimal);
begin
 fbalance:=fbalance+amount;
end;

method GoldAccount.Withdraw(amount:Decimal): Boolean;
begin
 if (fbalance >= amount) then
 begin
  fbalance:=fbalance-amount;
  result:=true;
  exit;
 end;
 Console.WriteLine("Withdrawal attempt failed.");
 result:=false;
end;

method GoldAccount.ToString: String;
begin
 Result:=String.Format("Jupiter Bank Saver: Balance = {0,6:C}", balance);
end;

end.

(略)

interface

type
 IBankAccount=interface
  method PayIn(amount:decimal);
  method Withdraw(amount:decimal):Boolean;
  property Balance:decimal read;
 end;
 BankAccount=class(IBankAccount)
 protected
  fbalance:Decimal;
 public
  method PayIn(amount:Decimal);
  method Withdraw(amount:Decimal):Boolean;
  property Balance:Decimal read fbalance;
 end;
 SaverAccount=class(BankAccount)
 public
  method ToString:String;override;
 end;
 GoldAccount=class(BankAccount)
 public
  method ToString:String;override;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
var
 BankAccount:IBankAccount;
begin
 BankAccount:= new SaverAccount();
 Console.WriteLine(BankAccount.GetType.ToString);
 BankAccount.PayIn(200);
 BankAccount.Withdraw(100);
 Console.WriteLine(BankAccount.ToString());
 BankAccount := new GoldAccount();
 Console.WriteLine(BankAccount.GetType.ToString);
 BankAccount.PayIn(500);
 BankAccount.Withdraw(600);
 BankAccount.Withdraw(100);
 Console.WriteLine(BankAccount.ToString());
 Console.ReadLine;
end;

method SaverAccount.ToString: String;
begin
 Result:=String.Format("Venus Bank Saver: Balance = {0,6:C}", fbalance);
end;

method GoldAccount.ToString: String;
begin
 Result:=String.Format("Jupiter Bank Saver: Balance = {0,6:C}", balance);
end;

method BankAccount.PayIn(amount:Decimal);
begin
 fbalance:=fbalance+amount;
end;

method BankAccount.Withdraw(amount:Decimal): Boolean;
begin
 if (fbalance >= amount) then
 begin
  fbalance:=fbalance-amount;
  result:=true;
  exit;
 end;
 Console.WriteLine("Withdrawal attempt failed.");
 result:=false;
end;

end.

//-----namespace--------------------

interface
 uses VenusBank,JupiterBank;

type
 IBankAccount=interface
  method PayIn(amount:decimal);
  method Withdraw(amount:decimal):Boolean;
  property Balance:decimal read;
 end;
 VenusBank.SaverAccount=class(IBankAccount)
 private
  fbalance:Decimal;
 public
  method PayIn(amount:Decimal);
  method Withdraw(amount:Decimal):Boolean;
  property Balance:Decimal read fbalance;
  method ToString:String;override;
 end;
 JupiterBank.GoldAccount=class(IBankAccount)
 private
  fbalance:Decimal;
 public
  method PayIn(amount:Decimal);
  method Withdraw(amount:Decimal):Boolean;
  property Balance:Decimal read fbalance;
  method ToString:String;override;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 var venusAccount:IBankAccount := new SaverAccount();
 var jupiterAccount:IBankAccount := new GoldAccount();
 venusAccount.PayIn(200);
 venusAccount.Withdraw(100);
 Console.WriteLine(venusAccount.ToString());
 jupiterAccount.PayIn(500);
 jupiterAccount.Withdraw(600);
 jupiterAccount.Withdraw(100);
 Console.WriteLine(jupiterAccount.ToString());
 console.ReadLine;
end;

method VenusBank.SaverAccount.PayIn(amount:Decimal);
begin
 fbalance:=fbalance+amount;
end;

method VenusBank.SaverAccount.Withdraw(amount:Decimal): Boolean;
begin
 if (fbalance >= amount) then
 begin
  fbalance:=fbalance-amount;
  result:=true;
  exit;
 end;
 Console.WriteLine("Withdrawal attempt failed.");
 result:=false;
end;

method VenusBank.SaverAccount.ToString: String;
begin
 Result:=String.Format("Venus Bank Saver: Balance = {0,6:C}", fbalance);
end;

method JupiterBank.GoldAccount.PayIn(amount:Decimal);
begin
 fbalance:=fbalance+amount;
end;

method JupiterBank.GoldAccount.Withdraw(amount:Decimal): Boolean;
begin
 if (fbalance >= amount) then
 begin
  fbalance:=fbalance-amount;
  result:=true;
  exit;
 end;
 Console.WriteLine("Withdrawal attempt failed.");
 result:=false;
end;

method JupiterBank.GoldAccount.ToString: String;
begin
 Result:=String.Format("Jupiter Bank Saver: Balance = {0,6:C}", balance);
end;

end

參考資料來源Professional C# 2008 Page 116.

4/20/2009

Constructors of Derived Classes 衍生類的建構式

在開始為層次結構中的類(這個類繼承了基底類,也可能有定制的建構式)定義自己的建構式時,會發生什麼情況?

假定沒有為類定義任何顯式的建構式,這樣編譯器就會為所有的類提供預設的建構式,在後臺會進行許多操作,編譯器可以很好地解決層次結構中的所有問題,每個類中的每個欄位都會初始化為預設值。但在添加了一個我們自己的建構式後,就要通過派生類的層次結構高效地控制建構過程,因此必須確保構造過程順利進行,不要出現不能按照層次結構進行建構的問題。

為什麼衍生類會有某些特殊的問題?原因是在創建衍生類的實例時,實際上會有多個建構式在起作用。實例化類的建構式本身不能初始化類,還必須調用基類中的建構式。這就是為什麼要通過層次結構進行建構的原因。

在C#呼叫基底類別的建構式用" 建構式() : base() ",在delphi prism呼叫基底類別則直接在方法裡"inherited constructor"。

interface

type
 GenericCustomer=class
 private
  name:String;
 public
  constructor;empty;
  constructor(name:String);
  method ShowName;virtual;
 end;
 Nevermore60Customer=class(GenericCustomer)
 private
  referrerName:String;
  highCostMinutesUsed:Integer;
 public
  constructor;empty;
  constructor(name,referrerName:String);
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 //var nc:=new Nevermore60Customer();
 var nc:=new Nevermore60Customer("pedro","jacky");
 nc.ShowName;
 Console.ReadLine;
end;

constructor GenericCustomer(name:String);
begin
 self.name:=name;
 Console.WriteLine("method GenericCustomer assign name= "+name);
end;

method GenericCustomer.ShowName;
begin
 //如果未經建構式constructor(name)初始化name,則會引發錯誤
 //Error:Object reference not set to an instance of an object.
 Console.WriteLine("name is "+name+" length = "+name.Length.ToString);
end;

constructor Nevermore60Customer(name,referrerName:String);
begin
 inherited constructor(name) ;
 self.referrerName:=referrerName;
 Console.WriteLine("method Nevermore60Customer assign referrerName = "+referrerName);
end;

end.

參考資料來源Professional C# 2008 Page 108

4/17/2009

Abstract Classes and Functions 抽象類和抽象方法

C#允許把類和方法聲明為abstract,抽象類不能實例化,而抽象方法沒有程式碼,必須在非抽象的衍生類中重寫。顯然,抽象方法也是虛擬的(但也不需要提供virtual關鍵字,實際上,如果提供了該關鍵字,就會產生一個語法錯誤)。如果類包含抽象方法,該類將也是抽象的,也必須聲明為抽象的。

C# allows both classes and functions to be declared as abstract. An abstract class cannot be instantiated, whereas an abstract function does not have an implementation, and must be overridden in any non -abstract derived class. Obviously, an abstract function is automatically virtual (although you don’t need to supply the virtual keyword; doing so results in a syntax error). If any class contains any abstract functions, that class is also abstract and must be declared.

interface

type
 CustomerAccount=abstract class
 public
  method CalculatePrice:double;virtual;abstract;
 end;
 GoldAccount=class(CustomerAccount)
 public
  method CalculatePrice:double;override;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 var gc:=new GoldAccount();
 Console.WriteLine(gc.CalculatePrice.ToString);
 Console.ReadLine;
end;

method GoldAccount.CalculatePrice: double;
begin
 result:=100*0.9;
end;

end.

參考資料來源Professional C# 2008 Page 106

4/16/2009

Inheritance 繼承: Calling Base Versions of Functions

表示一個類型繼承於一個基底類型,擁有該基底類型的所有成員變數和函式。在實現繼承中,衍生類型的每個函式繼承基底類型的程式碼,除非在衍生類型的定義中指定重寫該函式的程式碼。在需要給現有的類型添加功能,或許多相關的類型共用一組重要的公用功能時,這種類型的繼承是非常有用的。在C#,衍生類函式裡要使用基底類別的函式,用用"基底類別.函式名",在delphi prism裡,可用"inherited 函式名 "去呼叫。

C# has a special syntax for calling base versions of a method from a derived class: base. < MethodName > () . For example, if you want a method in a derived class to return 90 percent of the value returned by the base class method, you can use the following syntax:

interface

type
 CustomerAccount=class
 private
 public
  method CalculatePrice:double;virtual;
 end;
 GoldAccount=class(CustomerAccount)
 private
 public
  method CalculatePrice:double;override;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 var gc:=new GoldAccount();
 Console.WriteLine(gc.CalculatePrice.ToString);
 Console.ReadLine;
end;

method CustomerAccount.CalculatePrice: double;
begin
 result:=100;
end;

method GoldAccount.CalculatePrice: double;
begin
 result:=inherited*0.9;
end;

end.

class MainEntryPoint
{
 static void Main()
 {
  GoldAccount gc = new GoldAccount();
  decimal d = gc.CalculatePrice();
  Console.WriteLine(d.ToString());
  Console.ReadLine();
 }
}

class CustomerAccount
{
 public virtual decimal CalculatePrice()
 {
  return 100M;
 }
}

class GoldAccount : CustomerAccount
{
 public override decimal CalculatePrice()
 {
  return base.CalculatePrice() * 0.9M;
 }
}

參考資料來源Professional C# 2008 Page 106

4/15/2009

覆寫 ToString 方法

C# 中的每個物件都會繼承 ToString 方法,這個方法會傳回代表物件的字串。例如,型別 int 的所有變數都有 ToString 方法,使其能夠以字串的形式傳回本身的內容。

type
 Money=class
 private
  famount:Decimal;
 public
  property Amount:Decimal read famount write famount;
  method ToString: String; override;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 var cash1 := new Money();
 cash1.Amount := 40;
 Console.WriteLine("cash1.ToString() returns: " + cash1.ToString);
 Console.ReadLine;
end;

method Money.ToString: String;
begin
 result:="$" + Amount.ToString;
end;

end.

class MainEntryPoint
{
 static void Main(string[] args)
 {
  Money cash1 = new Money();
  cash1.Amount = 40M;
  Console.WriteLine("cash1.ToString() returns: " + cash1.ToString());
  Console.ReadLine();
 }
}

class Money
{
 private decimal amount;
 public decimal Amount
 {
  get
  {
   return amount;
  }
  set
  {
   amount = value;
  }
 }

 public override string ToString()
 {
  return "$" + Amount.ToString();
 }
}

參考資料來源Professional C# 2008 Page 99

4/14/2009

Static Classes 靜態類別

靜態類別和類別成員可用來建立資料和函式,讓您無須建立類別的執行個體,即可存取這些資料和函式。靜態類別成員可將資料和行為分隔開來,獨立於任何物件識別以外,也就是說,無論物件受到什麼影響,資料和函式都不會變更。當類別中沒有資料或行為相依於物件識別時,就可以使用靜態類別。

將類別宣告為靜態時,表示其中只包含靜態成員。您不能使用new關鍵字建立靜態類別的執行個體。當載入包含靜態類別的程式或命名空間時,.NET Framework Common Language Runtime (CLR)也會自動載入這些類別。請使用靜態類別來包含未與特定物件關聯的方法。

If a class contains nothing but static methods and properties, the class itself can become static. A static class is functionally the same as creating a class with a private static constructor.
An instance of the class can never be created. By using the static keyword, the compiler can help by checking that instance members are never accidentally added to the class. If they are, a compile error happens.This can help guarantee that an instance is never created.

interface
 uses System.Drawing;

type
 Dimensions=Partial static class
 public
  class var
  Length:Double:=20;
  Width:Double:=20;
  class method Diagonal:Double;
 end;
 Dimensions=Partial static class
 public
  class method Area:Double;
 private
  class constructor;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 //Type Dimensions does not provide an accessible constructor
 //var point:=new Dimensions;
 var D := Dimensions.Diagonal;
 Console.WriteLine(D.ToString());
 var A := Dimensions.Area;
 Console.WriteLine(A.ToString());
 Console.ReadLine;
end;

class method Dimensions.Diagonal: Double;
begin
 result:=Math.Sqrt(Length * Length + Width * Width);
end;

class constructor Dimensions;
begin
 Length:=20;
 Width:=20;
end;

class method Dimensions.Area: Double;
begin
 result:=Length*Width;
end;

end.

參考資料來源Professional C# 2008 Page 96

4/13/2009

Partial Classes 部分類別

您可以分割類別或結構的定義,或將一個介面分割為兩個以上的原始程式檔。每個原始程式檔都會包含一段類別定義,當編譯應用程式時,再將所有部分結合起來。適合分割類別定義的情況包括:
(1)處理大型專案時,可以將類別分割成幾個檔案,讓多位程式設計人員同時進行工作。
(2)使用自動產生的原始檔時,可以將程式碼加入至類別中,而無須重新建立原始程式檔。
(3)若要分割類別定義,請使用partial關鍵字修飾詞

type
 Dimensions=Partial class
 public
  Length:Double;
  Width:Double;
  method Diagonal:Double;
 end;
 Dimensions=Partial class
 public
  method Area:Double;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
var
 point:Dimensions:=new Dimensions;
begin
 point.Length := 3;
 point.Width := 6;
 var D := point.Diagonal;
 Console.WriteLine(D.ToString());
 var A := point.Area;
 Console.WriteLine(A.ToString());
 Console.ReadLine;
end;

method Dimensions.Diagonal: Double;
begin
 result:=Math.Sqrt(Length * Length + Width * Width);
end;

method Dimensions.Area: Double;
begin
 result:=Width*Length;
end;

end.

參考資料來源Professional C# 2008 Page 95

4/10/2009

struct 結構

struct型別是實值型別,通常用來封裝相關變數的小群組,例如,矩形的座標或庫存中某個項目的特性。在delphi prism用record關鍵字來宣告。

interface
uses System.Drawing;

type
 Dimensions=record
 public
  Length:Double;
  Width:Double;
  method Diagonal:Double;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
var
 point:Dimensions;
begin
 point.Length := 3;
 point.Width := 6;
 var D := point.Diagonal;
 Console.WriteLine(D.ToString());
 Console.ReadLine;
end;

method Dimensions.Diagonal: Double;
begin
 result:=Math.Sqrt(Length * Length + Width * Width);
end;

end.

struct Dimensions
{

 public double Length;
 public double Width;
 public double Diagonal
 {
  get
  {
   return Math.Sqrt(Length * Length + Width * Width);
  }
 }
}

class MainEntryPoint
{
 static void Main(string[] args)
 {
  Dimensions point;
  point.Length = 3;
  point.Width = 6;
  Double D = point.Diagonal;
  Console.WriteLine(D.ToString());
  Console.ReadLine();
 }
}

參考資料來源Professional C# 2008 Page 93

4/9/2009

Anonymous types 匿名型態

匿名型態允許開發人員在程式內簡單地定義沒有型別的變數,而不用在編譯階段中固定型態的變數,匿名類型在使用LINQ做查詢時,將可以應用在結果資料的動態轉換。匿名型態內參數型態完成相同時,也可以做運算處理。

Anonymous types are inline defined types to group related values together in a single block. An anonymous type can only be used inside the body of a method. Defining an anonymous type is as simple as using new class or new record.

class method ConsoleApp.Main;
begin
 var lUser := new class(Name: String := 'Peter', Age: Double := 49);
 Console.WriteLine(lUser.GetType.ToString);
 Console.WriteLine(lUser.Name+' is ' + lUser.Age + ' years old');
 Console.ReadLine;
end;

static void Main(string[] args)
{
 var lUser = new {Name = "Peter", Age = 49};
 Console.WriteLine(lUser.GetType().ToString());
 Console.WriteLine(lUser.Name + " is " + lUser.Age + " years old");
 Console.ReadLine();
}

參考資料來源Professional C# 2008 Page 91

4/8/2009

靜態變數

在c#裡宣告變數時, 前面加上"static"修飾字, 表示此變數為靜態變數。在delphi prism裡,用class var來宣告。靜態變數可由靜態建構式去做變數的初始化,在類別被載入記憶體時,初始化這些靜態成員變數。

One reason for writing a static constructor is if your class has some static fields or properties that need to be initialized from an external source before the class is first used.
The .NET runtime makes no guarantees about when a static constructor will be executed, so you should not place any code in it that relies on it being executed at a particular time (for example, when an assembly is loaded). Nor is it possible to predict in what order static constructors of different classes will execute. However, what is guaranteed is that the static constructor will run at most once, and that it will be invoked before your code makes any reference to the class. In C#, the static constructor usually seems to be executed immediately before the first call to any member of the class.

interface

type
 MyNumber=class
 private
  FNumber:Integer;
  public class var
  //把這個欄位宣告為唯讀類型,表示其值只能在建構式中設置
  PI:Double; readonly;
 public
  class constructor;
  constructor;
  constructor(number:Integer);
  property Number:Integer read FNumber write FNumber;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 var number:=new MyNumber();
 console.WriteLine("{0}",number.Number);
 console.WriteLine("{0}",MyNumber.PI);
 console.ReadLine;
end;

constructor MyNumber(number:Integer);
begin
 FNumber:=number;
end;

constructor MyNumber;
begin
end;

class constructor MyNumber;
begin
 PI:=3.141592654;
end;

end.

public class MyNumber
{
 private int fnumber;
 public MyNumber(int number)
 {
  this.fnumber = number;
 }
 public int number
 {
  get { return fnumber; }
  set { fnumber = value; }
 }
 public static double PI;
 static MyNumber()
 {
  PI = 3.141592654;
 }
}

class ConstructorTest
{
 static void Main(string[] args)
 {
  MyNumber number = new MyNumber(20);
  Console.WriteLine("{0}", number.number);
  Console.WriteLine("{0}", MyNumber.PI);
  Console.ReadLine();
 }
}

The next example illustrates the use of a static constructor and is based on the idea of a program that has user preferences (which are presumably stored in some configuration file). To keep things simple, we'll assume just one user preference — a quantity called BackColor , which might represent the background color to be used in an application. And because we don't want to get into the details of writing code to read data from an external source here, we'll make the assumption that the preference is to have a background color of red on weekdays and green on weekends.

interface
 uses System.Drawing;

type
 UserPreferences=public class
 public
  class var BackColor:Color; readonly;
  class constructor;
  constructor;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 Console.WriteLine("User-preferences: BackColor is: " +
  UserPreferences.BackColor.ToString());
 console.ReadLine;
end;

class constructor UserPreferences;
begin
 var now := DateTime.Now;
 if (now.DayOfWeek = DayOfWeek.Saturday) or (now.DayOfWeek = DayOfWeek.Sunday) then
  BackColor := Color.Green
 else
  BackColor := Color.Red;
end;

constructor UserPreferences;
begin
end;

end.

using System.Drawing;
public class UserPreferences
{
 public static readonly Color BackColor;
 static UserPreferences()
 {
  DateTime now = DateTime.Now;
  if (now.DayOfWeek == DayOfWeek.Saturday || now.DayOfWeek == DayOfWeek.Sunday)
   BackColor = Color.Green;
  else
   BackColor = Color.Red;
 }
 private UserPreferences()
 {
 }
}

class MainEntryPoint
{
 static void Main(string[] args)
 {
  Console.WriteLine("User-preferences: BackColor is: " +UserPreferences.BackColor.ToString());
  Console.ReadLine();
 }
}

參考資料來源Professional C# 2008 Page 87

靜態變數

在c#裡宣告變數時, 前面加上"static"修飾字, 表示此變數為靜態變數。在delphi prism裡,用class var來宣告。靜態變數可由靜態建構式去做變數的初始化,在類別被載入記憶體時,初始化這些靜態成員變數。

One reason for writing a static constructor is if your class has some static fields or properties that need to be initialized from an external source before the class is first used. The .NET runtime makes no guarantees about when a static constructor will be executed, so you should not place any code in it that relies on it being executed at a particular time (for example, when an assembly is loaded). Nor is it possible to predict in what order static constructors of different classes will execute. However, what is guaranteed is that the static constructor will run at most once, and that it will be invoked before your code makes any reference to the class. In C#, the static constructor usually seems to be executed immediately before the first call to any member of the class.

interface

type
 MyNumber=class
 private
  FNumber:Integer;
 public class var
  //把這個欄位宣告為唯讀類型,表示其值只能在建構式中設置
  PI:Double; readonly;
 public
  class constructor;
  constructor;
  constructor(number:Integer);
  property Number:Integer read FNumber write FNumber;
 end;

 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 var number:=new MyNumber();
 console.WriteLine("{0}",number.Number);
 console.WriteLine("{0}",MyNumber.PI);
 console.ReadLine;
end;

constructor MyNumber(number:Integer);
begin
 FNumber:=number;
end;

constructor MyNumber;
begin
end;

class constructor MyNumber;
begin
 PI:=3.141592654;
end;

end.

public class MyNumber
{
 private int fnumber;
 public MyNumber(int number)
 {
  this.fnumber = number;
 }
 public int number
 {
  get { return fnumber; }
  set { fnumber = value; }
 }
 public static double PI;
 static MyNumber()
 {
  PI = 3.141592654;
 }
}

class ConstructorTest
{
 static void Main(string[] args)
 {
  MyNumber number = new MyNumber(20);
  Console.WriteLine("{0}", number.number);
  Console.WriteLine("{0}", MyNumber.PI);
  Console.ReadLine();
 }
}

The next example illustrates the use of a static constructor and is based on the idea of a program that has user preferences (which are presumably stored in some configuration file). To keep things simple, we'll assume just one user preference — a quantity called BackColor , which might represent the background color to be used in an application. And because we don't want to get into the details of writing code to read data from an external source here, we'll make the assumption that the preference is to have a background color of red on weekdays and green on weekends.

interface
 uses System.Drawing;

type
 UserPreferences=public class
 public
  class var BackColor:Color; readonly;
  class constructor;
  constructor;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 Console.WriteLine("User-preferences: BackColor is: " +UserPreferences.BackColor.ToString());
 console.ReadLine;
end;

class constructor UserPreferences;
begin
 var now := DateTime.Now;
 if (now.DayOfWeek = DayOfWeek.Saturday) or (now.DayOfWeek = DayOfWeek.Sunday) then
  BackColor := Color.Green
 else
  BackColor := Color.Red;
end;

constructor UserPreferences;
begin
end;

end.

using System.Drawing;
public class UserPreferences
{
 public static readonly Color BackColor;
 static UserPreferences()
 {
  DateTime now = DateTime.Now;
  if (now.DayOfWeek == DayOfWeek.Saturday || now.DayOfWeek == DayOfWeek.Sunday)
   BackColor = Color.Green;
  else
   BackColor = Color.Red;
 }
 private UserPreferences()
 {
 }
}
class MainEntryPoint
{
 static void Main(string[] args)
 {
  Console.WriteLine("User-preferences: BackColor is: " +UserPreferences.BackColor.ToString());
  Console.ReadLine();
 }
}

參考資料來源Professional C# 2008 Page 87

4/7/2009

建構式

如果類別沒有預設建構函式,就會自動產生一個建構函式並使用預設值初始化物件欄位。例如Integer會初始化為 0,物件變數會初始為null。

如果要自定一個含有參數的建構式,在C#裡,便無法使用零參數的建立物件,在prism裡,至少要實作零參數的建構式之後,才能再定義含有參數的建構式。

如果提供了帶參數的建構式,編譯器就不會自動提供默認的建構式,只有在沒有定義任何建構式時,編譯器才會自動提供默認的建構式。

In general, if you don't supply any constructor, the compiler will just make up a default one for you behind the scenes. It will be a very basic constructor that just initializes all the member fields by zeroing them out however, that if you supply any constructors that take parameters, the compiler will not automatically supply a default one. This is done only if you have not defined any constructors at all. In the following example, because a one - parameter constructor is defined, the compiler assumes that this is the only constructor you want to be available, so it will not implicitly supply any others.

interface

type
 MyNumber=class
 private
  FNumber:Integer;
 public
  //constructor;
  //There is no overloaded constructor with 0 parameters for class
  constructor(number:Integer);
  property Number:Integer read FNumber write FNumber;
 end;
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 var number:=new MyNumber();
 console.WriteLine("{0}",number.Number);
 console.ReadLine;
end;

constructor MyNumber(number:Integer);
begin
 FNumber:=number;
end;

{
constructor MyNumber;
begin
end;
}

end.

namespace Chapter3
{
 public class MyNumber
 {
  private int fnumber;
  public MyNumber(int number)
  {
   this.fnumber = number;
  }
  public int number
  {
   get { return fnumber; }
   set { fnumber=value; }
  }
 }
 class ConstructorTest
 {
  static void Main(string[] args)
  {
   //error MyNumber 不包含使用0引數的建構函式
   //MyNumber number = new MyNumber();
   MyNumber number = new MyNumber(20);
   Console.WriteLine("{0}", number.number);
   Console.ReadLine();
  }
 }
}

參考資料Professional C# 2008 Page 86

4/6/2009

property 屬性

屬性的概念是,它使用一個函式或一對函式,在client呼叫端看來,它們是一個欄位。類似於設置一個欄位,但實際上是調用了屬性訪問器。訪問器可指定函式來處理屬性值讀取及設定時,加以處理的動作。屬性,定義中省略set訪問器,就可以創建唯讀屬性(delphi_prism可由read或write修飾子去決定屬性唯讀或唯寫),不特別指定時,就是使用自動實現的屬性,這種屬性會自動實現成員變數。

The idea of a property is that it is a method or pair of methods that are dressed to look like a field as far as any client code is concerned. The code looks like you're setting a field, but in fact you are calling a property accessor that contains code to.  The get accessor takes no parameters and must return the same type as the declared property. You should not specify any explicit parameters for the set accessor either, but the compiler assumes it takes one parameter, which is of the same type again, and which is referred to as value .

namespace ConsoleApplication2;

interface

type
 Bunny=public class
 //const //static constant
 //ForceName="Bunny";
 private
  FName:String;
  //FAge:Integer;
  //FIsRabbit:Boolean;
  //method GetForceName:String;
 public
  property Name:string read FName write FName;
  //Auto - implemented properties implement the backing member variable automatically.
  //The declaration private Integer Age; is not needed. The compiler will create this automatically.
  property Age:Integer;
  property IsRabbit:Boolean;
  //It is possible to create a read - only property by simply omitting the write accessor from the property
  //definition.
  //property ForceName:String read GetForceName;
  public method DoBirthday();
 end;
 
 ConsoleApp = class
 public
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
var
 bunny1:Bunny;
begin
 bunny1 := new Bunny();
 bunny1.Name := "Fred";
 bunny1.Age := 25;
 bunny1.IsRabbit := true;
 //Console.WriteLine(bunny1.ForceName); // call read only property
 if (bunny1.IsRabbit) then
 begin
  Console.WriteLine("The rabbit's name is " + bunny1.Name);
  Console.WriteLine("The rabbit's age is " + bunny1.Age.ToString());
 end;
 var bunny2 := new Bunny();
 bunny2.Name:="George";
 bunny2.Age:=30;
 bunny2.IsRabbit:=bunny1.IsRabbit;
 if (bunny2.IsRabbit) then
 begin
  Console.WriteLine("The rabbit's name is " + bunny2.Name);
  Console.WriteLine("The rabbit's age is " + bunny2.Age.ToString());
 end;
 Console.WriteLine("Bunny1 is type " + bunny1.GetType().ToString());
 Console.WriteLine("Bunny2 is type " + bunny2.GetType().ToString());
 bunny1.DoBirthday();
 Console.WriteLine("Bunny1 is now " + bunny1.Age.ToString());
 bunny1.DoBirthday();
 Console.WriteLine("Bunny1 is now " + bunny1.Age.ToString());
 console.ReadLine;
end;

method Bunny.DoBirthday();
begin
 Inc(Age);
end;

namespace Chapter3
{
 class PropertiesTest
 {
  static void Main(string[] args)
  {
   Bunny bunny1 = new Bunny();
   bunny1.Name = "Fred";
   bunny1.Age = 25;
   bunny1.IsRabbit = true;
   if (bunny1.IsRabbit)
   {
    Console.WriteLine("The rabbit's name is " + bunny1.Name);
    Console.WriteLine("The rabbit's age is " + bunny1.Age.ToString());
   }
   var bunny2 = new { Name = "George", Age = 30, IsRabbit = bunny1.IsRabbit };
   if (bunny2.IsRabbit)
   {
    Console.WriteLine("The rabbit's name is " + bunny2.Name);
    Console.WriteLine("The rabbit's age is " + bunny2.Age.ToString());
   }
   Console.WriteLine("Bunny1 is type " + bunny1.GetType().ToString());
   Console.WriteLine("Bunny2 is type " + bunny2.GetType().ToString());
   bunny1.DoBirthday();
   Console.WriteLine("Bunny1 is now " + bunny1.Age.ToString());
   bunny1.DoBirthday();
   Console.WriteLine("Bunny1 is now " + bunny1.Age.ToString());
   Console.ReadLine();
  }
 }
 public class Bunny
 {
  public string Name { get; set; }
  public int Age { get; set; }
  public bool IsRabbit { get; set; }
  public void DoBirthday()
  {
   this.Age += 1;
  }
 }
}

//The rabbit's name is Fred

//The rabbit's age is 25

//The rabbit's name is George

//The rabbit's age is 30

//Bunny1 is type Chapter3.Bunny

//Bunny2 is type <>f__AnonymousType0`3[System.String,System.Int32,System.Boolean]

//Bunny1 is now 26

//Bunny1 is now 27

參考資料來源Professional C# 2008 Page 83

4/4/2009

Method Overloading 重載

C#支援函式的重載--函式的幾個有不同簽名(函式名相同、但參數的個數和類型不同)的版本,為了重載方法,只需聲明同名但參數個數或類型不同的函式即可。C#不允許使用預設的參數值,但Delphi Prism可使用預設參數值

C# supports method overloading — several versions of the method that have different signatures (that is, the same name, but a different number of parameters and or different parameter data types).
C# does not support optional parameters, you will need to use method overloading to achieve the same effect.  As in any language, method overloading carries with it the potential for subtle runtime bugs if the wrong overload is called.

namespace ConsoleApplication2;

interface

type
 ConsoleApp = class
 public
  class method DisplayValue(i:Integer);
  class method DisplayValue(s:String);
  class method DisplayValue(i:Integer;k:string:='20');
  class method Main;
 end;

implementation

class method ConsoleApp.Main;
begin
 DisplayValue(22);
 console.ReadLine;
end;

class method ConsoleApp.DisplayValue(i:Integer);
begin
 Console.WriteLine("i value is "+i.ToString);
end;

class method ConsoleApp.DisplayValue(i:Integer;k:string:='20');
begin
 Console.WriteLine("i value is "+i.ToString+' and k is '+k);
end;

class method ConsoleApp.DisplayValue(s:String);
begin
 Console.WriteLine("s value is "+s);
end;

end.

namespace Wrox.ProCSharp.ParameterTestSample
{
 class OptionalParameterTest
 {
  static void DisplayValue(Int32 i)
  {
   Console.WriteLine("i value is " + i.ToString());
   // want 2nd parameter with default value "20"
   DisplayValue(i, "20");
  }
  //不允許使用預設的參數規範
  /*static void DisplayValue(Int32 i,String k="20")
  {
   // implementation
  }*/
  static void DisplayValue(Int32 i, String k)
  {
   Console.WriteLine("i value is " + i.ToString());
  }
  static void DisplayValue(String s)
  {
   Console.WriteLine("s value is " + s);
  }
  public static int Main()
  {
   DisplayValue(22);
   Console.ReadLine();
   return 0;
  }
 }
}

參考資料來源 Professional C# 2008 Page 82

4/1/2009

Passing Parameters to Methods 給函式傳遞參數

參數可以通過引用或值傳遞給函式。在變數通過引用傳遞給函式時,被調用的函式得到的就是這個變數,所以在函式內部對變數進行的任何改變在函式退出後仍舊發揮作用。而如果變數是通過值傳送給函式的,被調用的函式得到的是變數的一個副本,也就是說,在函式退出後,對變數進行的修改會丟失。對於複雜的資料類型,按引用傳遞的效率更高,因為在按值傳遞時,必須複製大量的資料。

In general, parameters can be passed into methods by reference or by value. When a variable is passed by reference, the called method gets the actual variable — so any changes made to the variable inside the method persist when the method exits. But, when a variable is passed by value, the called method gets an identical copy of the variable — which means any changes made are lost when the method exits. For complex data types, passing by reference is more efficient because of the large amount of data that must be copied when passing by value.

interface

type
 ConsoleApp = class
 public
  class method Main;
  class method SomeFunction(ints:Array of Integer;i:Integer);
 end;

implementation

class method ConsoleApp.Main;
begin
 var i := 0;
 var ints:Array[0..4] of Integer:=[0, 1, 2, 4, 8];
 // Display the original values
 Console.WriteLine("i = " + i);
 Console.WriteLine("ints[0] = " + ints[0]);
 Console.WriteLine("Calling SomeFunction...");
 // After this method returns, ints will be changed,
 // but i will not
 SomeFunction(ints, i);
 Console.WriteLine("i = " + i);
 Console.WriteLine("ints[0] = " + ints[0]);
 Console.ReadLine();
end;

class method ConsoleApp.SomeFunction(ints:Array of Integer;i:Integer);
begin
 ints[0] := 100;
 i := 100;
end;

end.

namespace Wrox.ProCSharp.ParameterTestSample
{
 class ParameterTest
 {
  static void SomeFunction(int[] ints, int i)
  {
   ints[0] = 100;
   i = 100;
  }
  //if an array or any other reference type, such as a class,
  //is passed into a method, and the method uses the reference to change a value in that array,
  //the new value is reflected in the original array object.
  public static int Main()
  {
   int i = 0;
   int[] ints = { 0, 1, 2, 4, 8 };
   // Display the original values.
   Console.WriteLine("i = " + i);
   Console.WriteLine("ints[0] = " + ints[0]);
   Console.WriteLine("Calling SomeFunction...");
   // After this method returns, ints will be changed,
   // but i will not.
   SomeFunction(ints, i);
   Console.WriteLine("i = " + i);
   Console.WriteLine("ints[0] = " + ints[0]);
   Console.ReadLine();
   return 0;
  }
 }
}

參考資料來源 Professional C# 2008 Page 80

3/22/2009

用簡單的辦法減少憂鬱

(飛碟電台一點關係,訪問林光強講師)

人生諸病,多生於鬱。很多人很容易心情不好,底下整理很簡單的技巧,照著去做,讓心情開始改變。江山易改,本性難移,別給自己找麻煩。

凡事到什麼地步,就照著什麼樣的地步去走,然後就會很愉快,順其自然一切都好。如果明明是這樣子,要給它弄彎的或弄直的,事實上違反天理。有些時候能力沒辦法解決的事情,時間是可以解決的,有些事情給它放一放,事緩則圓、曲則全(繞個彎,路就通了)。如果碰到綠燈,趕快走,碰到黃燈,就慢慢走,碰到紅燈就繞著走,反正總有辦法解決的。

下列方法可以馬上試試,結果截然不同

1.抬頭挺胸。心情不好的人第一個就會彎腰駝背、垂頭喪氣,當你挺胸的時候,氣就會很順。骨髓是人的氣血高速公路,你只要氣血一通,人自然心情就好了。所以你看過一個人上榜、中獎的時候,他就會很高興,抬頭挺胸。被讚美被肯定的時候,就會抬頭挺胸。心情不好的時候,挺胸心情才會更好。

2.能夠笑。癌症的人通常心情不好不會笑,病好了才會笑。錯!笑了以後,病才會好,心情越不好越要笑。當解決不了事情的時候,就笑,一笑解千愁,眉就開,心情就會放鬆。一笑,自己的免疫能力就會上升,心情就會開始開朗。不是你很愉快,你才會笑,其實人生遇到的事情,要真正影響一輩子的,大概只占百分之十,那麼真正影響你最大的,是你面對事情的態度。成功的人、失敗的人、快樂的人、痛苦的人遇到的事情都差不多,但是反應的方式不同,笑的時候就會很開心,心情就好了。

3. 曬太陽。幫助你心情非常愉快,不曬太陽,容易得憂鬱。如果可能,讓它流汗,幫助身體排毒。

4.拍掌。當你在鼓掌時候,情緒就會變的很快樂。一秒鐘拍兩下,慢慢地拍,氣血循環很好。一天的目標,拍到兩千下。在白天的曬太陽裡,一邊拍手,一邊走,赤腳走到草地上,接觸大自然,讓身體氣血循環,很有效。

5. 唱歌。如果一天可以唱到30分鐘的歌,心情就會好。

6. 吃排毒餐。吃蔬菜五殼雜量可以讓心情合協一致。

7. 朋友。有一群好朋友,什麼話都能講的朋友。

3/5/2009

Type Inference

Type Inference類型推斷,是由初次賦值時代入的變數值來決定變數型態。(和傳統的Variant型態不同)
Type Inference有以下的使用限制
1.需在函式內當區域變數使用
2.var 為關鍵字,依照後方給的變數值來決定資料型態
3.初始時就必須給值,不可空白或給 NULL
4.變數型態一經初始決定後,爾後再賦值時,只能儲存同型態的值
5.Type Inference可以指定陣列,但陣列的值必須為相同型態
Type inference makes use of the var keyword.The syntax for declaring the variable changes somewhat.  There are a few rules that you need to follow. The variable must be initialized. Otherwise, the compiler doesn't have anything to infer the type from.
The initializer cannot be null, and the initializer must be an expression. Once the variable has been declared and the type inferred, the variable's type cannot be changed. This is unlike the Variant type.

class methodConsoleApp.Main;
begin
 var name := "王小美";
 var age := 28;
 var isWoman := true;
 //var ErrCase := nil;//cannot assign <nil> to unknowntype
 var nameType := name.GetType();
 var ageType := age.GetType();
 var isWomanType := isWoman.GetType();
 Console.WriteLine("name is type "+ nameType.ToString());
 Console.WriteLine("age is type "+ ageType.ToString());
 Console.WriteLine("isWoman is type" + isWomanType.ToString());
 {//error cannot assignSystem.String to System.Int32
 //因為age已經是System.Int32了就不能再給它賦一個System.String類型的值
 age:='25';
 ageType := age.GetType();
 Console.WriteLine("now age is type" + ageType.ToString());}
 Console.ReadLine;
end;

執行結果
name is type System.String
age is type System.Int32
isWoman is type System.Boolean

完整範例可在此取得

本文參考資料
http://richielin-programer.blogspot.com/2008/02/visual-c-30.html Visual C#3.0 新語法筆記
Professional C# 2008 (Wrox) Page 91

2/15/2009

雙秀濟州趣四日

(印地安旅行社)

時間:2/20~2/23
團成員17女2男

已經八年沒坐過飛機出國去玩,以前去東京兩次及沙巴一次,這次將前往濟州。很興奮及期待,如果有去過的朋友,請留言建議我值得購買回來貨品,謝謝.

預計行程
第1天:
 台北->濟州 復興航空 GE – 862 07:25 / 10:15
 台北/濟州~神奇之路~盆栽園~龍頭岩~自然史博物館~傳統泡菜館+韓服寫真~亂打秀
 早餐:X 午餐:石鍋拌飯+涮涮鍋 晚餐:人蔘鷄餐(含人蔘酒及長壽麵)
 住宿:CITY CON HOTEL或同級

第2天:
 泰迪熊博物館~摩托車表演秀~松嶽山~將軍石~藥泉寺~樂天賭場+風車城~中央地下商場
 早餐:早餐外用鮑魚粥 午餐:什錦菇類養生鍋 晚餐:海鮮火鍋
 住宿:CITYCON HOTEL或同級

第3天:
 城邑民俗村~城山日出峰~橘子園~人蔘專賣店~真珠草~騎馬體驗營~琴湖度假村(SPA水世界+卡拉OK)
 早餐:飯店外用 午餐:黑毛豬肉烤肉餐+當地小菜 晚餐:韓定食+青花魚
 住宿:琴湖渡假村(2人1戶)

第4天:
 化妝品~雜貨店~濟州/台北
 濟州->台 北 復興航空 GE – 861 11:10 / 12:00

2/9/2009

delphi prism語法--linq

linq是一種類似sql語法,可以在資料群裡,找到合乎條件的資料。
語法結構注意這一行 var AlbumsLastYear := from a in cabinet where a.Year.Equals('2008');
會取得屬於2008年發行專輯資料。

把form上貼上一個button、treeView元件,畫面如下:

prism20090209a

references加入System.Core及System.Data.Linq。

音樂櫃cabinet是用list<MusicAlbum>泛型方法建立一個清冊。程式碼如下:

namespace LinqEx20090209;

interface

uses
 System.Drawing,
 System.Collections,
 System.Collections.Generic,
 System.Windows.Forms,
 System.ComponentModel,
 System.Linq,
 System.Data.Linq;

type
 MainForm = partial class(System.Windows.Forms.Form)
 private
  method button1_Click_1(sender: System.Object; e: System.EventArgs);
 protected
  method Dispose(disposing: Boolean); override;
 public
  constructor;
 end;

 MusicCategory=enum(HipHop,Pop,Rap,Classical);

 MusicAlbum=class(System.Object)
 const
  CopyRight="版權所有,嚴禁複製";
 private
  fTitle:String;
  fYear:String;
  fCategory:MusicCategory;
  fSinger:String;
  method SetTitle(value:String);
  method SetCategory(value:MusicCategory);
 public
  property Title:String read fTitle write SetTitle;
  property Category:MusicCategory read fCategory write SetCategory;
  property Year:String read fYear write fYear;
  property Singer:String read fSinger write fSinger;
 end;

implementation

method MusicAlbum.SetTitle(value:String);
begin
 if value<>'' then
  Self.fTitle:=value;
end;

method MusicAlbum.SetCategory(value:MusicCategory);
begin
 self.fCategory:=value;
end;

method MainForm.button1_Click_1(sender: System.Object; e: System.EventArgs);
var
 album:MusicAlbum;
 cabinet:List<MusicAlbum>;
begin
 cabinet:=new List<MusicAlbum>;

 album:=new MusicAlbum;
 album.Category:=MusicCategory.Classical;
 album.Title:='收放自如';
 album.Singer:='李聖潔';
 album.Year:='2008';
 cabinet.Add(album);

 album:=new MusicAlbum;
 album.Category:=MusicCategory.Pop;
 album.Title:='Magik Great Hits新歌+精選';
 album.Singer:='吳克群';
 album.Year:='2008';
 cabinet.Add(album);

 var AlbumsLastYear := from a in cabinet where a.Year.Equals('2008'); //注意這一行
 treeView.Nodes.Clear;
 for a in AlbumsLastYear do
 begin
  var node:TreeNode:=treeView.Nodes.Add('專輯: '+a.Title);
  node.Nodes.Add('歌手: '+a.Singer);
  node.Nodes.Add('年份: '+a.Year);
  node.Nodes.Add('類別: '+a.Category.ToString);
  node.Nodes.Add('版權宣告: '+a.CopyRight);
 end;
 treeView.ExpandAll;
end;

end.

執行結果如下

prism20090209b

在此取得完整範例

 

2/8/2009

如何把clipboard裡的文字,貼到notepad裡?

這次我把網友以C#回覆我在ktop詢問"如何把文字貼到別的應用程式視窗"的問題,用delphi語法練習一次

在新form建立如下畫面,放一個label、textBox、process、兩個button元件,並填好name及text屬性。

prism20090208a

相關程式碼如下:

uses
 System.Drawing,
 System.Collections,
 System.Collections.Generic,
 System.Windows.Forms,
 System.ComponentModel,
 System.Diagnostics,
 Microsoft.VisualBasic,
 Microsoft.VisualBasic.Devices;

type
 MainForm = partial class(System.Windows.Forms.Form)
 private
  method btnRunNotepad_Click(sender: System.Object; e: System.EventArgs);
  method btnCopyPaste_Click(sender: System.Object; e: System.EventArgs);
  method MainForm_FormClosed(sender: System.Object; e: System.Windows.Forms.FormClosedEventArgs);
 protected
  method Dispose(disposing: Boolean); override;
 public
  constructor;
 end;

implementation

method MainForm.btnRunNotepad_Click(sender: System.Object; e: System.EventArgs);
begin
 self.process1.Start;
end;

method MainForm.btnCopyPaste_Click(sender: System.Object; e: System.EventArgs);
begin
 if tbSource.Text<>"" then
 begin
  var textData:String := tbSource.Text;
  Clipboard.SetText(textData);
  var processes := Process.GetProcessesByName("notepad");
  for each p in processes do
  begin
   Interaction.AppActivate(p.Id); // 將應用程式設為Activate
   new Keyboard().SendKeys("^V"); //將按鍵傳送到Activate的應用程式
  end;
 end;
end;

method MainForm.MainForm_FormClosed(sender: System.Object; e: System.Windows.Forms.FormClosedEventArgs);
begin
 try
  Self.process1.CloseMainWindow;
 except
 end;
end;

end.

執行結果畫面如下:

prism20090208b

完整範例可在此取得

2/2/2009

初試DataSet Wizard的操作

1.New Project命名為BFFirstLook。

2.Server Explorer,在Data Connection處右鍵選Add Connection,挑Blackfish SQL (Blackfish SQL Local),Database設C:\Documents and Settings\All Users\Documents\Delphi Prism\Demos\database\databases\BlackfishSQL\employee.jds。UserName:sysdba,Password:masterkey。
3.Data Source頁Add New Data Source。選local. Employee。Yea,save connection as “employeeConnectionString”。DataSet Name: employeeDataSet。
prism20090202a

4.拖曳EMPLOYEE到MainForm,產生畫面如下:
prism20090202b

5. Server Explorer把Local.employee的Connection Close掉。

6.執行此專案,完整的資料表CRUD(增修刪)功能已建立。
prism20090202c

7.看一下delphi prism所產生的程式碼。
type

 MainForm = partial class(System.Windows.Forms.Form)
 private
  method EMPLOYEEBindingNavigatorSaveItem_Click(sender: System.Object; e: System.EventArgs);
  method MainForm_Load(sender: System.Object; e: System.EventArgs);
 protected
  method Dispose(disposing: Boolean); override;
 public
  constructor;
 end;

implementation

method MainForm.EMPLOYEEBindingNavigatorSaveItem_Click(sender: System.Object; e: System.EventArgs);
begin
 self.Validate();
 self.EMPLOYEEBindingSource.EndEdit();
 self.EMPLOYEETableAdapter.Update(self.employeeDataSet.EMPLOYEE);
end;

method MainForm.MainForm_Load(sender: System.Object; e: System.EventArgs);
begin
 // TODO: This line of code loads data into the 'employeeDataSet.EMPLOYEE' table. You can move, or remove it, as needed.
 self.EMPLOYEETableAdapter.Fill(self.employeeDataSet.EMPLOYEE);
end;

end.

完整範例在此取得

1/29/2009

程式上線的考驗

再三天就要過完今年農曆年假,面對新年度的工作,也許腦中開始蘊釀著新的熱情,也許舊年度的工作壓力還未全然釋放,我做了一個逼真的夢。關於工作的夢不多,底下的夢境好像為我新年度的工作暖身,告訴我不要再鬆懈(幾天下來賴了n天的床,睡得超飽的;吃撐了好多餐;看了好幾部片,真是幸福)。

我在擁擠及忙碌不堪的出貨中心的櫃台後面,櫃台前面擠滿了客戶。櫃台小姐正在打著訂單,我在緊叮著她打單,看電腦程式是否會出現狀況。在我身後的是主管,拿著碼表在計時,看電腦處理一張單據,需要花多久的時間?

整個緊繃的氣氛,小姐們個個專注在電腦螢幕後面,或有人拿個產品交付給客戶,遞上發票再收款並且致上謝謝光臨。

整個交易流程我是清楚的,從打訂單、收款、出貨到印發票,程式在哪個地方過帳扣庫存,在什麼環節佔用較多的時間大概心裡上有數。一般來說,如果網路環境和資料庫主機在多人運作的環境良好,大概剩下的就是程式裡資料處理的技巧夠不夠最佳化的問題。如果在主管視察時出現狀況,就得花時間解釋為何程式運作卡住或處理時間過長問題,並且可能質疑整個平台適用性的問題。此時就像舞者平常可能花了好幾年的時間,只為了台上那短暫幾分鐘巧妙的舞步,不小心的差錯就足以讓人否定平常一切的努力。

還好這位平常輸入品項的小姐手指靈活,三四十項品項在不到一分鐘時間內就輸入及存檔完畢,雖然當中還是有遇到產品的庫存量不足輸入不進去改換別的產品問題,不過大致上人員的訓練和程式處理速度獲得主管的肯定,應是通過此次的考驗。

我和主管離開了櫃台,結束這次的現場確認動作。一票人鬆了一口氣。