2)多维逗号隔开就可以了,长度用Length。数组类CRL编译后使得继承自Array类,也就是继承自IEnumerable,IStructuralComparable等,IEnumerable有 IEnumerator GetEnumerator()函数迭代器有Current,MoveNext,Reset方法,有Array基类Length属性等, foreach特性就是基于CRL定义的这些接口实现的。
3)数组的访问只支持整型的索引器。内部自定义对象数组可以用整型索引器访问的,但是提供给外部可以定义索引器,索引器就是属性只是多了参入参数,this和value的一些标识。
4)数组拷贝只支持浅拷贝,有Clone()系统会帮申请内存,Copy()要自己创建引用内存拷贝到已有数组(都是引用类型的元素);深拷贝要一个个迭代生成新对象。
5)数组支持协变,派生类可以赋值给基类数组,调用基类对象定义的方法。
6)对象数组创建:
myPersons[0] = new Person { FirstName = "Ayrton" };//, LastName = "Senna" 属性不一定要使用
myPersons[1] = new Person { FirstName = "Michael", LastName = "Schumacher" };
Array抽象类从静态方法创建数组:
// 长度是两维,每位大小是3
int[] lengths = { 3, 3 };
// 第一维1最小后面递增,第二维从10开始后面第二维重复
int[] lowerBounds = { 1, 10 };
Array racers = Array.CreateInstance(typeof(Person), lengths, lowerBounds);
racers.SetValue(new Person { FirstName = "Alain", LastName = "Prost" }, 1, 10);
racers.SetValue(new Person{FirstName = "Emerson",LastName = "Fittipaldi"}, 1, 11);
racers.SetValue(new Person { FirstName = "Ayrton", LastName = "Senna" }, 1, 12);
racers.SetValue(new Person { FirstName = "Ralf", LastName = "Schumacher" }, 2, 10);
racers.SetValue(new Person { FirstName = "Fernando", LastName = "Alonso" }, 2, 11);
racers.SetValue(new Person { FirstName = "Jenson", LastName = "Button" }, 2, 12);
Person[,] racers2 = (Person[,])racers;
Person first = racers2[1, 10];
Person last = racers2[2, 12];
可以获取片段,传入使用片段不需要加起始偏移和个数了。
namespace ArraySegmentSample { class Program { static void Main() { int[] ar1 = { 1, 4, 5, 11, 13, 18 }; int[] ar2 = { 3, 4, 5, 18, 21, 27, 33 }; var segments = new ArraySegment<int>[2] { // 对arg1,起始0,数量为3 new ArraySegment<int>(ar1, 0, 3), // 对arg2,起始3,数量为3 new ArraySegment<int>(ar2, 3, 3) }; var sum = SumOfSegments(segments); Console.WriteLine("sum of all segments: {0}", sum); } static int SumOfSegments(ArraySegment<int>[] segments) { int sum = 0; foreach (var segment in segments) { for (int i = segment.Offset; i < segment.Offset + segment.Count; i++) { sum += segment.Array[i]; // 如果改变了值会直接反应到原数组中 segment.Array[i] = 100; } } return sum; } } }
数组和元组排序可用:IStructuralComparable
相等判断可用:IStructuralEquatable
判断排序:
因为Sort函数要求调用泛型类型的CompareTo<T>方法,如果是默认类型的就不用处理,如果是自定义类型那么要继承IComparable<T>接口,实现CompareTo<T>方法:
public class Person : IComparable<Person> { // this相比other,小于返回负数,等于返回0,大于返回正数 public int CompareTo(Person other) { if (other == null) throw new ArgumentNullException("other"); int result = this.LastName.CompareTo(other.LastName); if (result == 0) { result = this.FirstName.CompareTo(other.FirstName); } return result; } }
public class PersonComparer : IComparer<Person> { public int Compare(Person x, Person y) { if (x == null) throw new ArgumentNullException("x"); if (y == null) throw new ArgumentNullException("y"); switch (compareType) { case PersonCompareType.FirstName: return x.FirstName.CompareTo(y.FirstName); case PersonCompareType.LastName: return x.LastName.CompareTo(y.LastName); default: throw new ArgumentException( "unexpected compare type"); } } }调用时候:
相等判断:
一般重写Object的Equal就可以。如果要比较对象数组那么需要,强转为IStructuralEquatable使用Equals方法,使用实例化EqualityComparer泛型,泛型类型实现IEquatable接口,重写Equals方法,因为Object也有该方法,所以需要new关键字修饰下。
实例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Wrox.ProCSharp.Arrays { public class Person : IEquatable<Person> { public int Id { get; private set; } public string FirstName { get; set; } public string LastName { get; set; } public override string ToString() { return String.Format("{0}, {1} {2}", Id, FirstName, LastName); } // 一般情况下判断是否相等,重载Object类型的Equals就可以了,不需要转换到IStructuralEquatable类型 // 实现IEquatable接口方法 public override bool Equals(object obj) { throw new Exception("xx"); if (obj == null) throw new ArgumentNullException("obj"); return Equals(obj as Person); } public override int GetHashCode() { return Id.GetHashCode(); } #region IEquatable<Person> Members public bool Equals(Person other) { if (other == null) throw new ArgumentNullException("other"); bool bEqual1 = this.FirstName == other.FirstName; bool bEqual2 = this.LastName == other.LastName; return bEqual1 && bEqual2; } #endregion } } using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace Wrox.ProCSharp.Arrays { class TupleComparer : IEqualityComparer { #region IEqualityComparer Members public new bool Equals(object x, object y) { return x.Equals(y); } public int GetHashCode(object obj) { return obj.GetHashCode(); } #endregion } class Program { static void Main() { var janet = new Person { FirstName = "Janet", LastName = "Jackson" }; var janet2 = new Person { FirstName = "Janet", LastName = "Jackson" }; Person[] persons1 = { new Person { FirstName = "Michael", LastName = "Jackson" }, janet }; Person[] persons2 = { new Person { FirstName = "Michael", LastName = "Jackson" }, janet }; if (persons1 != persons2) Console.WriteLine("not the same reference"); // 继承自Object的Equals对象使用时OK,如果是对象数组使用就有问题了 if (!janet.Equals(janet2)) { Console.WriteLine("janet equals returns false - not the same reference"); } else { Console.WriteLine("janet equals returns true, the same reference"); } if (!persons1.Equals(persons2)) Console.WriteLine("persons equals returns false - not the same reference"); // 需要强转为IStructuralEquatable类型,IStructuralEquatable类型的Equals会调用EqualityComparer // EqualityComparer会检查泛型类Person是否继承了IEquatable接口实现了Equals方法,没有则调用Object的方法 if ((persons1 as IStructuralEquatable).Equals(persons2, EqualityComparer<Person>.Default)) { Console.WriteLine("the same content"); } var t1 = Tuple.Create<int, string>(1, "Stephanie"); var t2 = Tuple.Create<int, string>(1, "Stephanie"); if (t1 != t2) Console.WriteLine("not the same reference to the tuple"); // 就是一个对象,所以直接调用正确 if (t1.Equals(t2)) Console.WriteLine("equals returns true"); // 强转为IStructuralEquatable,调用Equals会要求被比较的参数传入一个TupleComparer对象,使用TupleComparer中 // 定义的Equals方法,没有则使用父类的Equals. if ((t1 as IStructuralEquatable).Equals(t2, new TupleComparer())) { Console.WriteLine("yes, using TubpleComparer"); } } } }
使用见:
if ((persons1 as IStructuralEquatable).Equals(persons2, EqualityComparer<Person>.Default))
元组Tuple就是一个可以存放不同类型的数组容器,暂时觉得作用不大,存放凌乱难以维护,如果是需要函数式编程的话作用会比较大。
8个泛型个数类型的Tuple和一个静态类型的Tuple::Create可以创建需要的元组,方法元组元素用tupbleObj.ItemX。