第七,八,九,十天
(最近几天因为课程设计原因耽误了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)
(最近几天因为课程设计原因耽误了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)