C#数组特性

1.C#数组基本特性

1)数组是存储的引用,引用的元素存放在托管堆,如果元素是值类型任意初始化方式都可以,如果元素是引用类型那么初始化时侯元素要new出来。

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];

2.数组片段ArraySegment对象

可以获取片段,传入使用片段不需要加起始偏移和个数了。

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;
        }
    }
}

3.数组的比较

数组和元组排序可用: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;
        }
}

调用时候:
 Array.Sort(persons);

也可以继承IComparer<Person>,实现public int Compare(Person x, Person y)函数。
例如:

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");
            }
        }
}
调用时候:
Array.Sort(persons, new PersonComparer(PersonCompareType.FirstName));


相等判断:
一般重写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))

4.元组

元组Tuple就是一个可以存放不同类型的数组容器,暂时觉得作用不大,存放凌乱难以维护,如果是需要函数式编程的话作用会比较大。
8个泛型个数类型的Tuple和一个静态类型的Tuple::Create可以创建需要的元组,方法元组元素用tupbleObj.ItemX。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值