zoukankan      html  css  js  c++  java
  • C#高编

    1.简单数组:

    如果需要使用同一类型的多个对象,就可以使用数组。数组是引用类型,所以必须给它分配堆上的内存,为此,应使用new运算符。

    数组的声明方式:

    int[] myArray;
    myArray = new int[4];
    或
    int[] myArray = new int[4];
    或
    int[] myArray = new int[4]{4,7,11,2};//初始化器只能在声明变量时使用,不能再声明数组之后使用
    int[] myArray = new int[]{4,7,11,2};//编译器会自动统计元素个数
    int[] myArray = {4,7,11,2};

    声明自定义类型的数组:

    public class Person
    {
        public string FirstName{get;set;}
        public string LastName{get;set;}
    
        public override string ToString()
        {
            return String.Format("{0}{1}",FirstName,LastName);
        }
    }
    
    //调用
    Person[] myPersons = new Person[2];

     注意:如果数组中的元素是引用类型,就必须为每个数组元素分配内存。

    myPerson[0] = new Person{FirstName = "Ayrton",LastName = "Senna"};

     也可以对自定义类型使用数组初始化器:

    Person[] myPerson2 = 
    {
        new Person { FirstName = "Ayrton", LastName = "Senna"},
        new Person { FirstName = "Michael",LastName = "Schumacher"}
    };

     2.多维数组

    声明二维数组,需在方括号中加上一个逗号。数组在初始化应指定每一维的大小(也成为阶)。声明数组之后,就不能修改其阶数了。

    nt[,] twodim = new int[3,3];
    twodim[0,0] = 1;twodim[0,1] = 2;twodim[0,2] = 3;
    twodim[1,0] = 4;twodim[1,1] = 5;twodim[1,2] = 6;
    twodim[2,0] = 7;twodim[2,1] = 8;twodim[2,2] = 9;

     如果事先指定元素的值,也可以使用数组索引器来初始化二维数组。

    int[,] twodim = {  {1,2,3},
                       {4,5,6},
                       {7,8,9}
                    };

     声明三维数组

    int[,,] threedim = {
    { { 1, 2 }, { 3, 4 } },
    { { 5, 6 }, { 7, 8 } },
    { { 9, 10 }, { 11, 12 } }
    };

     3.锯齿数组

    锯齿数组相比二维数组,大小设置比较灵活,每一行都可以有不同的大小。

    在声明锯齿数组时,要依次放置左右括号。在初始化时,在第一对方括号中设置该数据包含的行数。定义各行中元素个数的第2个方括号设置为空。

    int[][] jagged = new int[3][];
    jagged[0] = new int[2] { 1,2 };
    jagged[1] = new int[6] { 3,4,5,6,7,8 };
    jagged[2] = new int[3] { 9,10,11 };

    4.Array类

    LongLength属性:如果数组包含的元素个数超出了整数的取值范围,就可以使用其来获得元素的个数。

    Rank属性:可以获得数组的维数。

    Array类是一个抽象类,所以不能使用构造函数来创建数组。但除了可以使用C#语法创建数组实例之外,还可以使用静态方法CreateInstance()创建数组。如果事先不知道元素的类型,则该静态方法就非常有用。

    可以用SetValue()方法设置对应元素的值,用GetValue()方法读取对应元素的值。

    Array intArray1 = Array.CreateInstance(typeof(int),5);
    for(int i = 0; i < 5, i++)
    {
        intArray1.SetValue(33,i);
    }
    
    for(int i = 0; i < 5, i++)
    {
        Console.WriteLine(intArray1.GetValue(i);
    }

    还可以将已创建的数组强制转换成声明为int[]的数组:

    int[] intArray2 = (int[])intArray1;

    CreateInstance()的重载:创建多维数组和不基于0的数组。

    int[] lengths = { 2,3 };//设置长度,2*3个元素的二维数组
    int[] lowerBounds = { 1,10 };//第一维基于1,第二维基于10
    Array racers = Array.CreateInstance(typeof(Person), lengths, lowerBounds);
    //SerValue()方法设置数组的元素,其参数是每一维的索引:
    racers.SetValue(new Person
    {
        FirstName = "Alain",
        LastName = "Prost"
    }, 1, 10);
    racers.SetValue(new Person
    {
        FirstName = "Emerson",
        LastName = "Fittipaldi"
    }, 1, 11);
    ......

    尽管数组不是基于0,但可以用一般的C#表示法将它赋予一个变量。只需注意不要超出边界即可。

    Person[,] racer2 = (Person[,])racers;
    Person first = racers2[1,10];
    Person last = racers2[2,12];

    5.复制数组:

    使用Clone()方法,实现ICloneable接口

    int[] intArray1 = { 1,2 };
    int[] intArray2 = (int[])intArray1.Clone();

    如果数组的元素是值类型,则会复制所有值。

    如果数组包含引用类型,则不复制元素,而只复制引用。

    使用Array.Copy()方法,创建浅表副本。

    二者区别:Clone方法会创建一个新数组,而Copy方法必须传递阶数相同且有足够元素的已有数组。

    4.2排序:

    使用Array.Sort()方法,但需要数组中的元素实现IComparable接口。简单类型(如String和Int32)已实现IComparable接口,所以可以对包含这些类型的元素进行排序。

    string[] names = { "Shakira","Beyonce" };
    Array.Sort(names);

    自定义类实现排序:

    实现IComparable接口的CompareTo()方法,如果比较的对象相等,则该方法返回0,如果该实例应排在参数对象的前面,则返回小于0的值。反之返回大于0的值。

    public class Person:IComparable<Person>
    {
        public int CompareTo(Person other)
        {
            if(other == null) throw new ArgumentNullException("other");
            
            int result = this.LastName.CompareTo(other.LastName);//因为lastName属性是string简单类型,因此具有CompareTo()方法
    
            if(result == 0)
            {
                result = this.FirstName.CompareTo(other.FirstName);
            }
            return result;
        }
        //...
    }

     如果Person对象的排序方式与上述不同,或者不使用为数组中的元素,则可以实现IComparer接口或IComparer<T>接口,定义方法Compare(),它独立于要比较的类,所以需传入两个比较的参数。

     6.数组协变

    数组支持协变,这表示数组可以声明为基类,其派生类型的元素可以赋予数组元素。

    数组协变只能用于引用类型,不能用于值类型。

    7.ArraySegment<T>

    结构ArraySegment<T>表示数组的一段。如果某方法应返回数组的一部分,或者给某方法传递数组的一部分,就可以使用数组段。

    static int SumOfSegments(ArraySegment<int>[] segments)
    {
    ...
    }

     8.枚举

    • 在foreach中使用枚举,可以迭代集合中的元素,且无需知道集合中的元素个数。foreach语句使用了一个枚举器。
    • 数组或集合实现带GetEumerator()方法的IEumerable接口。方法返回一个实现接口的枚举。接着,foreach语句就可以使用接口迭代集合了。
    • foreach语句并不一定需要在集合类中实现这个接口,有一个名为GetEnumerator()的方法,它返回实现了IEnumerator接口的对象就足够了。

    foreach语句:首先,调用GetEnumerator()方法,获得数组的一个枚举器。在while循环中—只要MoveNext()返回true—就用Current属性访问数组中的元素:

    foreach(var p in persons)
    {
        Console.WriteLine(p);
    }

    以上语句解析为下面的代码段

    IEnumerator<Person> enumerator = persons.GetEnumerator();
    while(enumetor.MoveNext())
    {
        Person p = enumerator.Current;
        Colsole.Writeline(p);
    }

    yield语句:返回集合的一个元素,并移动到下一个元素上。yield break可停止迭代。

    包含yield语句的方法或属性也称为迭代块。迭代块可以声明为返回IEnumerator或IEnumerable接口,或者这些接口的泛型版本。可以包含多条yield return语句或yield break语句,但不能包含return语句。

    注:在C#1.0中,使用foreach可以轻松迭代集合,但创建枚举器仍需要做大量工作,C#2.0添加了yield语句,以便于创建枚举器。

    public class HelloCollection
    {
        public IEnumerator<string> GetEnumerator()
        {
            yield return "Hello";
            yield return "World";
        }
    }
    public class MusicTitles
    {
        string[] names = { "Tubular Bells","Hergest Ridge",
    "Ommadawn","Platinum" };
        
        public IEnumerator<string> GetEnumerator()
        {
            for(int i = 0;i<4;i++)
            {
                yield return names[i];
            }
        }
    
        public IEnumerator<string> Reverse()
        {
            for(int i = 3;i>=0;i--)
            {
                yield return names[i];
            }
        }
    
        public IEnumerable<string> Subset(int index,int length)
        {
            for(int i = 0;i<index + length;i++)
            {
                yield return names[i];
            }
        }
    }
    View Code

    类MusicTiltles可以用默认方式迭代集合,用Reverse()方法逆序迭代标题,用Subset() 方法迭代子集。

    迭代字符串数组的客户端代码先使用GetEnumerator()方法,但不必在代码中编写,因为是默认方法。其他方法需要指定。

    var titles = new MusicTitles();
    //正序
    foreach( var title in titles)
    {
        Console.WriteLine(title);
    }
    
    //逆序
    foreach(var title in titles.Reverse())
    {
        Console.WriteLine(title);
    }

    9.元组

    数组合并了相同类型的对象,而元组合并了不同类型的对象。元组起源于函数编程语言(如F#),在这些语言中频繁使用元组。

    .NET4定义了8个泛型Tuple类和一个静态Tuple类,它们用作元组的工厂。不同的Tuple类支持不同数量的元素。如Tuple<T1>包含一个元素,Tuple<T1,T2>包含两个元素。

    10.结构比较

    数组和元祖都实现接口IStructuralEquatable和IStructuralComparable。这两个接口是.NET4新增的,不仅可以比较引用,还可以比较内容。

    这些接口都是显式实现的,所以在使用时需要把数组和元祖强制转换为这个接口。

    接口一用于比较两个元祖或数组是否有相同的内容,接口二用于给元祖或数组排序。

  • 相关阅读:
    C#中 @ 的用法
    ASP.NET页面间传值
    ASP.NET中常用的文件上传下载方法
    把图片转换为字符
    把图片转换为字符
    JavaScript 时间延迟
    Using WSDLs in UCM 11g like you did in 10g
    The Definitive Guide to Stellent Content Server Development
    解决RedHat AS5 RPM安装包依赖问题
    在64位Windows 7上安装Oracle UCM 10gR3
  • 原文地址:https://www.cnblogs.com/KevinG/p/3533209.html
Copyright © 2011-2022 走看看