C# 数组(5) 持续更新
同一类型和不同类型的多个对象
使用同一类型的多个对象,使用集合和数组。
使用不同类型的多个对象,使用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) 持续更新的更多相关文章
- 学习Swift -- 数组(Array) - 持续更新
集合类型--数组 Array是Swift中的一种集合类型:数组,数组是使用有序列表储存同一类型的多个值,与OC的NSArray的最大不同是,Swift的数组是值类型,OC的数组是引用类型 声明数组的方 ...
- PHP开发过程中数组汇总 [ 持续更新系列 ]
开发过程中经常会使用到数组函数,故特地总结出来,自己熟悉,同时供大家参考!(实例部分会抽空尽快完成) 一.目录 array_merge(); 合并数组 array_keys(); array_filt ...
- 前端深入之js篇丨Array数组操作从入门到成神Up Up Up,持续更新中
写在前面 随着前端深入的不断学习,发现数组这个数据结构在前端中有着相当大的存在感,由于我初学前端的时候并没有系统性的学习数组,所以我将通过这篇文章同你一起学习数组,希望我们能一起进步,学会熟练操作数组 ...
- iOS开发系列文章(持续更新……)
iOS开发系列的文章,内容循序渐进,包含C语言.ObjC.iOS开发以及日后要写的游戏开发和Swift编程几部分内容.文章会持续更新,希望大家多多关注,如果文章对你有帮助请点赞支持,多谢! 为了方便大 ...
- 总结js常用函数和常用技巧(持续更新)
学习和工作的过程中总结的干货,包括常用函数.常用js技巧.常用正则表达式.git笔记等.为刚接触前端的童鞋们提供一个简单的查询的途径,也以此来缅怀我的前端学习之路. PS:此文档,我会持续更新. Aj ...
- ( 译、持续更新 ) JavaScript 上分小技巧(四)
后续如有内容,本篇将会照常更新并排满15个知识点,以下是其他几篇译文的地址: 第一篇地址:( 译.持续更新 ) JavaScript 上分小技巧(一) 第二篇地址:( 译.持续更新 ) JavaScr ...
- ( 译、持续更新 ) JavaScript 上分小技巧(三)
最近家里杂事较多,自学时间实在少的可怜,所以都在空闲时间看看老外写的内容,学习之外顺便翻译分享~等学习的时间充足些再写写自己的一些学习内容和知识点分析(最近有在接触的:复习(C#,SQL).(学习)T ...
- ( 译、持续更新 ) JavaScript 上分小技巧(二)
考虑到文章过长,不便于阅读,这里分出第二篇,如有后续,每15个知识点分为一篇... 第一篇地址:( 译.持续更新 ) JavaScript 上分小技巧(一) 第三篇地址:( 译.持续更新 ) Java ...
- ( 译、持续更新 ) JavaScript 上分小技巧(一)
感谢好友破狼提供的这篇好文章,也感谢写这些知识点的作者们和将他们整理到一起的作者.这是github上的一篇文章,在这里本兽也就只做翻译,由于本兽英语水平和编程能力都不咋地,如有不好的地方也请多理解体谅 ...
- 关于ASP.NET MVC开发设计中出现的问题与解决方案汇总 【持续更新】
最近一直用ASP.NET MVC 4.0 +LINQ TO SQL来开发设计公司内部多个业务系统网站,在这其中发现了一些问题,也花了不少时间来查找相关资料或请教高人,最终都还算解决了,现在我将这些问题 ...
随机推荐
- list集合的一些小见解
关于LIst集合 前言: 第一次写博客,有些东西可能总结的到位,发表一下自己的一些观点,欢迎大佬们点评和指教 正文: list集合可以分为ArrayLlst和LinkedList. ArrayList ...
- python解析html
*参考 推荐BeautifulSoup http://blog.csdn.net/abclixu123/article/details/38502993 http://www.cnblogs.com/ ...
- Docker下mysql容器开启binlog日志(保留7天)
现有需求开启用Docker容器启动的mysql数据库的binlog,以作为 日志记录 和 数据恢复,我们了解了MySQL的binlog日志的开启方式以及binlog日志的一些原理和常用操作,我们知道, ...
- NOIP比赛中如何加速c++的输入输出
NOIP比赛中如何加速c++的输入输出 在竞赛中,遇到大数据时,往往需要更快的读取方式.由于比赛中输出一般规模较小,本文只讨论输入如何加速. 现在我们生成1000000个随机数,构成1000*1000 ...
- Python 【格式化字符串】
print('血量:'+str(player_life)+' 攻击:'+str(player_attack)) 第一种格式化字符串 print('血量:%s 攻击:%s' % (player_life ...
- k8s-traefik默认80端口
vim traefik.yaml kind: Deployment apiVersion: extensions/v1beta1 metadata: name: traefik-ingress-con ...
- 浅谈后缀数组SA
这篇博客不打算讲多么详细,网上关于后缀数组的blog比我讲的好多了,这一篇博客我是为自己加深印象写的. 给你们分享了那么多,容我自私一回吧~ 参考资料:这位dalao的blog 一.关于求Suffix ...
- 3037 插板法+lucas
先说下lucas定理 1)Lucas定理:p为素数,则有: (2)证明: n=(ak...a2,a1,a0)p = (ak...a2,a1)p*p + a0 = [n/p]*p+a0 (注意 这里( ...
- C#通讯框架改写
现有项目是利用C#的socket与PLC进行实时通讯,PLC有两种通讯模式——常规采集&高频采集. 其中常规采集大概在10ms左右发送一次数据,高频采集大概在2ms左右发送一次数据. 现有代码 ...
- 在开源UOJ的导航栏中添加新页面链接
前言 刚用开源UOJ搭建OJ成功时就想在导航栏那里添加一个站内页面链接,无奈当时乱搞水平低,网上也没有教程,不晓得怎么弄 今天突然来了闲情乱搞一通,结果还真乱搞成了...特意写下为后来人少走点弯路 前 ...