2012年12月25日 星期二

LINQ to Objects Using C# 4.0: Using and Extending LINQ to Objects and Parallel LINQ (PLINQ)

amazon的參考

LINQ 設計模式 using C# 4.0
作者:Troy Magennis 著、曹紋蓮 譯
出版社:上奇資訊
ISBN:9862575417
出版日期:2012-10-31
台幣定價:490


P.2-5(原文P.21)
為了確保新的型別個體是穩定且可在初始化後立即使用(避免物件進入無效的狀態),好的寫程式習慣是將所有重要資料都使用建構函數參數。

C# 3.0 introduced an object initialization shortcut syntax that allows a single C# statement to both construct a new instance of a type and assign property values in one statement. While it is good programming practice to use constructor arguments for all critical data in order to ensure that a new type is stable and ready for use immediately after it is initialized (not allow objects to be instantiated into an invalid state), Object Initializers reduce the need to have a specific parameterized constructor for every variation of noncritical data argument set needed over time.

P.2-8(原文P.24)
Bear: 這裡的compile-time type翻譯不好,應該是翻為"編譯時期型別"而非編譯時間型別。

The initialize expression (the expression to the right side of the equal sign), must have a compile-time type.

P.2-11(原文P.28)
Bear: 這用法不錯,可以學起來

// lambda expression -
button.Click += (object sender, EventArgs args) => MessageBox.Show(”Clicked”);

P.2-17(原文P.34~35)
Bear: 未滿35歲,可以用它這裡的方式判別:生日+35年比今天大

var q = from c in contacts where c.DateOfBirth.AddYears(35) > DateTime.Now

P.3-8(原文P.48)
使用擴充方法語法的小技巧:
1.先表達最受限制的查詢方法,可使接續的運算子減少工作負載。
2.將每一個運算子(包括其聯結來源)分開至不同行,這樣可在除錯時,分別指出各運算子的錯誤訊息。
3.保持前後一致,在一個應用程式只使用一種方法。
4.讓查詢更易讀,不要害怕將查詢分成多個部份,並縮排列出同一層級的運算子。

EXTENSION METHOD DEVELOPER TIPS
■ Express the most limiting query method first; this reduces the workload of the successive operators.
■ Split each operator onto a different line (including the period joiner). This allows you to comment out individual operators when debugging.
■ Be consistent—within an application use the same style throughout.
■ To make it easier to read queries, don’t be afraid to split up the query into multiple parts and indent to show hierarchy.

P.3-8(原文P.49)
使用查詢表達式語法的小技巧:
1.如果需要混合擴充方法與查詢表達式,則將擴充方法放至表達式的最後。
2.把每個查詢表表達式部份分開,這樣可在除錯時,指出個別指令的錯誤訊息。

QUERY EXPRESSION DEVELOPER TIPS
■ If you need to mix extension methods with query expressions, put them at the end.
■ Keep each part of the query expression on a separate line to allow you to individually comment out individual clauses for debugging.

P.3-11(原文P.52)
在判斷的條件很冗長時,你可能不只需要寫一個查詢,應該要考慮將其放到一個屬於自已的主體方法裡(寫任何重複程式碼的好習慣)。

Although you can write queries and inline the code for the filter predicate, you don’t have to. If the predicate is lengthy and might be used in more than one query expression, you should consider putting it in its own method body (good practice for any duplicated code). Rewriting the previous examples using an external predicate function shows the technique:

P.3-23(原文P.64)
當在使用查詢表達式時,每個排序鍵和選擇方向的關鍵字必須用逗點分開,如果沒有指明遞減或遞增的排序方向,LINQ會預設為遞減排序。

When using the query expression syntax, each sorting key and the optional direction keyword needs to be separated by a comma character. If the descending or ascending direction keywords are not specified, LINQ
assumes ascending order.

P.3-24(原文P.65)
CurrentCultureIgnoreCase 使用目前文化特性的文字比較規則,來執行不區分大小寫的字串比較。

CurrentCultureIgnoreCase
Performs case-insensitive string comparisons using the word comparison rules of the current culture.

P.4-5(原文P.78-79)
在資料來源寫 key selector 時,有些會需要處理 null 值,如果使用 Substring 方法,有任何一個數字字串是null 值,則表 4-1 的程式碼會執行失敗。

Some care when writing the key selector is required for handling null values in the source data. The code shown in Listing 4-1 will fail if any of the part-number strings are null in value the moment the Substring method is attempted. Null values are safely handled in general, but if the range variable is processed within the key selector function, the normal null handling rules apply. Thus it is necessary to confirm an element isn’t null before attempting to access properties or call methods on these range variables.

P.4-5(原文P.79)
在資料來源的 null 值會破壞群組表達式,所以此群組查詢將執行失敗。

// beware - nulls in source data can break your group
// expression. This grouping will fail.
var q = from pn in partNumbers
group pn by pn.Substring(0, 3);

P.4-5(原文P.79)
為了避免這種情形,應先確認 key selection 表達式中的null 值,再把這些元素放至群組裡,使其可以依序處理 null 群組,且不會產生例外。

To protect against this circumstance, check the key selection expression for null values and throw all those elements into a group of your choosing to keep the exception from being thrown and to allow the null grouping to be orderly processed, as the following code demonstrates:

P.4-6(原文P.79)
在查詢表達式中,完整 if-then-else 敘述是無效的語法。
Bear: 所以只能用三元運算式( ? : )來處理條件式。

USING THE TERNARY (?) AND NULL COALESCING (??)
OPERATORS The ternary operator shortens the common if (condition) then (true expression) else (false expression) pattern of code to (condition) ? (true expression) : (false expression). This is especially useful when handling null values within query expressions where a full if-then-else statement is not valid syntax.

P.4-6(原文P.80)
Bear: null值預防及處理方法

The null-coalescing operator is used to define a default value if the variable it follows has a null value, that is, X = (variable) ?? (default if null). Listing 4-2 demonstrates this usage.

Listing 4-2 Example of using the null-coalescing operator and the ternary operator to protect keySelector expressions from null values

// Guard against null data using ternary (? as shown)
var q1 = from c in Contact.SampleData()
group c by
c.State == null ? ”(null)” : c.State;
// Guard against null data using
// the null coalescing operator (??).
var q2 = from c in Contact.SampleData()
group c by
c.State ?? ”(null)”;

P.4-14(原文P.89)
Bear: 這裡的 State: FL應該不會被縮排才對,已比對過原文,確定是中文版的錯

State: AK
Adam Gauwain
Chris Gauwain
State: FL
Collin Zeeman
State: TX
Blaine Reifsteck
Mack Kamph

P.4-25(原文P.101)
要在LINQ至物件執行一個外部聯結風格的查詢,DefaultIfEmpty 標準查詢運算子是使用於聯結的from指令,並在選擇投影處理這個運算子產生的null值。

To carry out an outer-join style query in LINQ to Objects, the DefaultIfEmpty standard query operator is used in the from clause of a join, and the null value generated by this operator handled in the select projection. Although this sounds difficult, Listing 4-13 demonstrates an outer join using the sample data shown in Table 4-2, which generates the Console output shown in Output 4-10. This query is a little ambiguous at first glance, but in essence it injects a null element (the default value for an instance of Order type) for any Customer element that would have been removed by the inner join. This propagates a null value for order that any subsequent code working with that result property can process. In this example the ternary operator in the Console.WriteLine statement is catching and handling the null values by replacing those results with the string ”(no orders)”.

P.7-4(原文P.)
Bear: 有錯誤、null及空集合時要特別注意。

P.8-5(原文P.237)
定義使用選擇性參數的方法簽章規則如下:

1.強迫參數不能在選擇性參數後出現。
2.預設指定必須用在編譯時期的常數表達式、不用參數的數值型別結構或T為數值型別的default(T)。
3.常數表達式必須可被識別,並隱含轉換為這個參數的型別。
4.有 ref和out 修飾詞的參數,不能為選擇性參數。
5.參數陣列(params)可以在選擇性參數後出現,但這些陣列就不能有已設定的預設值,如果在呼叫時數值被略過與使用一個空的參數陣列,其都會達到一樣的結果。

The rules when defining a method signature that uses optional parameters are:
1. Required parameters cannot appear after any optional parameter.
2. The default specified must be a constant expression available at compile time or a value type constructor without parameters, or default(T) where T is a value type.
3. The constant expression must be implicitly convertible by an identity (or nullable conversion) to the type of the parameter.
4. Parameters with a ref or out modifier cannot be optional parameters.
5. Parameter arrays (params) can occur after optional parameters, but these cannot have a default value assigned. If the value is omitted by the calling invocation, an empty parameter array is used in either case, achieving the same results.

P.8-5(原文P.238)
使用以下的選擇性參數方法定義是不會被執行的:

The following method definitions using optional parameters will not compile:

//”Optional parameters must appear after all required parameters”
public void M1 (int i = 1, string s) {}

//”Default parameter value for ‘p’ must be a compile-time constant”
//(Can’t use a constructor that has parameters)
public void M2(Point p = new Point(0,0)) {}

//”Default parameter value for ‘p’ must be a compile-time constant”
//(Must be a value type (struct or built-in value types only))
public void M5(StringBuilder p = new StringBuilder()) {}

//”A ref or out parameter cannot have a default value”
public void M6(int i = 1, out string s = ””) {}

//”Cannot specify a default value for a parameter array”
public void M7(int i = 1, params string[] values = ”test”) {}

P.8-7(原文P.240)
只要符合以下的規定,就可結合指定的位置和具名引數來呼叫方法:
1.若要使用結合位置與具名引數,其位置引數必須先被傳送(它們不能在具名引數之後)。
2.所有的非選擇性參數,都必須用名稱或位置指定。
3.如果引數是用位置指定的,其接下來不能同時用名稱來指定。

Methods can be called with any combination of positionally specified and named arguments, as long as the following rules are observed:
1. If you are going to use a combination of positional and named arguments, the positional arguments must be passed first. (They cannot come after named arguments.)
2. All non-optional parameters must be specified somewhere in the invocation, either by name or position.
3. If an argument is specified by position, it cannot then be specified by name as well.

P.8-8(原文P.240)
Bear: 看不懂這是在說啥

// “The best overload for ‘.ctor’ does not have a
// parameter named ‘x’”
Point p5 = new Point(x: 10);

P.8-8(原文P.241)
Bear: 看不懂這是在說啥

NewWay newWay = new NewWay();
// skipping an optional parameter
newWay.DoSomething(
”({0},{1}) New way - param1 skipped.”,
param2: false);
// any order, but if it doesn’t have a default
// it must be specified by name somewhere!
newWay.DoSomething(
param2: false,
formatString: ”({0},{1}) New way - params specified” +
” by name, in any order.”,
param1: 5);