2013年5月23日星期四

C# in Depth(精通C#)

這是一本想更深入瞭解C#的人必讀的一本書。作者完整的交代了C#1.0到C#4.0之間的改變,這樣的寫法讓讀這本書有點像在念C#的歷史。書中詳細的說明C#每次改版新增了哪些功能,以及為什麼要新增這些功能,是為了解決什麼樣的問題。

我一直覺得要瞭解一個程式語言的語法最重要的事情就是瞭解語法的演進的過程。其實就像學習數學和物理一樣,只會死背公式是沒有用的。程式語言作者設計某種語法一定是有他的原因。如果我們不懂的背後設計的原由,就很難活用這個語法。學習程式語言另一個重要的事情是此語法實際的用途和例子,比如說使用某種語法可以改善程式的可讀性,讓程式看起來更精簡。這兩點作者都有完整的解釋,這也是這本書為什麼被這麼多人推薦的原因。

書中甚至提到一些compiler相關的東西,像是匿名型別compiler如何推論出正確的型別,LINQ和extension methods是如何被compiler轉譯。這些東西在其他C#的書幾乎沒有被解釋。雖然說不用懂這些也能寫程式,不過我相信要寫出好程式多瞭解這些東西是會有幫助的。

這本書雖然有中文版,但是我覺得翻譯不是很理想。在閱讀過程中常常可以看到錯字或缺字,句子翻譯起來不太通順(書中很常出現"然而"有點妨礙閱讀),甚至會有少翻的情況發生。因此還是建議有能力的讀者可以閱讀原文本。另外第二版沒有中文版是蠻可惜的,中文版只有介紹到C#3.0。

總而言之,這是一本C#的經典書籍,很適合學完基本語法後當C#的第二本書,看完之後一定會對C#有更深入的體認

最近看到C# in Depth要出第三版,內容涵蓋了C#5.0的語法。有興趣的人可以到Amazon網站注意出版訊息。

2013年5月20日星期一

在Visual Studio 2012的C++ Projects中設定target framework

Visual Studio 2012沒有UI可以設定C++ Project的Target Framework
唯一的方法就是去修改.vcxproj裡頭的TargetFrameworkVersion
可以用常用的文字編輯器直接把.vcxproj打開,直接修改TargetFrameworkVersion就可以了
C++ project新建立時候預設會使用v4.0,在.vcxproj裡頭有可能會找不到TargetFrameworkVersion
這時候可以自己加入TargetFrameworkVersion tag到PropertyGroup Globals中
下面是一個範例,此設定檔的Target Framework是v4.5
<PropertyGroup Label="Globals">
      ...
      <RootNamespace>...</RootNamespace>
      <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>

2013年5月7日星期二

[Python]如何disassemble Python程式碼

大家都知道Python程式碼會被編譯成Python bytecode並執行在Python的VM上。有沒有什麼方法可以把Python程式碼變成bytecode印出來呢?Python有個disassembler module可以幫助你把Python code轉成bytecode。
以下是一段範例。
>>> import dis
>>> def foo():
...     a = 1
...     b = 2
...     c = a + b
...
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)

  3           6 LOAD_CONST               2 (2)
              9 STORE_FAST               1 (b)

  4          12 LOAD_FAST                0 (a)
             15 LOAD_FAST                1 (b)
             18 BINARY_ADD
             19 STORE_FAST               2 (c)
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE
dis module中的dis method可以幫助你把Python code轉成byte code

2013年5月3日星期五

[C]#if和#else,切換程式碼的小技巧

在寫程式時當我們修改程式碼時通常會把舊有的程式碼註解起來,再加入新的程式碼。有沒有什麼方法能快速在新舊程式碼之間切換呢?C裡頭的#if和#else是一個好方法。下列是一個常見的新舊程式碼範例,我們用註解把程式碼分開:
                   
newCode();             
/*                     
someOtherCode();        
*/
/*  
newCode();             
*/                      
someOtherCode(); 
其實可以用C裡頭preprocessor的小技巧來快速切換程式碼
#if 1
newCode();  
#else
test(); /* FIXME: please don't to that. */
someOtherCode(); 
#endif    
#if 0
newCode();
#else
test(); /* FIXME: please don't to that. */
someOtherCode(); 
#endif    
如此一來我們只要切換1和0就可以快速切換不同區塊的程式碼,就算裡頭有註解也不用擔心
要註解一大塊程式碼也可以使用這個技巧
#if 0
newCode();
test();
#endid

2013年4月10日星期三

Static Typing, Dynamic Typing, Strong Typing, Weak Typing

Static Typing

如果一個程式語言中的每個變數型別在編譯時期就完全決定好,我們稱這個程式語言屬於static type。這類的程式語言在使用變數時通常都需要先宣告變數,編譯器會在編譯時期去做type checking。比如說Java, C, C++, C#。以下是一段C的範例:

int num, sum; // explicit declaration
num = 5; // now use the variables
sum = 10;
sum = sum + num;

變數使用前需要宣告是static type的特徵之一

Dynamic Typing

Dynamic type和static type相反,一個屬於dynamic type的程式語言不需要宣告變數,因此編譯器無法對型別做檢查在編譯時找出型別上的錯誤。在執行期間存取變數時,會透過適當的機制來判斷此變數可能的型別。Dynamic type不需要事先宣告變數就能直接使用,比如說Python, PHP, Ruby, Perl。以下是一段Python的範例程式:

sum = 1   // directly using the variable
sum += 2

上面的範例我們直接使用變數sum而沒有事先宣告,這是dynamic type的其中一個特徵。 簡單來說,Static typing會在編譯時去做type checking。而dynamic type會在run-time時做check。

Strong Typing

Strong typing很長會和static typing以及dynamic typing搞混。Strong typing是指變數會被綁定到某個型別,除非經過明顯的型別轉換,不然型別不會任意改變。比如說Python就是strong typing,以下是個範例:

>>> x = 3
>>> y = '4'
>>> print(x+y)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unsupported operand type(s) for +: 'int' and 'str'

Python不允許int和string相加,除非我們主動去做型別轉換,不然x和y變數不會經過隱藏的型別轉換加在一起。這就是Strong typing的主要特徵。Python是dynamic typing同時也是strong typing

Weak Typing

Weak typing是指型別的概念比較弱,變數的型別可能隨時會經過隱性的轉換。比如說JavaScript,以下是JavaScript的範例:

var x = 3    
var y = '4'
alert(x + y) //Produces "34"

不同於Python,JavaScript允許這種語法並且會自動幫你做型別轉換。這就是weak typing的特徵之一。

Strong Typing v.s. Weak Typing

其實這兩者並沒有一個約定成俗的定義,很多程式語言都同時有兩種的特性。只能說偏向某一邊比較多。比如說C,大部分人認為C偏向Weak Typing,因為C有pointer可以做任意轉型,同時也有void *這種變數可存取任意型別。

2013年4月9日星期二

Type-safe v.s. Type-Unsafe

某一些程式語言比較自由,允許我們去做一些危險的動作。比如說C和C++的Pointer就允許我們直接對記憶體做操作。這類的功能讓程式語言變得很強大,但是一不小心有可能會讓程式整個當掉。這種允許我們任意存取記憶體位置的程式語言就不能算是Type-safe。比如說以下的C程式讓我們access超過int boundary的位置:
int i = 10;
char *s = (char*)i;
print(*(s+10));
這種問題不會發生在C#身上,因為C#是Type-safe的程式語言。以下範例在C和C++合法,但是在C#會丟出錯誤訊息:
double d = 10.59; 
int i = 5; 
i = d; //this causes an Error
在C#中不能隨便把某個型別的資料當作是另外一種型別,如果編譯器認為這樣轉型是不合法的,在編譯的時候就會丟出錯誤。

[C#]Delegate

如果你有學過C,C#的delegate其實很類似C的function pointer。delegate讓我們可以把function透過參數的形式來傳遞,也就是說delegate可以讓我們把function當作first class opject來操作。下列是一個delegate的簡單範例:
using System;
delegate void StringProcessor(string input);
class Person
{
    string name;
    public Person(string name) { this.name = name; }
    public void Say(string message)
    {
        Console.WriteLine("{0} says: {1}", name, message);
    }
}

class SimpleDelegateUse
{
    static void Main()
    {
        Person jon = new Person("Jon");
        Person tom = new Person("Tom");
        StringProcessor jonsVoice, tomsVoice;
        jonsVoice = new StringProcessor(jon.Say);
        tomsVoice = new StringProcessor(tom.Say);
        jonsVoice("Hello, son.");
        tomsVoice.Invoke("Hello, Daddy!");
    }
}
此範例中我們建立了宣告了兩個delegate的instance,分別是jonsVoice以及tomsVoice。最後用兩種不同的方式呼叫function
使用delegate要有以下三個步驟:

1. 宣告delegate type
delegate void StringProcessor(string input);
這行就是我們宣告delegate type的地方,這個delegate的type是含有一個string參數且回傳值為void的function。此delegate type只能接受回傳值以及參數個數一模一樣的function。不過有一種特殊情況:
void Test(object x);
此function也可以被assigned給此delegate的instance,因為string是繼承自object

2. 建立delegate instance
StringProcessor jonsVoice, tomsVoice;
jonsVoice = new StringProcessor(jon.Say);
用new可以建立剛才宣告好得delegate instance,建立傳入的參數是之後要透過delegate呼叫的function

3. 呼叫delegate instance的function

編譯之後會把jonsVoice("Hello, son.")轉成jonsVoice.Invoke("Hello, son.")
最後又會透過delegate呼叫原本assigned的function jon.Say("Hello, son.")

delegate很常用在UI Button的click,我們會事先宣告EventHandler的delegate instance。當button被按下時,執行對應的處理function。有點類似call back function。

每個delegate instance內部都有一個invocation list用來紀錄function,也就是說一個delegate instance可以紀錄不只一個function。當有多個function時,delegate會一一呼叫invocation list中所儲存的function。我們可以透過+=以及-=運算子來新增移除function。以下是個簡單的範例:

void HowAreYou(string sender) {
  Console.WriteLine("How are you, " + sender + '?');
}
 
void HowAreYouToday(string sender) {
  Console.WriteLine("How are you today, " + sender + '?');
}
 
Notifier greetMe;
 
greetMe = new Notifier(HowAreYou);
greetMe += new Notifier(HowAreYouToday);
 
greetMe("Leonardo");                      // "How are you, Leonardo?"
                                          // "How are you today, Leonardo?"
 
greetMe -= new Notifier(HowAreYou);
 
greetMe("Pereira");                       // "How are you today, Pereira?"

2013年4月3日星期三

[C#]快速讀取、寫入檔案的方法

C#提供一些快速的Method可以直接寫入或是讀取檔案,善用的話可以節省一些時間
以下三個static methods只需要一個步驟就可把資料從檔案讀到記憶體中,傳入參數都是讀取檔案的路徑
File.ReadAllText(path)                        // (回傳string)
File.ReadAllLines(path)                       // (回傳array of strings)
File.ReadAllBytes(path)                       // (回傳一個byte array)

下列四個static methods同樣只需要一個步驟就可把資料寫入到檔案中,傳入參數是路徑以及寫入的資料
File.WriteAllText(path, string)
File.WriteAllLines(path, array of strings)
File.WriteAllBytes(path, bytes)      
File.AppendAllText(path, string)              // (適合用在log file)
File.ReadAllLines和File.ReadLines看起來很像,但是ReadAllLines會一次把所有資料讀到記憶體中
ReadLines會回傳一個IEnumerable<string>,不會一次把所有資料讀到記憶體中

2013年4月2日星期二

如何讓Visual Studio 2012中compile的程式可在Windows XP上執行

最近發現一個問題,Visual Studio 2012預設並不支援Windows XP。也就是說Compile出來的程式沒辦法在XP上執行。花了一點時間上網找解決方法,發現微軟在去年年底出的Visual Studio 2012 Update 1已經可以支援XP了。程式開發人員可以在Visual Studio 2012上撰寫程式並compile成XP可執行的執行檔。

安裝好更新檔之後還需要設定專案所使用的toolset為Visual Studio 2012 – Windows XP (v110_xp)

詳細步驟如下:

1. 在Solution Explorer中的Project上按右鍵並點選Properties

2. 在左手邊樹狀目錄中選取Configuration Properties, General,把Platform Toolset property設定成Visual Studio 2012 – Windows XP (v110_xp)

3. 重新編譯後會產生可在XP上執行的執行檔

2013年3月28日星期四

無瑕的程式碼-敏捷軟體開發技巧守則 (Clean Code: A Handbook of Agile Software Craftsmanship)


最近發現Clean Code總算出中文翻譯書了,去書局翻了一下內容發現翻譯品質還不錯。害怕原文書的朋友們可以考慮買這本翻譯書。前陣子也看到O'reilly最近要出The Art of Readable Code的中文翻譯本,這本書和Clean Code主題類似,有興趣的人可以注意一下出版的消息。

很高興看到有越來越多好書被翻譯成中文,也希望未來能夠有更多經典書能被翻譯成中文讓更多人閱讀。

原文板的讀書心得和筆記如下:

心得 : Clean Code

筆記 :