2014年3月24日 星期一

Anonymous Types 用於重構的範例

今日與一位前輩從同時開發 Android 與 Windows Phone 的經驗上,撰寫 Java、C# 兩種語言的優缺點,最後聊到 Anonymous Types 的用處,該前輩指出他在撰寫 LINQ 時大量的使用了這種 C# 語言的技巧,這對沒有習慣使用 LINQ 的我而言真的算是上了一課,Anonymous Types 常被稱為匿名類別,與匿名函式一樣,顧名思義就是未實際定義名字的類別。

匿名函式 Anonymous Functions 大部份的同好都知道且很習慣使用這種語法,但知道 Anonymous Types 的人一定比知道 Anonymous Functions 的人少很多,所以這一直是我在幫公司面試資深工程師時,若考完 C# 筆試後的面談必問考題之一。

雖然從 C# 的書籍上看過這種語法,卻從來沒用過,實際上連 Anonymous Functions 我都很少用,原因無他,就是覺得每個東西都該取個名字程式才好讀,也有助於將 Function 的行數縮短。

Anonymous Types 有一個迷人的特性,雖然它的宣告方式很簡單,但在 Anonymous Types 中的成員皆是 Properties 而非一般的 Member Variable,所以它可以被用在 LINQ 的相關操作之中,但它不可以是 Function 的回傳值或參數,且之中的 Properties 是唯讀的,我們只能取得這個物件中的值,無法對其做修改。所以對非 LINQ 的用戶來說,匿名類別的使用情境較少,下午想了一下,發現 Anonymous Types 其實很適合用在一種需要重構的情境,請看看以下的程式片段

public Boolean IsValid(List<Item> items)
{
    const Int32 MAX_COUNT = 2000;
    const Int32 MIN_FEMALE_COUNT = 1000;
    const Int32 MAX_CHILDREN_COUNT = 200;

    Boolean bRes = false;

    if ( items.Count < MAX_COUNT )
    {
        if ( items.Where(item => item.Gender == 0).Count >= MIN_FEMALE_COUNT )
        {
            if ( items.Where(item => item. Age < 20).Count >= MAX_CHILDREN_COUNT )
            {
                bRes = true;
            }
        }
    }

    return bRes;
}

利用 Anonymous Types 即可將多個常數條件包裝成一個有意義的物件,不需要額外定義一個 Class 同時又具備唯讀的特性,對於增加程式碼的可讀性很有幫助

public Boolean IsValid(List<Item> items)
{
    var EventCondition = new { MaxCount = 2000,
                               MinFemaleCount = 1000,
                               MaxChildrenCount = 200 };
    Boolean bRes = false;

    if ( items.Count < EventCondition.MaxCount )
    {
        if ( items.Where(item => item.Gender == 0).Count >= EventCondition.MinFemaleCount )
        {
            if ( items.Where(item => item. Age < 20).Count >= EventCondition.MaxChildrenCount )
            {
                bRes = true;
            }
        }
    }


    return bRes;
}

LINQ 的用法可以參考匿名類別及匿名函式的 MSDN 介紹,MSDN 介紹即是以 LINQ 查詢句子來做示範:Anonymous TypesAnonymous Functions

沒有留言:

張貼留言