同一类型和不同类型的多个对象

使用同一类型的多个对象,使用集合和数组。

使用不同类型的多个对象,使用Tuple(元组)。

初始化数组

int[] myArray = new int[];

myArray 存放在栈中,而 myArray 的内容 放在 托管堆。

声明数组后,必须为数组分配内存,以保存数组的所有的元素。数组是引用类型,必须给它分配堆上的内存。

如果不知道数组包括多少元素,可以使用集合。

还可以用数组初始化器。

int[] myArray = new int[]{,,,};

访问数组

myArray[] = ;
myArray[] = ;

如果使用错误的索引值,会抛出 IndexOutOfRangeException 错误。

遍历数组

int[] myArray = new int[]{,,,};
for (int i = ; i < myArray.Length; i++)
{
Console.WriteLine("{0}",myArray[i]);
}
int[] myArray = new int[]{,,,};
foreach (int val in myArray)
{
Console.WriteLine("{0}",val);
}

foreach 语句利用了本章 IEnumerable 和 IEnumerator 接口。

使用引用类型

Person[] myPersons = new Person[];
myPersons[] = new Person() {FirstName = "FirstName1", LastName = "LastName1"};
myPersons[] = new Person() { FirstName = "FirstName2", LastName = "LastName2" };
Person[] myPersons =
{
new Person {FirstName = "FirstName1", LastName = "LastName1"},
new Person {FirstName = "FirstName2", LastName = "LastName2"}
};

多维数组

int[,] mInts = new int[,];
mInts[, ] = ;
mInts[, ] = ;
mInts[, ] = ;
mInts[, ] = ;
int[,] mInts =
{
{, },
{, },
{, },
{, }
};

当然还可以声明三维数组

int[,,] mInts = new int[,,];
mInts[, , ] = ;
mInts[, , ] = ;
mInts[, , ] = ;
mInts[, , ] = ;
mInts[, , ] = ;
mInts[, , ] = ;
mInts[, , ] = ;
mInts[, , ] = ;
int[,,] mInts =
{
{{, }, {, }},
{{, }, {, }},
{{, }, {, }}
};

锯齿数组

int[][] jagged = new int[][];

在初始化锯齿数组是,只在第1对方括号中设置该数组包含的行数。定义各行中元素个数的第2个方括号设置为空,让数组每行包含不同元素个数,之后指定行中元素个数。

int[][] jagged = new int[][];
jagged[] = new int[] {, };
jagged[] = new int[] {, , };
jagged[] = new int[] {, , , };

Array类

方括号声明数组, 实际上派生一个自抽象基类Array新类。foreach语句迭代数组,实际就是调用 Array中的 GetEnumerator()。

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

Array.Rank 获得数组的维数。

创建数组

Array intArray1 = Array.CreateInstance(typeof(int),);
for (int i = ; i < ; i++)
{
intArray1.SetValue( + i,i);
} for (int i = ; i < ; i++)
{
Console.WriteLine(intArray1.GetValue(i));
} int[] intArray2 = (int[]) intArray1;

创建多维数组

int[] lengths = {, };
int[] lowerBounds = {, };
Array racers = Array.CreateInstance(typeof(Person),lengths,lowerBounds);

复制数组

数组实现ICloneable接口,然后调用Clone返回浅副本。

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

copy必须传递足够元素的数组。

有时也需要深度克隆,但克隆的时候,要仔细思考一下,是否真的需要克隆。

排序

int[] intArray1 = {, , };
Array.Sort(intArray1);
foreach (var i in intArray1)
{
Console.WriteLine(i);
}

如果数组是自定义类,那么类就要实现Icomparable接口

public class Person: IComparable<Person>
{ public string FirstName { get; set; }
public string LastName { get; set; } public int CompareTo(Person other)
{
if (other == null) return ;
int result = String.CompareOrdinal(this.LastName, other.LastName);
if (result == )
{
result = String.CompareOrdinal(this.FirstName, other.FirstName);
}
return result;
} public override string ToString()
{
return String.Format("{0} {1}",FirstName,LastName);
}
}

对象相等,方法返回0。小于 返回 小于0的值 ,大于返回 大于0的值。

如果不能修改类,还可以新类里 实现 IComparer 或 IComparer<T> 实现接口。

public enum PersonCompareType
{
FirstName,
LastName
} public class PersonComparer : IComparer<Person>
{
private PersonCompareType compareType; public PersonComparer(PersonCompareType compareType)
{
this.compareType = compareType;
} #region IComparer<Person> Members public int Compare(Person x, Person y)
{
if (x == null) throw new ArgumentNullException("x");
if (y == null) throw new ArgumentNullException("y"); switch (compareType)
{
case PersonCompareType.FirstName:
return String.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal);
case PersonCompareType.LastName:
return String.Compare(x.LastName, y.LastName, StringComparison.Ordinal);
default:
throw new ArgumentException(
"unexpected compare type");
}
} #endregion
}
Array.Sort(persons,
new PersonComparer(PersonCompareType.FirstName)); foreach (Person p in persons)
{
Console.WriteLine(p);
}

数组协变

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

static void TestArray(object[] objects)

这里就可以传入 Person[] 参数进去了。

注意,数组协变只能用于引用类型,不能用于值类型。另外如果object[],被赋予了 Person[] 。就不能赋值其他类型的值了,否则运行时,会出现 ArrayTypeMismatchException 的异常。

ArraySegment<T>

ArraySegment表示数组的一部分。

static void Main(string[] args)
{
int[] ar1 = {, , , , , , };
int[] ar2 = { , , , , , , }; ArraySegment<int>[] setmentInts = new ArraySegment<int>[]
{
new ArraySegment<int>(ar1,,),
new ArraySegment<int>(ar2,,),
}; int sum = SumOfSegments(setmentInts);
Console.WriteLine(sum);
} static int SumOfSegments(ArraySegment<int>[] segments)
{
int sum = ;
foreach (var segment in segments)
{
//for (int i = segment.Offset; i < segment.Offset + segment.Count; i++)
//{
// sum += segment.Array[i];
//} foreach (var value in segment)
{
sum += value;
}
}
return sum;
}

数组段不复制原数组的元素,但原数组可以通过ArraySegment<T>访问。如果数组段的元素改变了,这些变换就会反映到原数组中。

枚举

数组或集合实现带 GetEumerator方法的IEumerable 接口。 GetEumberator 方法返回一个实现Ieumerable 接口的枚举。然后 foreach语句就可以使用Ieumerable接口迭代集合。

IEnumerator接口

foreach使用IEnumerator接口的方法和属性,迭代集合中的所有方法。为此,IEnumerator定义了Current属性,来返回光标所在的元素,该接口的MoveNext()方法移动到集合的下一个元素上,如果有这个元素,该方法就返回true。如果集合不再有更多的元素,该方法返回false。

这个接口的泛型版本IEnumerator<T> 派生字接口 IDispose ,因此定义了 Dispose 方法,来清空枚举器占用的资源。

IEnumerator 接口还定义了 Reset() 方法,以与 COM 交互操作。

foreach语句

C#的 foreach 语句 不会解析为 IL代码中的 foreach语句。 C#编译器会把 foreach语句转换为 IEnumerator接口的方法和属性。

foreach (var value in ar1)
{
Console.WriteLine(value);
}

解析为

int[] ar1 = {, , , , , , };
int[] ar2 = { , , , , , , }; IEnumerator enumerator = ar1.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}

yield

yield可以创建枚举器,yield return语句返回集合一个元素,并移动到下一个元素上。yield break 可停止迭代。

public class SimpleConllection : IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
yield return "Hello";
yield return "World";
} IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
} static void Main(string[] args)
{
SimpleConllection simpleConllection = new SimpleConllection();
foreach (string s in simpleConllection)
{
Console.WriteLine(s);
}
}

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

使用迭代块,编译器会生成 yield 类型,其中包含一个状态机,代码如下

public class SimpleConllection
{
public IEnumerator GetEnumerator()
{
return new Enumerator();
} 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 :
current = "Hello";
state = ;
return true;
case :
current = "World";
state = ;
return true;
case :
break;
}
return false;
} public void Dispose()
{ } public void Reset()
{ } public string Current { get; private set; } object IEnumerator.Current
{
get { return current; }
}
}
}

yield 语句 会生成一个枚举器,而不仅仅生成一个包含的项的列表。这个枚举器通过 foreach 语句调用。foreach中访问每一项是,就会访问枚举器。这样迭代大数据时,无须一次把所有的数据读入内存。

元组

数组存储相同类型的对象,元组存放不同类型的对象。.net 4.0 中 定义了 8个泛型Tuple类和一个静态Tuple类。用于创建Tuple。

http://blog.csdn.net/limlimlim/article/details/7835926

private static Tuple<int, int> Divide(int dividend, int divisor)
{
return Tuple.Create<int, int>(dividend, divisor);
} static void Main(string[] args)
{
Tuple<int, int> result = Divide(, );
Console.WriteLine("result of divison:{0}," +
"reminder:{1}", result.Item1, result.Item2);
}

当然 元组 还可以套用 元组。

http://blog.csdn.net/limlimlim/article/details/7835926

数组和元组 都实现了 IStructuralComparable,IStructuralEquatable 接口。

IStructuralEquatable 用于比较两个元组或数组是否有相同的内容。

IStructuralEquatable 用于元组或数组排序。

Tuple 也提供了 Equals

http://www.tuicool.com/articles/iqMv2i

C# 数组(5) 持续更新的更多相关文章

  1. 学习Swift -- 数组(Array) - 持续更新

    集合类型--数组 Array是Swift中的一种集合类型:数组,数组是使用有序列表储存同一类型的多个值,与OC的NSArray的最大不同是,Swift的数组是值类型,OC的数组是引用类型 声明数组的方 ...

  2. PHP开发过程中数组汇总 [ 持续更新系列 ]

    开发过程中经常会使用到数组函数,故特地总结出来,自己熟悉,同时供大家参考!(实例部分会抽空尽快完成) 一.目录 array_merge(); 合并数组 array_keys(); array_filt ...

  3. 前端深入之js篇丨Array数组操作从入门到成神Up Up Up,持续更新中

    写在前面 随着前端深入的不断学习,发现数组这个数据结构在前端中有着相当大的存在感,由于我初学前端的时候并没有系统性的学习数组,所以我将通过这篇文章同你一起学习数组,希望我们能一起进步,学会熟练操作数组 ...

  4. iOS开发系列文章(持续更新……)

    iOS开发系列的文章,内容循序渐进,包含C语言.ObjC.iOS开发以及日后要写的游戏开发和Swift编程几部分内容.文章会持续更新,希望大家多多关注,如果文章对你有帮助请点赞支持,多谢! 为了方便大 ...

  5. 总结js常用函数和常用技巧(持续更新)

    学习和工作的过程中总结的干货,包括常用函数.常用js技巧.常用正则表达式.git笔记等.为刚接触前端的童鞋们提供一个简单的查询的途径,也以此来缅怀我的前端学习之路. PS:此文档,我会持续更新. Aj ...

  6. ( 译、持续更新 ) JavaScript 上分小技巧(四)

    后续如有内容,本篇将会照常更新并排满15个知识点,以下是其他几篇译文的地址: 第一篇地址:( 译.持续更新 ) JavaScript 上分小技巧(一) 第二篇地址:( 译.持续更新 ) JavaScr ...

  7. ( 译、持续更新 ) JavaScript 上分小技巧(三)

    最近家里杂事较多,自学时间实在少的可怜,所以都在空闲时间看看老外写的内容,学习之外顺便翻译分享~等学习的时间充足些再写写自己的一些学习内容和知识点分析(最近有在接触的:复习(C#,SQL).(学习)T ...

  8. ( 译、持续更新 ) JavaScript 上分小技巧(二)

    考虑到文章过长,不便于阅读,这里分出第二篇,如有后续,每15个知识点分为一篇... 第一篇地址:( 译.持续更新 ) JavaScript 上分小技巧(一) 第三篇地址:( 译.持续更新 ) Java ...

  9. ( 译、持续更新 ) JavaScript 上分小技巧(一)

    感谢好友破狼提供的这篇好文章,也感谢写这些知识点的作者们和将他们整理到一起的作者.这是github上的一篇文章,在这里本兽也就只做翻译,由于本兽英语水平和编程能力都不咋地,如有不好的地方也请多理解体谅 ...

  10. 关于ASP.NET MVC开发设计中出现的问题与解决方案汇总 【持续更新】

    最近一直用ASP.NET MVC 4.0 +LINQ TO SQL来开发设计公司内部多个业务系统网站,在这其中发现了一些问题,也花了不少时间来查找相关资料或请教高人,最终都还算解决了,现在我将这些问题 ...

随机推荐

  1. HIVE配置mysql metastore

    HIVE配置mysql metastore    hive中除了保存真正的数据以外还要额外保存用来描述库.表.数据的数据,称为hive的元数据.这些元数据又存放在何处呢?    如果不修改配置hive ...

  2. logstash1 - kafka - logstash2 - elasticsearch - kibana

    0.拓扑图 参考:https://www.cnblogs.com/JetpropelledSnake/p/10057545.html 1.logstash的配置 [root@VM_0_4_centos ...

  3. IOS div上下滑动效果

    内容放在div中 div加样式:width: 100%;height: 100%;z-index: 70;overflow: auto;

  4. linux 系统自签免费ssl证书和nginx配置

    首先执行如下命令生成一个key openssl genrsa -des3 -out ssl.key 1024 然后他会要求你输入这个key文件的密码.不推荐输入.因为以后要给nginx使用.每次rel ...

  5. 【AtCoder】ARC059

    为啥这场ARC那么水--一个点就切完了 ARC059 C - いっしょ / Be Together 枚举就行 #include <bits/stdc++.h> #define fi fir ...

  6. codeforces 1249C1 + 1249C2 (贪心)

    (点击此处查看原题) 题意分析 给出一个数n,求一个数m,使得m >= n ,并且m 满足: m = ∑ 3 ^ i * x (x = 0 或者 x = 1 ),求出满足条件的最小的m 解题思路 ...

  7. Redis 使用指南:深度解析 info 命令

    Redis 是一个使用  ANSI C 编写的开源.基于内存.可选持久性的键值对存储数据库,被广泛应用于大型电商网站.视频网站和游戏应用等场景,能够有效减少数据库磁盘 IO, 提高数据查询效率,减轻管 ...

  8. C# DataTable根据字段排序

    DataTable dt = new DataTable(); dt.Columns.Add("Name"); dt.Columns.Add("Age");// ...

  9. BASE64 Encode Decode

    package com.humi.encryption; import java.io.IOException; import java.io.UnsupportedEncodingException ...

  10. Javascript中的继承与复用

    实现代码复用的方法包括:工厂模式.构造函数模式.原型模式(<高三>6.2章 P144),它们各自的特点归结如下:1.工厂模式虽然使创建对象一定程度上实现了代码复用,但却没有解决对象识别问题 ...