CLR via C# 笔记 -- 数组(16)

1. 数组隐式继承 System.Array,所以数组是引用类型。变量包含的是对数组的引用,而不是包含数据本身的元素。

2. 数组协变性。将数组从一种类型转换为另一种类型。

string[] sa = new string[100];
object[] oa = sa;
oa[5] = "Jeff";         // 性能损失:CLR检查oa的元素类型是不是String;检查通过
oa[3] = 5;              // 性能损失:CLR检查oa的元素类型是不是Int32;发现有错,抛异常

System.Buffer的BlockCopy方法,只支持基元类型,不具有转型能力。

System.Array的ConstrainedCopy方法,要么完美复制,要么抛出异常,不会破坏目标数组中的数据,不执行装箱、拆箱和向下类型转换。

3. 所有数组都隐式实现 IEnumerable,ICollection,IList

4. 创建下限非0的数组

int[] lowerBounds = { 2015, 1 };
int[] lengths = { 5, 4 };
decimal[,] quarterlyRevenue = (decimal[,])Array.CreateInstance(typeof(decimal), lengths, lowerBounds);
Console.WriteLine("{0,4} {1,9} {2,9} {3,9} {4,9}", "year", "Q1", "Q2", "Q3", "Q4");
int fristYear = quarterlyRevenue.GetLowerBound(0);      // 2015
int lastYear = quarterlyRevenue.GetUpperBound(0);       // 2019
int fristQuarter = quarterlyRevenue.GetLowerBound(1);   // 1
int lastQuarter = quarterlyRevenue.GetUpperBound(1);    // 4
for (int year = fristYear; year <= lastYear; year++)
{
    Console.Write(year + " ");
    for (int quarter = fristQuarter; quarter < lastQuarter; quarter++)
    {
        Console.Write("{0,9:C} ", quarterlyRevenue[year, quarter]);
    }
    Console.WriteLine();
}

5. 数组只有两种,下限为0的一维数组(System.String[])和下限未知的多维数组(System.String[,])。1维1基数组(System.String[*])C#不允许使用。访问一维0基数组比访问非0基多维数组要快,因为在for循环中JIT编译器会生成代码来检查是否 0 >= GetLowerBound(0) && (length-1) <= GetUpperBound(0),一维0基数组只会在for循环前检查1次,非0基多维数组则每次都会检查。

private const int c_numElements = 10000;
public static void Main()
{
    int[,] a2Dim = new int[c_numElements, c_numElements];
    int[][] aJagged = new int[c_numElements][];
    for (int x = 0; x < c_numElements; x++)
    {
        aJagged[x] = new int[c_numElements];
    }

    Safe2DimArrayAccess(a2Dim);

    SafeJaggedArrayAccess(aJagged);

    Unsafe2DimArrayAccess(a2Dim);
}
private static int Safe2DimArrayAccess(int[,] a) 
{
    int sum = 0;
    for (int x = 0; x < c_numElements; x++)
    {
        for (int y = 0; y < c_numElements; y++)
        {
            sum += a[x, y];
        }
    }
    return sum;
}
private static int SafeJaggedArrayAccess(int[][] a) 
{
    int sum = 0;
    for (int x = 0; x < c_numElements; x++)
    {
        for (int y = 0; y < c_numElements; y++)
        {
            sum += a[x][y];
        }
    }
    return sum;
}
private static unsafe int Unsafe2DimArrayAccess(int[,] a) 
{
    int sum = 0;
    fixed (Int32* pi = a) 
    {
        for (int x = 0; x < c_numElements; x++)
        {
            int baseOfDim = x * c_numElements;
            for (int y = 0; y < c_numElements; y++)
            {
                sum += pi[baseOfDim + y];
            }
        }
    }
    return sum;
}

6. 栈上分配数组

public static void Main() 
{
    StackallocDemo();
    InlineArrayDemo();
}
private static void StackallocDemo() 
{
    unsafe 
    {
        const int width = 20;
        Char* pc = stackalloc char[width]; // 在栈上分配数组
        string s = "Jeffrey Richter";
        for (int index = 0; index < width; index++)
        {
            pc[width - index - 1] = (index < s.Length) ? s[index] : '.';
        }
        Console.WriteLine(new string(pc, 0, width));
    }
}

private static void InlineArrayDemo() 
{
    unsafe 
    {
        CharArray ca;
        Int32 widthInByBytes = sizeof(CharArray);
        Int32 width = widthInByBytes / 2;

        string s = "Jeffrey Richter";
        for (int index = 0; index < width; index++)
        {
            ca.Characters[width - index - 1] = (index < s.Length) ? s[index] : '.';
        }
        Console.WriteLine(new string(ca.Characters, 0 ,width));
    }
}

internal unsafe struct CharArray 
{
    public fixed Char Characters[20];
}

 

posted @ 2021-06-02 00:14  Karl_Albright  阅读(67)  评论(0编辑  收藏  举报