`
cdragon
  • 浏览: 76993 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

effective hierarchy(一)之 从array说起(1)

阅读更多

MSDN(c#2.0):
数组的元义是相同类型(type)的一组"变量"。它是类型声明的,如type[] arrayName;

数组类型用成对的'[' ']'表示,默认情况下,[]内可不填写硬代码(hardcode),c#会根据情况自动分配;

数组元素用成对的'{' '}'表示;{}标界数组单元;

在c#中,数组提升为对象层次,不再仅仅是c和c++中连续可及(addressable)的内存区域;

一个元素就是数组中的一个值;数组的长度是它可包含的元素总数;数组的秩是数组中的维数;数组中维度的下限是数组中该维度的起始索引,多维数组的各个维度可以有不同的界限。


数组的属性:
(1)形态上可以是一维、多维或多重交错的(一维数组的意义在于纯对值处理);
(2)数值类型数组的元素默认为零,而引用类型数组的元素默认为null;后者需要显式地实例化;前者就int[] ints={1,2,3} 好了;)
(3)多重交错数组是数组的数组(an array of arrays),类型是引用类型;
(4)数组元素的索引是从零开始,即n个元素的数组,它的索引是从0到n-1;
(5)数组元素的类型可以是任何类型,当然也包括数组;
(6)array的抽象基类型(abstract base type)是Array,可使用基类的所有属性和成员,如Rank属性表示维度,或格致;

(7)Array基类型已经实现了IEnumerable接口和IEnumberable<T>泛型接口,可以使用foreach对数组的元素进行遍历(iteration);

(8)隐式类型的数组。

一、数组作为函数的参数

数组是引用类型,故可以改变其值,常用来作为函数参数。
(1)参数可以是已经初始化的数组,如 void PrintArray(int[] arr) { // method code }
(2)也可以在参数中初始化一个新数组,如 PrintArray(new int[] { 1, 3, 5, 7, 9 });

 

二. 使用out或ref

1. 基础知识

(1)这两个关键字(keyword),都能使参数以引用方式传递(be passed by reference);

(2)在调用方法(calling method,实参)和方法定义(method defination,形参)中,都必须显式地使用该关键字;

(3)运行时段(run-time)的区别,out要求调用方法在返回(method return)前对其处理,可以返回值也可以返回对象;

        ref强调参数在传递之前就将其初始化,也可传递引用类型;

(4)在编译时段(compile time),ref和out不构成函数的多态性(方法重载)。即一个方法不能使用了ref后,又使用out,反之亦然,如

class CS0663_Example 
{
    // compiler error CS0663: "cannot define overloaded 
    // methods that differ only on ref and out"
    public void SampleMethod(out int i) {  }
    public void SampleMethod(ref int i) {  }
}

 

(5)若要构成方法重载(overloaded methods),二者只用其一,如

class RefOutOverloadExample
{
    public void SampleMethod(int i) {  }
    public void SampleMethod(out int i) {  }
}

 (6)属性不是变量,不能用作out或ref的参数;

 

2. 数组类型的out或ref参数

(1)同所有的out参数一样,必须由被调用方(callee)处理;

(2)同所有的ref参数一样,必须由调用方(caller)处理。

 

//主要用途示例:
class TestOut
{
    static void FillArray(out int[] arr)
    {
        // Initialize the array:
        arr = new int[5] { 1, 2, 3, 4, 5 };
    }

    static void Main()
    {
        int[] theArray; // Initialization is not required

        // Pass the array to the callee using out:
        FillArray(out theArray);

        // Display the array elements:
        System.Console.WriteLine("Array elements are:");
        for (int i = 0; i < theArray.Length; i++)
        {
            System.Console.Write(theArray[i] + " ");
        }
    }
}

 

 

三、在数组中使用foreach语句(statement)

(1)用简单清晰地方式遍历数组

//遍历单维数组
int[] numbers = { 4, 5, 6, 1, 2, 3, -2, -1, 0 };
foreach (int i in numbers)
{
    System.Console.WriteLine(i);
}

//遍历多维数组
int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } };
foreach (int i in numbers2D)
{
    System.Console.Write("{0} ", i);
}

 

 

(2)但,对于多维数组,嵌套的for循环,能对数组元素,进行更好地控制。

 

四、多重交错数组

注,这里将这种数组类型单列出来,是因为它杰出的性能。如下图,

 

 

(1)数组的元素是数组,这样的数组被称作嵌套数组、多重数组,或交错数组.个人认为嵌套数组的叫法更准确。因为与多维数组相比,两者在数组元素存储方式上的不同,多维数组是连续存放,通过偏移量(offset),即可确定数组元素,而嵌套数组明显与此不同;

(2)这样,数组的元素之间,就可以是不同的维数(dimension)和大小(size).如3个元素的一维多重数组,声明为

         int[][] jaggedArray = new int[3][];

(3)使用嵌套数组前,元素必须被初始化.如

         jaggedArray[0] = new int[5];
         jaggedArray[1] = new int[4];
         jaggedArray[2] = new int[2];

        或,

          jaggedArray[0] = new int[] { 1, 3, 5, 7, 9 };
          jaggedArray[1] = new int[] { 0, 2, 4, 6 };
          jaggedArray[2] = new int[] { 11, 22 };

        或,

         int[][] jaggedArray2 = new int[][]
        {
           new int[] {1,3,5,7,9},
           new int[] {0,2,4,6},
           new int[] {11,22}
         };

        或简写为,

      int[][] jaggedArray3 =
   {
       new int[] {1,3,5,7,9},
       new int[] {0,2,4,6},
       new int[] {11,22}
   };

(4)嵌套数组和多维数组混合。
        int[][,] jaggedArray4 = new int[3][,]
       {
           new int[,] { {1,3}, {5,7} },
           new int[,] { {0,2}, {4,6}, {8,10} },
           new int[,] { {11,22}, {99,88}, {0,9} }
        };

      //访问方式,输出5

     System.Console.Write("{0}", jaggedArray4[0][1, 0]);

 

 

//主要用途示例
class ArrayTest
{
    static void Main()
    {
        // Declare the array of two elements:
        int[][] arr = new int[2][];

        // Initialize the elements:
        arr[0] = new int[5] { 1, 3, 5, 7, 9 };
        arr[1] = new int[4] { 2, 4, 6, 8 };

        // Display the array elements:
        for (int i = 0; i < arr.Length; i++)
        {
            System.Console.Write("Element({0}): ", i);

            for (int j = 0; j < arr[i].Length; j++)
            {
                System.Console.Write("{0}{1}", arr[i][j], j == (arr[i].Length - 1) ? "" : " ");
            }
            System.Console.WriteLine();
        }
    }
}

 

 

五、数组拷贝的几种方式

(1) 对源数组的元素逐个复制;

(2)Copy方式,把某个数组在一定范围内的元素拷贝到另外一个数组,并且根据需要执行类型转换(cast)和装箱;

(3)CopyTo方式,拷贝当前一维数组从指定索引位置(index)开始的元素到另外一个数组;

(4)Clone方式,数组的浅表复制(shallow copy)。

        a/即,无认是数值还是引用类型,它都只复制数组的元素,但不拷贝引用所指向的对象。目标数组和源数组是指向相同的对象。

        b/数组的深复制(deep copy)不仅拷贝元素,而且拷贝元素直接和间接引用的全部。

        c/clone的数组和原来的数组是相同的类型(same type);

        d/该方法是O(n)操作,n是长度。

 

//主要用途示例

   Array.Copy(weekDays,copyArr1,copyArr1.Length);
 
 
     // Copies the source Array to the target Array, starting at index 6.注,0表示全部
      mySourceArray.CopyTo( myTargetArray, 6 );

     // Create a clone of the CultureInfo array.
      CultureInfo[] arrCIClone = (CultureInfo[]) arrCI.Clone();

 

 

六、隐式类型数组

借助于var关键字(c#3.0)的本地变量的推理类型(inferred type) 的能力--通过表达式右侧的初始化语句来推理(自动判断)变量的类型,使得单维数组同样受益。

(1)可以创建隐式类型的数组,数组实例的类型是由数组初始化的元素推理得到。

(2)隐式类型数组常用于查询表达式中,和匿名类型/对象/集合(collection)的初始化器,一起使用。

 

//用途示例
class ImplicitlyTypedArraySample
{
    static void Main()
    {
        var a = new[] { 1, 10, 100, 1000 }; // int[]
        var b = new[] { "hello", null, "world" }; // string[]

        // single-dimension jagged array
        var c = new[]   
        {  
           new[]{1,2,3,4},
           new[]{5,6,7,8}
        };

        // jagged array of strings
        var d = new[]   
       {
        new[]{"Luca", "Mads", "Luke", "Dinesh"},
        new[]{"Karen", "Suma", "Frances"}
        };
    }
}

 

 小结:数组的元义是相同类型的变量组--有意义的线性编程的基准。语言高级特征的内核(kernel)。

 

 优点:(1)数组是性能计算的利器。

    (2)在.NET2.0框架中,Array类实现了System.Collections.Generic.IList、System.Collections.Generic.ICollection 和 System.Collections.Generic.IEnumerable 泛型接口。(由于实现是在运行时提供给数组的,因而对于文档生成工具不可见。)

 

 

 

  • 大小: 12.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics