《C#高级教程》学习笔记7

来源:互联网 发布:武汉软件新城 编辑:程序博客网 时间:2024/05/18 00:18
第七,八,九,十天
(最近几天因为课程设计原因耽误了C#学习进程,刚花了大量精力干掉课程设计,然后又花了挺多时间玩游戏看漫画来恢复精力,正当准备努力学习的时候,同学却来找我一起挑战做手机游戏来参加比赛,然后关于游戏类型与主题讨论了很长时间,于是学习便呵呵掉了,之后还要花时间去研究安卓,真是作死的节奏了)

CreateInstance()方法还有很多重载版本,可创建多维数组及不基于0的数组
int[] length={2,3};
int[] lowerBounds={1,10};
Array racers=Array.CreateInstance(typeof(Person),length,lowerBounds);
racers.SetValue(new Person{
    FirstName="A";
    SecondName="B";
},1,10);

6.5.2复制数组
数组是引用类型,直接赋值只是两个引用而且。
复制数组,会使数组实现ICloneable接口。这个接口定义的Clone()方法会创建数组的浅表副本。
int[] intArray1={1,2};
int[] intArray2=(int[])intArray1.Clone();
数组里有引用无素,则只复制引用,不复制元素
还可以使用Array.Copy()方法创建浅表副本。与Clone()方法的区别:Clone()会创建一个新数组,Copy()方法必须传递阶数相同用有足够元素的已有数组。

6.5.3排序
Array类使用QuickSort算法对数组中的元素进行排序。
Sort()方法需要数组中的元素实现IComparable接口。
对数组使用自定义类,则该类必须实现IComparable接口,此接口里只定义了一个方法CompareTo(),方法返回0。该实例对象应排在参数对象的前面则返回小于0的值,
相反则大于0
不能修改在数组中用作元素的类,就可以实现IComparer接口或IComparer<T>接口。这两个接口定义了方法Compare()。
IComparer接口独立于要比较的类。
Array.sort()时,第一个参为数组,第二个为new的比较器

6.6数组作为参数
public void A(Person[] person){}
public Person[] B(){}

6.6.1数组协变
数组支持协变,这表示数组可以声明为基类,其派生类型的元素可以赋予数组元素。
static void DisplayArray(object[] data){}

6.6.2 ArraySegment<T>
结构ArraySegment<T>表示数组的一段。把数组部分复制到方法去。
传参时:
(ArraySegment<int>[] segments)
之类
用例:
int[] ar1={1,4,5,11,13,18};
int[] ar2={3,4,5,18,21,27,33};
var segments = new ArraySegment<int>(2){
    new ArraySegment<int>(ar1,0,3),
    new ArraySegment<int>(ar2,3,3)
}

6.7枚举
foreach,可以迭代集合中的元素,且无需知道集合中的元素个数。
数组或集合实现带GetEnumerator()方法的IEnumerable接口。
GetEnumerator()方法返回一个实现IEnumerable接口的枚举。
接着,foreach语句就可以使用IEnumerable接口迭代集合。

6.7.1 IEnumerator接口
foreach语句作用IEnumerator接口的方法和属性,迭代集合中的所有元素。
为此IEnumerator定义了Current属性来返回光标所在的元素,
该接口的MoveNext()方法,移动到集合的下一个元素上,如果有这个元素就返加true,否则false。
IEnumerator<T>派生自接口IDisposable,因此定义了Dispose()方法来清理枚学会举器占用的资源。

6.7.2 foreach语句
C#的foreach语句不会解析为IL代码中的foreach语句。
foreach(var p in persons){
    Console.WriteLine(p);
}
解析:
IEnumerator<Person> enumerator=persons.GetEnumerator();
while(enumerator.MoveNext()){
    Person p=enumerator.Current();
    Console.WriteLine(p);
}

6.7.3 yield语句
yield语句返回集合的一个元素,并移动到下一个元素,yield break可停止迭代。
例:
using System;
using System.Collections;
namespace Wrox.ProCShape.Arrays{
    public class HelloCollection{
        public IEnumerator<String> GetEnumerator(){
            yield return "Hello";
            yield return "World";
        }
    }
}
然后用foreach迭代语句
使用迭代块,编译器会生成一个yield类型,其中包含一个状态机,如下面的代码段所示。
public class HelloCollection{
    public IEnumerator GetEnumerator(){
        return new Enumerator(0);
    }
}
public class Enumerator:IEnumerator<string>,IEnumerator,IDisposable{
    private int state;
    private string current;
    public Enumerator(int state){
        this.state=state;
    }
    bool System.Collections.IEnumerator.MoveNext(){
        switch(state){
        case 0:
            current="Hello";
            state=1;
            return true;
        case 1:
            current="World";
            state=2;
            return true;
        }
        return false;
    }
    void System.Collections.IEnumerator.Reset(){
        throw new NotSupportedException();
    }
    string System.Collections.Generic.IEnumerator<string>.Current{
        get{
            return current;
        }
    }
    object System.Collections.IEnumerator.Current{
        get{
            return current;
        }
    }
    void IDisposable.Dispose(){}
}
1.迭代集合的不同方式
例:
public class MusicTitles{
    string[] names={"A","B","C","D"};
    public IEnumerator<string> GetEnumerator(){
        for(int i=0;i<4;i++){
            yeild return name[i];
        }
    }
    public IEnumerable<string> Reverse(){
        for(int i=3;i>=0;i--){
            yeild return name[i];
        }
    }
    public IEnumerable<string> Subset(int index,int length){
        for(int i=index;i<index+length;i++){
            yield return name[i];
        }
    }
}
用:
var titles=new MusicTitles();
foreach(var title in titles){
    Console.WriteLine(title);
}
Console.WriteLine("reverse");
foreach(var title in titles.Reverse()){
    Console.WriteLine(title);
}
Console.WriteLine("subset");
foreach(var title in titles.Subset(2,2)){
    Console.WriteLine(title);
}

2.用yield return返回枚举器
public class GameMove{
    private IEnumerator cross;
    private IEnumerator circle;
    private GameMove{
        cross=Cross();
        circle=Circle();
    }
    private int move=0;
    private int MaxMoves=0;
    public IEnumerator Cross(){
        while(true){
            Console.WriteLine("Cross,move{0}",move);
            if(++move>=MaxMoves)
                yield break;
            yield return circle;
        }
    }
    public IEnumerator Circle(){
        while(true){
            Console.WriteLine("Circle,move{0}",move);
            if(++move>=MaxMoves)
                 yield break;
             yield return cross;
        }
    }
}

var game=new GameMove();
IEnumerator enumerator=game.Cross();
while(enumerator.MoveNext()){
    enumerator=enumerator.Current as IEnumerator;
}
输出:
Cross,move 0
Cicle,move 1
Cross,move 2
Cicle,move 3
Cross,move 4
Cicle,move 5
Cross,move 6
Cicle,move 7
Cross,move 8

6.8元组
数组合并了相同类型的对象,而元组合并了不同类型的对象。
在.NET Framework中,元组可用于所有的.NET语言。
.NET Framework定义了8个泛型Tuple类(自.NET4.0以来)和一个静态Tuple类。
不同泛型Tuple类支持不同数量的元素。如Tuple<T1>包含一个元素,Tuple<T1,T2>包含两个元素,以此类推。
例:
public static Tuple<int,int> Divide(int dividend,int divisor){
    int result=dividend/divisor;
    int reminder=dividend%divisor;
    return Tuple.Create<int,int>(result,reminder);
}
调用:
var result=Divide(5,2);
Console.WriteLine("{0},{1}",result.Item1,result.Item2);
如果元组包含的项超过8个,就可以使用带8个参数的Tuple类定义。最后一个传元组。
public class Tuple<T1,T2,T3,T4,T5,T6,T7,TRest>

(2014.12.12 158页,还有1517-158=1359)
0 0
原创粉丝点击