C#C#高级编程笔记 Day 8, 二零一四年四月 1十五日 (数组)

1、数组的先导化

  注脚了数组后,就不可以不为数组分配内存,以保存数组的全数因素。数组是援引类型,所以必须给它分配堆上的内存,为此,应采纳new
运算符,钦命数组中成分的项目和多少来初阶化数组的变量。若使用了为未分配的要素,就会抛出NullReferenceExceptonl
类型的要命。

  • int myArray=new int[4];

 

C# 1

–>
在内定了数组的尺寸后,即便不复制数组中的全体因素,就不可以重复设置数组的轻重,假若事先不驾驭数组中应包涵几个要素,就足以行使集合。

上边采纳数组开头化器为数组的每一个元素赋值。数组早先化智能在宣称数组变量时使用,不可以在注解数组之后接纳。

  • int[] myArray=new int[4]{4,7,11,2};

    //或者
    
    int[] myArray=new int[]{4,7,11,2};.
    

二 、数组协理协变,表示数组可以申明为基类,其派生类型的要素得以授予数组成分。

  • 1 static Person[] GetPerson()
    2 {
    3     return new Person[]{
    4         new Person{FirstName="Damon",LastName="Hill"},
    5         new Person{FirstName="Niki",LastName="Lauda"},
    6         new Person{FirstName="Ayrton",LastName="Senna"}
    7     };
    8 }
    

  • 数组协变只可以用于引用类型,无法用来值类型。数组协变有四个题材,它只能够通过运维时充足来缓解。
    如果把Person 数组赋予 object 数组,object数组就可以使用派生自object的任何元素。
    例如,编译器允许把字符串传递给数组元素。但因为object 数组引用Person 数组,
    所以就会出现以个运行时异常 ArrayTypeMismatchException.
    

3、ArraySegment<T>

  结构ArraySegment<T>表示数组的一段,尽管急需运用分裂的格局处理某些大型方法的不等部分,那么可以把相应的数组部分复制到各样艺术中。此时,与创制三个数组比较,更使得的点子是利用一本数组。将全数数组传递给不相同的法门。那么些措施中只是用数组的某些部分。方法的参数除了数组以外,还应包含数组内的偏移量以及该措施应该运用的因素数。那样一来,方法就须求至少多少个参数。当使用数组段时,只要求2个参数就足以了。ArraySegment<T>结构包括了关于数组段的音讯(偏移量和要素个数)。

  SumOfSegments()方法提取一组ArraySegment<int>成分,计算改数组段定义的持有整数之和,并赶回整数和

  •   
     1 static int SumOfSegments(ArraySegment<int>[] segments)
     2 {
     3     int sum=0;
     4     foreach(var segment in segments)
     5     {
     6         for(int i=segment.Offset;i<segment.Offset+segment.Count;i++)
     7         {
     8             sum+=segment.Array[i];
     9         }
    10     }
    11     return sum;
    12 } 
    

四 、枚举:在foreach语句中行使枚举,可以迭代集合中的成分,且毫无知道集合中的成分个数。foreach语句使用了2个枚举器。下图显示了调用
foreach
的客户端和聚众之间的涉及。数组或集合完结带GetEumerator()方法的IEumerable接口。GetEumerator()方法再次回到一个贯彻IEumerable接口的枚举。接着,foreach语句就足以拔取IEumerable接口迭代集合了。

C# 2

  • GetEnumerator()方法用IEnumerable接口定义。foreach语句并不真的内需在集合类中落实这么些接口。有三个名为GetEnumerator()的不二法门,它回到落成了IEnumerator接口的目标就足足了

【扩展】

    .NET Framework 的核心时其运行库执行环境 即Common Language
Runtime,称为公共语言运行库(CLR)或.NET 运行库。通常将在CLR控制下
运行的代码称为托管代码(managed code)。
     但是,在CLR执行编写好的源代码(使用C#或其他语言编写的代码)之
前,需要编译它们。在.NET中,编译分为两个阶段:
    (1)将源代码编译为Microsoft 中间语言(IL)。
    (2)CLR把 IL编译为平台专用代码。
    这两个阶段的编译过程非常重要,因为Microsoft中间语言时提供.NET 的许多优点的关键。
    Microsoft中间语言与Java 字节码共享一种理念:他们都是低级语言,语法
很简单(使用数字代码,而不是文本代码),可以非常快速地转换为本地机器码。
对于代码,这种精心设计地通用语法有很重要地优点:平台无关性、提高性能、
和语言地互操作性。

 

5、IEnumerator接口

  foreach语句使用IEnumerator接口的主意和天性,迭代集结中的全数因素。为此,IEnumerator定义了Current属性,来回到光标所在的因素,该接口的MoveNext()方法移动到集结的下三个成分上,如果有那些因素,该格局就回来true。固然集合不再有越多的要素,该方法就回去false。

  foreach语句

  C#的foreach语句不会分析为IL代码中的foreach语句。C#编译器会把foreach语句转换为IEnumerable接口的章程和性质。上边是一条不难的foreach语句,它迭代persons数组中的全体因素,并逐一显示它们:

  • 1 foreach(var p in persons)

    2 {
    3     Console.WriteLine(p);
    4 }
    

     foreach
    语句会分析为下边的代码段。首先,调用GetEnumerator()方法,得到数组的二个枚举器。在while循环中——只要MoveNext()重临true——就用Current属性来访问数组中的成分:

  • 1 IEnumerator enumerator=person.GetEnumerator();

    2 while(enumerator.MoveNext())
    3 {
    4     Person p=enumeratoe.Current;
    5     Console.WriteLine(p);
    6 }
    

陆 、yield语句:以便创立枚举器。

  yield ruturn 语句重回集合的一个因素,并活动到下一个因素。

  yield break 可甘休迭代

  下边为三个采取yield return
语句落成三个简短集合的代码:HelloCollecetion
类包涵GetEnumeration()方法。该格局已毕代码包涵两条 yield return
语句,它们分别重返字符串 Hello 和 World

  • 1 using System;
    2 using System.Collections;
    3
    4 namspace com.test.yinxi
    5 {
    6 public class HelloCollection
    7 {
    8 public IEnumeratorGetEnumerator()
    9 {
    10 yield return “Hello”;
    11 yield return “World”;
    12 }
    13 }
    14 }

  • 包蕴yield 语句的办法或性质也叫做迭代块。迭代块必须声明为回到

    IEnumeration 或 IEnumerable 接口,或者这些接口的泛型版本,这个块
    可以包含多条 yield return 语句 或 yield break 语句,但不能包含 return 语
    句。
    

7、元组

  数组合并了同等类其余对象,而元组合并了不一样系列的目标。.NET
Framework 定义了七个泛型Tuple
类和1个静态Tuple类,它们用作元组的厂子,差距泛型Tuple
类协理分裂数额的因素。方法Divid()重返包蕴八个成员的元组
Tuple<int,int>。泛型类的参数定义了成员的品种,它们都以整数。元组用静态
Tuple 类的静态 Create() 方法创设。Create()
方法的泛型参数定义了要实例化的元组类型,新建的元组用 result 和 raminder
变量开端化,重回那七个变量相除的结果。

  • 1 public static Tuple Divide(int dividend,int divisor)
    2 {
    3     int result =dividend/divisor;
    4     int reminder=dividend%divisor;
    5 
    6     return Tuple.Create<int,int>(result,reminder);
    7 }
    8 
    9 //调用
    

    10 var result=Divide(5,3);
    11 Console.WriteLine(“result of division : {0},reminder: {1}”,result.Item1,result.Item2);

  要是元组包蕴的项超过八个,就可以行使带7个参数的Tuple类定义。最终1个模板参数是TRest,表示必须给它传递1个元组。那样,就足以创立带任意参数的元组了。

  • public class Tuple

     其中,最终1个模板参数是2个元组类型,所以可以创制带任意多项的元组:

  • var tuple =Tuple.Create>(“Stenphanie”,”Alina”,”Nagel”,2009,6,2,1.37,Tuple.Create(52,3490));

捌 、【专题】结构相比

  数组和元组都落成接口IStructuralEquatable和IStructuralComparable。那七个接口都以.NET
4
新增的,不仅可以相比引用,还是能相比内容。那些接口都是现实完成的,所以在利用时需求把数组和元组强制转换为那几个接口。IStructuralEquatable接口用于相比多个元组或数组是不是有一样的情节,IStructuralComparable接口用于给数组或元组排序。下边为一个贯彻
IEquatable
接口的Person类。IEquatable接口定义了1个强类型化的Equals()方法,以相比FirstName
和LastName属性的值。

  • 1 public class Person :IEquatable

    2 {    
    3     public int Id{get;private set;}
    4     public string FirstName{get;set;}
    5     public string LastName{get;set;}
    6 
    7     public override string ToString()
    8     {
    9         return String.Format("{0},{1},{2}",Id,FirstName,LastName);
    

    10 }
    11
    12 public override bool Equals(object obj)
    13 {
    14 if(obj==null)
    15 {
    16 return base.Equals(obj);
    17 }
    18 return Equals(obj as Person);
    19 }
    20
    21 public override int GetHashCode()
    22 {
    23 return Id.GetHashCode();
    24 }
    25
    26 public bool Equals(Person other)
    27 {
    28 if(other==null)
    29 {
    30 return base.Equals(other);
    31 }
    32 return this.Id==other.Id && this.FirstName==oher.FirstName&&this.LastName==other.LastName;
    33 }
    34 }

     接下来创造了八个饱含Person项的数组。这三个数组通过变量名janet
    包蕴相同的Person对象,和五个内容一致的不等Person对象。相比较运算符“!=”再次来到true,因为这实则是七个变量person1 和 persons2医用的多少个例外数组。因为
    Array类没有重写带一个参数的Equals方法,所以用“==”运算符相比较引用也会得到一致的结果,即那五个变量不同。

  • 1 var janet =new Person{FirstName=”Janet”,LastName=”Jackson”};

    2 Person[] persons1={
    3     new Person
    4     {
    5         FirstName="Michael",
    6         LastName="Jackson"    
    7     }.
    8     janet
    9 };
    

    10 Person[] persons2={
    11 new Person
    12 {
    13 FirstName=”Michael”,
    14 LastName=”Jackson”
    15 },
    16 janet
    17 };
    18 if(persons1!=persons2)
    19 {
    20 Console.WrilteLine(“not the same reference!”);
    21 }

     

     

相关文章