0基一維數組的性能是最佳的.因為可以使用一些特殊的IL指令. 16.1 初始化數組元素 16.2 數組轉型 元素為 引用類型 的數組,如果 維數相同 ,且元素源類型到目標類型 存在隱式或顯式轉換 ,CLR 允許將數組元素從一種類型轉型另一種. CLR不允許將值類型元素的數組轉型為其他任何類型 ,不過 ...
//創建一個一維數組
int[] myIntegers; //聲明一個數組引用
myIntegers = new int[100]; //創建含有100個int的數組
//創建一個二維數組
double[,] myDoubles = new double[10, 20];
//創建一個三維數組
string[,,] myStrings = new string[5, 3, 10];
//創建交錯數組
Point[][] myPolygons = new Point[3][];
myPolygons[0] = new Point[10];
myPolygons[1] = new Point[20];
myPolygons[2] = new Point[30];
- 0基一維數組的性能是最佳的.因為可以使用一些特殊的IL指令.
16.1 初始化數組元素
// 1) 利用c#的隱式類型的局部變數功能:
var names1 = new string[] { "Alidan", "Grant" };
// 2) 利用C#的隱式類型的局部變數和隱式類型的數組功能:
var names2 = new[] { "Alidan", "Grant", null };
// 3) 額外的語法獎勵(這裡不能用var)
string[] names3 = { "Alidan", "Grant" };
// 4) 使用C#的隱式類型的局部變數\隱式類型的數組和匿名類型功能:
var kids = new[] { new { Name = "Aidan" }, new { Name = "Grant" } };
foreach (var kid in kids)
Console.WriteLine(kid.Name);
16.2 數組轉型
- 元素為引用類型的數組,如果維數相同,且元素源類型到目標類型存在隱式或顯式轉換,CLR 允許將數組元素從一種類型轉型另一種.
- CLR不允許將值類型元素的數組轉型為其他任何類型,不過可用 Array.Copy 方法來模擬.
//創建二維 FileStream 數組
FileStream[,] fs2dim = new FileStream[5, 10];
//隱式轉型為二維 Object 數組
object[,] o2dim = fs2dim;
//顯示轉型為二維 Stream 數組
Stream[,] s2dim = (Stream[,])o2dim;
//創建一維 Int32 數組(元素是值類型)
int[] ildim = new int[5];
//下麵的代碼創建元素為引用類型的數組,
//每個元素都是對已裝箱 Int32 的引用
object[] obldim = new object[ildim.Length];
Array.Copy(ildim, obldim, ildim.Length);
- 使用數組轉型有性能損失,對數組元素賦值時,CLR必須在運行時檢查數組包含元素的類型是否與新元素類型相符.
- System.Buffer.BlockCopy() 方法比 Array.Copy() 方法快,但前者只支持基元類型,不提供像 Array 的 Copy 方法那樣的轉型能力.
- Array.ConstrainedCopy 方法要麼完成複製,要麼拋出異常,總之不會破壞目標數組中的數據.
16.3 所有數組都隱式派生自 System.Array
16.4 所有數組都隱式實現 IEnumerable, ICollection 和 IList
- System.Array 實現了 IEnumerable,ICollection 和 IList 三個介面,但未實現其對應的泛型介面.
- CLR 創建一維 0 基數組類型時,CLR 自動使數組類型實現
IEnumerable<T>
,ICollection<T>
和IList<T>
(T是數組元素的類型) 介面.同時,還為數組類型的所有基類型實現這三個泛型介面,只要它們是引用類型(數組元素為值類型的,不為數組的基類型實現介面).
16.5 數組的傳遞和返回
- 數組作為實參傳給方法時,實際傳遞的是對該數組的引用.因此,被調用的方法能修改數組中的元素.
- 方法返回數組對象時,如果元素數量為 0 ,強烈建議返回一個空數組,而不是 null ,因為調用方法時可以省去 null 檢查.
16.6 創建下限非零的數組
16.7 數組的內部工作原理
- 訪問一維 0 基數組的元素比訪問非 0 基一維或多維數組的元素稍快.因為:
- 有一些特殊 IL 指令處理一維 0 基數組,導致 JIT 編譯器生成優化代碼;
- For 迴圈時,JIT 編譯器會將對 Length 屬性的調用結果緩存起來,每次迭代檢查的都是這個臨時變數.(不要自作聰明自己緩存 Length 結果)
- 如要提升性能,可以用交錯數組代替矩形數組.
- 矩形數組的訪問方式
a[x,y]
,交錯數組的訪問方式a[x][y]
16.8 不安全的數組訪問和固定大小的數組
static class Program
{
static void Main(string[] args)
{
StackallocDemo();
InlineArrayDemo();
}
private static void StackallocDemo()
{
unsafe
{
const int width = 20;
char* pc = stackalloc char[width]; //在棧上分配數組
string s = "Jeffrey Richter"; //15個字元
for (int index = 0; index < width; index++)
{
pc[width - index - 1] = (index < s.Length) ? s[index] : '.';
}
//下麵這行代碼顯示".....rethciR yerffeJ"
Console.WriteLine(new String(pc, 0, width));
}
}
private static void InlineArrayDemo()
{
unsafe
{
CharArray ca; //在棧上分配數組
int widthInBytes = sizeof(CharArray);
int width = widthInBytes / 2; //Char類型占2個位元組
string s = "Jeffrey Richter"; //15個字元
for (int index = 0; index < width; index++)
{
ca.Characters[width - index - 1] = (index < s.Length) ? s[index] : '.';
}
//下麵這行代碼顯示".....rethciR yerffeJ"
Console.WriteLine(new String(ca.Characters, 0, width));
}
}
}
internal unsafe struct CharArray
{
//這個數組內聯(嵌入)到結構中
public fixed char Characters[20];
}
在結構中嵌入數組,需滿足:
- 類型必須是結構(值類型);不能在類(引用類型)中嵌入數組.
- 欄位或其定義結構必須用 unsafe 關鍵字標記.
- 數組欄位必須用 fixed 關鍵字標記
- 數組必須是一維 0 基數組.
- 數組的元素類型必須是以下類型之一:Boolean,Char,SByte,Byte,Int16,Int32,UInt16,UInt32,Int64,UInt64,Single,Double