c#高级编程(第八版)-第六章数组随笔

如果需要使用同一类型的多个对象,就可以使用集合和数组,c#使用特殊句号声明和初始化数组,简单来说需要时使用同一类型的多个对象时,就可以使用数组,数组是一种数据结构。

数组的声明:

 int[] Array;

数组的初始化:

声明数组后必须给数组分配内存,以保存数组的所有元素,数组是引用类型,所以必须给他分配堆上内存,因此使用new运算符。             数组声明的的方式。

int[] Array=new int[];

初始化的三种方式:

int[] Array=new int[4]{1,2,3,4};
int[] Array=new int[]{1,2,3,4};
int[] Array={1,2,3,4};

在声明和初始化数组后就可以使用索引器访问数组的元素了,数组只支持有整型参数的索引器,通过索引便可以访问其中的元素(从0开始)。

int[] Array={1,2,3,4};

Array[0]=1,  Array[3]=4;

如果不知道数组的元素个数可以用Length属性,下面两种也是取数据的方式

for(int i=0;i<Array.length;i++)
{
   int a=Array[i];
}
foreach(int b in Array)
{
   int a=b;
}

引用类型数组

除了能声明预定义类型的数组外,还可以声明自定义类型数组

public class Person
{
  public string FirstName;
   public string LastName;
}

数组声明:

person[] Array=new person[2];

数组初始化::

和int类型一样。

person[]  Array=new person[2]{new person{FirstName="大卫",LastName="菠萝"},new person{FirstName="小卫",LastName=“土豆”}};

其实引用类型的数组和int类型数组一样,只不过把类型换了一下而已。

多维数组

一般数组(一维数组)用一个整数来索引,多维用两个或者多个整数来索引。

二维数组声明

int[,] Array=new int[2,3](代表2行3列的数组)。

二维数组初始化

int[,] Array=new int[]{{1,2},{1,3},{1,4}}//(代表3行2列的数组)。
//取值,索引从0开始
Array[0,0]=1;
Array[0,1]=2;

3维数组及以上,还有锯齿数组都差不多,就不讨论了。

Array类

用方括号声明数组是c#中使用Array类的表示法,在后台使用c#语法,会创建一个派生自抽象基类Array的新类,这样就可以使用Array为每个c#数组定义的方法和属性了,,例如前面使用的Length属性,或者是foreach语句来迭代数组,其实使用了Array类中的GetEnumerator()方法。(我的理解就是数组可以使用Array类中的属性和方法).

Array类实现的其他属性有longlength和rank,longlength表示所有维数中元素的个数,rank表示维数。

Array类是抽象类,所以不能构造函数来创造数组,但是可以用静态方法来CreateInstance()方法来创建数组,如果事先不知道元素类型就很有用,因为类型可以当做参数传进去。

//创建一个类型为int,大小为5的数组
Array IntArray=Array.CreateInstance(typeof(int),5);
//赋值
for(int i=0;i<IntArray.length;i++)
{
    IntArray.SetValue(33,i);//后面i为索引
}
//取值
for(int i=0;i<IntArray.length;i++)
{
    int a= IntArray.GetValue(i);
}

引用数组,锯齿数据,多维数组同样可以用Array.CrueateInstance方法来创建,则不再讨论。

复制数组

因为数组是引用类型,所以将一个数组赋值为另外一个数组,就会等到两个引用同一数组的变量,复制数组会实现ICloneable接口,这个接口定义的Clone()方法会创建数组的浅表副本(我的理解就是 数组 a=数组 b 改变数组a的值,b也会跟着改变,数组 a=数组b.clone()改变a的值不会改变b的值)

排序

Array类使用QuickSort算法对数组中的元素进行排序,Sort()方法需要数组中元素实现Icomparable接口

int[] Array={3,2,1};
Array.sort(Array);
//从小到大排序,则Array里数据排序
Array[0]=1;
Array[1]=2;
Array[2]=2;

引用类型数组排序就不在这里介绍了,没有封装好的方法,需要自己写。

数组作为参数

int[] Array={1,2,3};
static void TestArray(int[] pram)
{
   //....... 函数体
}
//数组协边,即数组也可以声明为基类(通俗点就是object[] 可以传数组)
static void TestArray(object[] pram)//可以传引用类型的数组
{
   //....... 函数体
}

数组协变,只能用于引用类型,不能用于值类型,数组协边有个问题,他只能通过运行时异常来解决,如果把引用数组赋予object[]数组,object数组就可以使用使用派生自object的任何元素。(不建议用object[])。

ArraySegment<T>

结构ArraySegment<T>表示数组的一段,如果需要使用不同的方法处理某个大型方法的不同部分,则需要将相应的部分传到相应的方法中,更有效的是使用一个数组,将整个数组传递到不同方法去。

//举个简单的例子,若有两个不同的数组,选取不同的部分求和,则可以使用Arraysegment
static int SumOfSegment(Arrsegement<int>[] segments)
{
  int sum=0;
 foreach(var segment in segments)
 {
   for(int=segment.offest;i<segment.offset+segment.count;i++)
   {
    sum+=segment.array[i];
   }
 }
  return sum;
}
int[] a={1,2,3,4,5};
int[] b={2,3,4,5,6,7};
//数组a取出索引1,往后数两个数的数(从索引开始算),数组b,取出索引1,往后数3个数的数(从1开始算),a 取出2,3,b取出3,4,5
static void TestSegMent()
{
   ArraySegment<int>[] segments=new ArraySegment<int>[2]{new ArraySegment<int>(a,1,2),new ArraySegment<int>(b,1,3)};//将不同数组的不同部分传入segment中(自我感觉不咋用的到0.0)
   int sum=SumOfSegment(segments);
}

枚举

在foreach语句中使用枚举,可以迭代集合中元素,无须知道集合的个数,foreach使用了一个枚举器。;数组或集合实现带GetEumerator()方法的IEnumerable接口。

Tip:GetEnumerator()方法用IEnumerable接口定义,foreach语句并不真的需要在集合类中实现这个接口,有一个名为GetEnumerator的方法,他返回了实现IEnumerator接口的对象就足够了。

IEnumerator接口

foreach语句使用IEnumerator接口的方法和属性,迭代集合中所有的元素,为此IEnumerator定义了current属性,来返回光标当前所在的元素。该接口的MoveNext()方法移动到集合的下一个元素,如果有这个元素就返回true,如果没有下一个元素则返回false.该接口的泛型版本IEnumerator<T> 接口派生自IDisposable接口,因此定义了Dispose()方法,来清理枚举器产生的资源。

Foreach语句

int[] array={1,2,3,4};
foreach(int a in array)
{
  console,writeline(a)
}
//上面的foreach等价于下面的枚举器
IEnumeator<int> enumerator=array.GetEnumerator()//用getenumerator()方法获得数组的一个枚举器
while(enumerator.movenext())
{
  int p=enumerator.current;
  console.writeline(p);
}

Yield语句

c#2.0添加了yield语句,以便于创建枚举器,yield return语句返回集合的一个元素,并移动到下一个元素上,yield back可以停止迭代。

 //返回hello world 
pubic IEnumerator<string> GetEnumerator()
{
  yield return "Hello";
  yield return "wrold";
}

tip:包含yeild语句的方法和属性也被成为迭代块,迭代块必须声明为返回IEnumerator或者IEnumerable接口,或者这些接口的泛型版本。这个快可以包含多个yeild return和yeild back语句,但是不能包含return语句.

元组

元组的初始化

//元组初始化时应设值否则会报错
Tuple<int,string> tuple=new Tuple<int,string>(1,"2");
//或者下一种
Tuple<int,string> tuple=new Tuple<int,string>(1,"2");

 

数组是和并相同类型的成员,元组是合并不同类型的成员。,net定义了8个泛型的Tuple类和一个静态Tuple类,例如Tuple<T1>包含一个元素,Tuple<T1,T2>包含了两个元素。

public Static Tuple<int,string> Divide(int a,int b)
{
  int result1=a+b;
  int result=(a-b).tostring();
  return Tuple.Create<int,int>(result1,reult2);
}
public static Test()
{
  Tuple<int,string> tuple= Divide();
  int a=tuple.item1;//第一个数
string b=tuple.item2;//第二个数
}

Tip:如果元祖包含的项超过8个,就可以用带8个参数的Tuple类定义,最后一个模板参数是TRest表示必须给它传递一个元组,举个例子

//当元组包含的项超过8个时,最后一个模板必须是元组
var tuple = new Tuple<int, int, int, int, int, int, int, Tuple<int, string>>(1, 1, 1, 1, 1, 1, 1, Tuple.Create<int, string>(1, "2"));
//或者下一种
var tuple2 = new Tuple<int, int, int, int, int, int, int, Tuple<int, string>>(1, 1, 1, 1, 1, 1, 1, new Tuple<int, string>(1,"2"));

(自我感觉元组的使用就是当类中的元素少的时候,可以用元组替代,简化代码)。

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值