2011年7月5日 星期二

CLR via C#(3rd Edition)

CLR via C#(第3版)/微軟技術叢書


Bear在這裡買的
amazon的參考
-----------------------------------------------------------
作者:(美)瑞奇特|簡體版譯者:周靖
出版社:清華大學
ISBN:9787302232599
出版日期:2010/09/01
裝幀:
頁數:777
人民幣:RMB 99 元
-----------------------------------------------------------

CLR via C# 實際內文頁要再加上18

P.86(原文P.94)

編譯器在編譯時無法准確地獲知對象o引用的是什麼類型。所以,編譯器允許代碼通過編譯。但在運行時,CLR知道了o引用的是什麼類型(在每次執行轉型的時候),所以它會核實對象的類型是不是Employee或者從Employee派生的任何類型。

public static void PromoteEmployee(Object o) {
// At this point, the compiler doesn't know exactly what
// type of object o refers to. So the compiler allows the
// code to compile. However, at runtime, the CLR does know
// what type o refers to (each time the cast is performed) and
// it checks whether the object's type is Employee or any type
// that is derived from Employee.
Employee e = (Employee) o;
...

P.87

Bear:
使用is再加上強制轉型的方式做,致少就會對物件進行2次檢查。若改用as的話,只會檢查一次喔。

as操作符的工作方式與強制類型一樣,只是它永遠不會拋出一個異常。相反的,如果對象不能轉型,結果就是null。所以正確的作法是檢查最終生成的引用是否為null。

The as operator works just as casting does except that the as operator will never throw an exception. Instead, if the object can’t be cast, the result is null. You’ll want to check to see whether the resulting reference is null, or attempting to use the resulting reference will cause a System.NullReferenceException to be thrown.

P.88(原文P.97)

子代可替代父代,父代不可替代子代

P.88(原文P.110)

注意,如果Employee的Lookup方法實現Joe時只是一個Employee類別,而不是一個Manager類別,Lookup會在內部構造一個Employee對象,它的類型對象指針將引用Employee類型對象。這樣一來,最終執行的就是Employee的GetProgressReport實現,而不是Manager的GetProgressReport實現。

Note that if Employee’s Lookup method had discovered that Joe was just an Employee and not a Manager, Lookup would have internally constructed an Employee object whose type object pointer member would have referred to the Employee type object, causing Employee’s implementation of GetProgressReport to execute instead of Manager’s implementation.

P.104 中間 (原文P.117)

error?
Boolean found = false; // Generated code sets found to 0

P.106(原文P.118~119)

Here’s an example that uses the unchecked operator:
UInt32 invalid = unchecked((UInt32) (-1)); // OK
And here is an example that uses the checked operator:

Byte b = 100;
b = checked((Byte) (b + 200)); // OverflowException is thrown

In this example, b and 200 are first converted to 32-bit values and are then added together; the result is 300. Then 300 is converted to a Byte due to the explicit cast; this generates the OverflowException. If the Byte were cast outside the checked operator, the exception wouldn’t occur:

b = (Byte) checked(b + 200); // b contains 44; no OverflowException

P.108(原文P.121)

這意味著Decimal值的處理速度慢於CLR基元類型的值的處理速度。另外由於沒有相應的IL指令來處理Decimal值,所以checked和unchecked操作符、語句及編譯器開關都失去了效用。

When you compile code that uses Decimal values, the compiler generates code to call Decimal’s members to perform the actual operation. This means that manipulating Decimal values is slower than manipulating CLR primitive values. Also, because there are no IL instructions for manipulating Decimal values, the checked and unchecked operators, statements, and compiler switches have no effect. Operations on Decimal values always throw an OverflowException if the operation can’t be performed safely.

P.110(原文P.124)

The only difference is that C# “thinks” that the instance is initialized if you use the new operator. The following code will make this point clear:
// These two lines compile because C# thinks that
// v1's fields have been initialized to 0.
SomeVal v1 = new SomeVal();
Int32 a = v1.x;
// These two lines don't compile because C# doesn't think that
// v1's fields have been initialized to 0.
SomeVal v1;
Int32 a = v1.x; // error CS0170: Use of possibly unassigned field 'x'

P.126(原文P.142)

In fact, I recommended that value types have their fields marked as readonly so that the compiler will issue errors should you accidentally write a method that attempts to modify a field.

P.140(原文P.157)

定義類型時,如果不顯式指定類型的可見性,C#編譯器默認將類型的可見性設為internal(兩者之中較有限的那一個)。

If you do not explicitly specify either of these when you define a type, the C# compiler sets the type’s visibility to internal (the more restrictive of the two).

P.161(原文P.183)

簡體翻譯看不順眼的:句點應該在小括號之後才對吧?

但是,readonly字段只能在一個構造器方法中寫入(這個構造器只能調用一次,也就是對象首次創建時)。編譯器和驗證機制確保readonly字段不會被構造器以外的任何方法寫入。注意,可利用反射來修改readonly字段。

However,
readonly fields can be written to only within a constructor method (which is called only once, when an object is first created). Compilers and verification ensure that readonly fields are not written to by any method other than a constructor. Note that reflection can be used to modify a readonly field.

P.163(原文P.185)

當某個字段是引用類型,並且該字段標記為readonly時,那麼不可改變的是引用,而非字段引用的對象。

Bear:
這個非常的重要嘿,但這個不難理解,請用delphi的想法去思考,在procedure Foo(const v: TLabel)中,你不能去改變v的參考(ex: v := label2;),但你可以改變v的內容(ex: v.caption := '';)

Important When a field is of a reference type and the field is marked as readonly, it is the reference that is immutable, not the object that the field refers to. The following code demonstrates:
public sealed class AType {
// InvalidChars must always refer to the same array object
public static readonly Char[] InvalidChars = new Char[] { 'A', 'B', 'C' };
}
public sealed class AnotherType {
public static void M() {
// The lines below are legal, compile, and successfully
// change the characters in the InvalidChars array
AType.InvalidChars[0] = 'X';
AType.InvalidChars[1] = 'Y';
AType.InvalidChars[2] = 'Z';
// The line below is illegal and will not compile because
// what InvalidChars refers to cannot be changed
AType.InvalidChars = new Char[] { 'X', 'Y', 'Z' };
}
}

P.169(原文P.192)

internal struct Point {
public Int32 m_x, m_y;
public Point() {
m_x = m_y = 5;
}
}
internal sealed class Rectangle {
public Point m_topLeft, m_bottomRight;
public Rectangle() {
}
}
Now when a new Rectangle is constructed, what do you think the m_x and m_y fields in the two Point fields, m_topLeft and m_bottomRight, would be initialized to: 0 or 5? (Hint: This is a trick question.)

P.305(原文P.347)

數組的動態擴容會損害性能。要避免這種危害,請設置一個合適的初始容量。

When appending characters to the character array, the StringBuilder detects if the array is trying to grow beyond the array’s capacity. If it is, the StringBuilder automatically doubles the capacity field, allocates a new array (the size of the new capacity), and copies the characters from the original array into the new array. The original array will be garbage collected in the future. Dynamically growing the array hurts performance; avoid this by setting a good initial capacity.

P.335(原文P.382)

簡體有誤:TraParse應為TryParse,已告知譯者勘誤。

Parse和TryParse方法在調用時,會在內部執行以下動作。
1. 刪除字符串頭尾的所有空白字符。

When Parse and TryParse are called, the following actions are performed internally:
1. It removes all whitespace characters from the start and end of the string.