• 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新增的,不仅可以比较引用,还可以比较内容。

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

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

  • 相关阅读:
    第二天第三课:03-reques_header_two
    第二天第二节:02-request_header
    爬虫第二天第一课:01-get_params2
    爬虫第三天第二课:02-auth-use用户密码认证
    爬虫第三天:01-money-proxy-handler代理池
    设计模式(C#)——07装饰者模式
    设计模式(C#)——06桥接模式
    设计模式(C#)——05适配器模式
    设计模式(C#)——04原型模式
    设计模式(C#)——03建造者模式
  • 原文地址:https://www.cnblogs.com/KevinG/p/3533209.html
Copyright © 2020-2023  润新知