C#数据容器
字符串(String)
构造
string str = "this is a string"; //使用字面值初始化;
str = new string(charr_array); //使用字符数组初始化;
str = new string(ch, n); // 重复字符n次;
查找
tf = name.StartsWith("B")
正则表达式
Regex in System.Text.RegularExpressions
Regex.Match()
运算
String
类有很多字符串修改方法,但是String
对象本身是不会改变的;修改的结果由返回值返回,只能对变量进行重新复制,让它指向内存中的另一块区域。
要在源字符串直接做修改,则改用StringBuilder
类。
拼接
使用+
或Concat
方法,将对象的字符串表示(ToString()
)拼接形成一个字符串。
String.Concat(obj1,obj2,...);
String.Concat({obj1,obj2,....})
+
运算符作用对象包含字符串时,作为拼接运算符。
字符串内插
string greeting = 'Hello', firstName = 'Bob';
string message = $"{greeting} {firstName}!";
可以同时使用逐字文本前缀符号
@
和字符串内插$
符号。
格式化
使用格式声明对参数进行格式化并输出字符串。
String.Format("{0}...{1}...", arg1, arg2, ...)
支持格式化语法的类似方法包括:
StringBuilder.AppendFormat
、Console.WriteLine
、TextWriter.WriteLine
、Debug.WriteLine
等。
复合格式声明
复合格式由参数索引,对齐声明和格式声明组成)。
{ index[,[+-]alignment][:formatString]}
多个格式项可以引用同一个参数,索引顺序与参数顺序无关。
对齐方式:alignment
的绝对值代表了字符串的最小长度(字符串长度超过该值,则alignment
无效);正值代表右对齐,负值代表左对齐,如果需要则填充空白。
不同类型的对象有不同的格式声明(格式声明在不同国家/语言有不同输出),其中: 标准数字格式包括:
格式 | 名称 | 说明 |
---|---|---|
`C | c[n]` | 货币格式 |
`D | d[n]` | 整型数字 |
`E | e[n]` | 指数计数法 |
`F | f[n]` | 定点计数法 |
`G | g[n]` | 科学计数法 |
`P | p[n]` | 百分比 |
`X | x` | 十六进制整型 |
自定义数值格式:
标准日期和时间:
格式 | 说明 | 示例 |
---|---|---|
d | 短日期 | 6/15/2009 |
D | 长日期 | Monday, June 15, 2009 |
g | 短日期时间 | 6/15/2009 1:45 PM |
G | 长日期时间 | 6/15/2009 1:45:30 PM |
自定义日期和时间类型:获取日期时间中的字段
格式 | 说明 | 格式 | 说明 |
---|---|---|---|
y/yy | year(0-99 /00-99 ) | yyyy | year(0000-9999 ) |
M/MM | month(1-12 /01-12 ) | MMM/MMMM | month name (short/long) |
d/dd | day-of-month | ||
ddd | day-of-week, short (Mon ) | dddd | day-of-week, long (Monday ) |
h/hh | hour(1-12 /01~12 ) | H/HH | hour(0-23 /01-23 ) |
m/mm | minute(0-59/00-59 ) | ||
s/ss | second(0-59 /00-59 ) | ||
t/tt | AM/PM | ||
g/gg | A.D. or B.C. | f/ff/fff/... | .x /.xx /.xxx /... seconds |
K | time zone | z/zz | timezone hour offset |
: | 时间分隔符 | / | 日期分隔符 |
TimeSpan类型
枚举类型
比较
bool Equals(string value, StringComparison comparisonType);
bool EndsWith(string value, comparisonType)
comparisonType
:比较规则包括{Ordinal, OrdinalIgnoreCase }
。当调用字符串比较函数如String.Compare
、String.Equals
、String.IndexOf
,应该总是使用带有comparisonType
的函数指定比较规则。省略comparisonType
,则该方法按照Ordinal
规则(case-sensitive和culture-insensitive)进行比较。
StringBuilder
StringBuilder str = new StringBuilder();
str.Append(value);
编码
Encoding
数组
数组是用于存储多个同一类型变量的数据结构。数组是引用类型,派生于抽象基类Array类,所以数组也能当做类来使用。
声明
声明数组:
type[] arrayname; // 1-D
type[,,,...] arrayname; // multi-dimension array
数组的类型由值类型type
和“[]
”指定的维数决定。数组元素的类型可以是基本类型也可以是引用类型(甚至可以是数组类型)。数组的维数根据“[]
”中的“,
”的个数确定,维数=逗号个数+1
。
数组初始化时的维度应该与数组声明一致,也可以将数组的声明和初始化放到一起。
type[] arrayname = new type[size];// initialize as default
数组在初始化时确定其维数和长度,且不能在实例存在期间修改。
数组的每个维度的长度或初始化列表可以省略,但两者不能同时省略:如果省略初始化列表则使用元素类型的默认值初始化数组;如果省略长度,则根据初始化列表元素的长度确定数组的长度;如果两者同时给出,则必须保证维数和长度声明与初始化列表一致。
arrayname = new type[size]{initialize_list};
arrayname = new type[m,n]{{list1},{list2},...{listm}};
arrayname = new type[,]{{list1},{list2},...{listm}};
arrayname = {{list1},{list2},...{listm}};
锯齿数组
锯齿数组(或称为交错数组)的每个元素是数组。
type [,...][,...] arrayname;
声明中,第一个[,...]
是锯齿数组的维度声明,第二个是锯齿数组元素的维度声明。虽然每个子数组的维数由声明确定,但是在初始化时,子数组之间各相应维度的长度可以各不相同,因此称为锯齿/交错数组。使用初始化列表赋值:
int[][,] jag_array = { // 使用初始化列表
new int[,]{{1,2,3},{2,4,1}},
new int[,]{{2,1},{4,2}},
new int[,]{{1,3,5},{2,1,3},{3,4,5}}
...
};
int[][,] jag_array = new int[M][,]{...}
先使用new
初始化交替数组本身,再初始化数组的每个元素:
int[][] jag_array = new int[M][];
for(int i=0; i<M; ++i){ //对每个元素逐个赋值
jag_array[i] = new int[len_i];
}
可以定义高维的锯齿数组::
int[,][] multi_array = {
{new int[]{1,2,3}, new int[]{2,1}},
{new int[]{1,3}, new int[]{2,1,3}}
};
数组访问
下标
普通数组的访问方法是array[i,j,...]
。
交错数组的访问方法是array[i][j,k,...]
。
迭代
使用循环语句for
。
// 普通数组
for(int i = 0; i<M; ++i){
for(int j=0; j<M; ++j){
Console.Write("{0:G} ", array2d[i,j])
}
}
使用foreach
语句,高维数组视为一维数组迭代。
foreach(int x in array2d){
Console.Write("{0:G} ", x)
}
foreach
只能读元素,而不能修改数组。
数组维数和长度
array.Length; // 数组的元素总数
array.GetLength(dim); //数组的一个维度的长度;
容器
容器类型
泛型和非泛型容器
泛型容器(System.Collections.Generic
)用于储存同一类型的元素,具有强类型要求,从而提供更好的类型安全以及更好的性能。
非泛型容器(System.Collections
)存储的元素不要求特定的类型,所有元素都当作Object
对象。非泛型集合(如 ArrayList
)不建议使用,并且保留用于兼容性目的。大多数非泛型版本容器都不支持应用商店应用。
容器名 | 泛型 | 非泛型 | 说明 |
---|---|---|---|
列表 | List<T> | ArrayList | 容器的大小可以增加或减小。提供查找、排序和修改等等方法。 |
链表 | LinkedList<T> | ||
有序列表 | SortedList<Tk, Tv> | SortedList | 使用ICompare 接口根据对元素进行排序。 |
队列 | Queue<T> | Queue | 具有先进先出(FIFO)操作规则。 |
栈 | Stack<T> | Stack | |
映射 | Dictionary<Tk,Tv> | HashTable | 基于键值或Hash值索引元素。 |
有序映射 | SortedDictionary<Tk, Tv> | ||
集合 | HashSet<T> | ||
有序集合 | SortedSet<T> |
专用容器
System.Collections.Specialized
包含专用的强类型的结合。例如:链表字典,位向量,字符串容器。
并发容器
System.Collections.Concurrent
提供高效地线程安全的容器访问操作。当从多线程访问容器时,应该使用本空间中的对应容器类型代替System.Collections.Generic
和System.Collections
中的类型。
容器公共特性
容器基于ICollection
、IList
和IDictionary
接口及其泛型版本。IList
和IDictionary
派生自ICollection
。
容器接口包括:
-
ICollection<T>
-
IList<T>
-
IDictionary<T>
-
IComparer<T>
-
IEqualityComparer<T>
-
IEnumerator<T>
-
ISet<T>
枚举元素
容器类型继承IEnumerable
/IEnumerable<T>
,因此可以通过foreach
语句进行枚举。继承自IEnumerable<T>
的容器还可以通过LINQ
进行查询。LINQ
通常更简洁且可读性更强,提供筛选、排序以及分组能力,且能提高性能。
复制到数组
通过CopyTo
方法将元素按照枚举顺序复制到一维数组中。
容量和计数
-
Capacity
在不重新分配空间前,容器的容量。
Capacity
不应该设置为比Count
小的值,否则引发异常(ArgumentOutOfRangeException
)。 -
Count
容器包含元素的数量。
一致的下界
元素从0起索引。Array可以自定义起始索引。
比较
Contains, IndexOf,
LastIndexOf
以及Remove
等方法使用等式比较。泛型容器的比较方案:如果类型T继承了IEquatable\<T\>
接口,则使用接口的Equals
函数;否则使用Object.Equals
。
排序顺序
BinarySearch
和Sort
使用一个顺序比较器,用于比较容器的元素或与给定的值比较。
default comparer:依赖参与比较的对象至少有一个实现了IComparable接口。泛型类型的比较器方案:如果T实现了IComparable<T>接口,则默认比较器为IComparable<T>.CompareTo(T);如果T实现了IComparable接口,则默认比较器为IComparable.CompareTo(T);如果T没有实现以上接口,则必须显示提供比较器。
元素排序
SortedList
/SortedList<TKey, TValue>
、SortedDictionary<TKey, TValue>
实现
IDictionary
/``IDictionary<TKey, TValue>`接口,每个元素是key/value对。元素根据
ICompare
/ICompare<T>
接口排序。每个类提供仅返回key或value的属性。
HashTable
/Dictionary<TKey,TValue>
按key排序。
迭代器
迭代器用于容器的迭代访问操作。
使用foreach
语句来调用迭代器。
访问容器的接口
容器相关操作
Queue
- Dequeue/Enqueue
Stack
-
Push/Pop
Peek
LINQ
You can write LINQ queries in C# with SQL Server databases, XML documents, ADO.NET Datasets, and any collection of objects that supports IEnumerable
or the generic IEnumerable<T>
interface.
All LINQ query operations consist of three distinct actions:
-
Obtain the data source.
-
Create the query.
-
Execute the query.
数据源(Data Source)
LINQ数据源可以是支持IEnumerable<T>
接口以及继承该接口的任何实例。支持IEnumerable<T>
及其派生接口(如IQueryable<T>
)的类型被称为可查询类型。
Enumerable
类提供一组用于查询实现IEnumerable<T>
的对象的静态方法。
XElement
Northwnd
查询
查询语法:从对象序列中查询满足条件的对象,并返回筛选结果。
var seattleCustomers = from customer in customers
where customer.City == "Seattle"
[orderby customer.ID]
select customer.Name; // or select customer
from
指定数据源;where
应用过滤条件;select
语句指定返回元素的类型。
var localDistributors =
from customer in customers
join distributor in distributors on customer.City equals distributor.City
select new { Customer = customer, Distributor = distributor.ID };
return a new type
var scoreQuery = from student in students
from score in student.Scores
where score > 90
select new { Last = student.LastName, score };
执行查询
延迟执行
查询变量本身只储存查询命令,当通过foreach
语句对查询变量进行迭代时,才真正执行查询。
强制立即执行
统计函数:Count
、Max
、Average
、First
强制执行:ToList()
或ToArray()
;
在查询语句之后,立即使用foreach
语句。
List
List
实现的接口
IndexOf
、LastIndexOf
和Remove
方法使用类型T
的默认比较函数(EqualityComparer<T>.Default
属性)判断相等。如果T
实现了System.IEquatable<T>
接口,则返回包含该接口的EqualityComparer
,否则返回包含由T
提供的Objects.Equals
和Objects.GetHashCode
的EqualityComparer
。
Contains
方法使用默认的相等比较函数判断相等。如果T
实现了IEquatable<T>
接口,则调用IEquatabale.Equals
方法,否则使用Object.Equals
。
Sort
、BinarySearch
使用类型T的默认的比较函数(Comparer<T>.Default
属性)。如果T
实现了IComparable<T>
接口,则默认比较函数为IComparable<T>.CompareTo(T)
;否则如果实现了IComparable
接口,则默认比较函数是IComparable.CompareTo()
;如果T
没有实现比较接口,则必须显式提供比较委托。
List
允许引用类型取值为null
,以及重复元素。
ArrayList
ArrayList的容量是自动扩充的(类似于字符串,与一般数组不同);
ArrayList只能是一维的;
构造函数
List<T>() //with default capacity
List<T>(Int32 Capacity)
属性
T this[int index] { get; set; }
按序号访问指定的元素。
方法
插入
void Add( T item );
void Insert( int index, T item )
Add
添加元素到列表末尾。
Insert
在指定序号处插入元素,指定的序号小于0
或大于Count
会引发异常(ArgumentOutOfRangeException
)。
删除
bool Remove( T item );
int RemoveAll( Predicate<T> match );
void RemoveAt( int index )
void Clear();
void TrimExcess()
Remove
移除出现的第一个指定元素,如果成功移除返回true
;如果指定元素不在列表中或移除失败,返回false
。
RemoveAll
移除满足条件的所有元素,并返回移除元素的数量。
RemoveAt
移除指定位置的元素,指定的序号小于0
或大于Count
会引发异常(ArgumentOutOfRangeException
)。
Clear
移除列表中的所有元素。
TrimExcess
将列表的容量缩小至元素实际数量。
查找
bool Contains( T item );
bool Exists( Predicate<T> match );
T Find( Predicate\<T\> match ); // FindLast
int FindIndex( Predicate\<T\> match ); // FindLastIndex
int IndexOf( T item ); // LastIndexOf
List<T> FindAll( Predicate<T> match );
Contains
判断一个元素是否包含在列表中。(This method determines equality by using
the default equality comparer, as defined by the object's
implementation of the IEquatable<T>.Equals method forT (the type of
values in the list).)
Exists
判断是否存在匹配给定条件的元素。match
定义了查找元素的条件。列表的元素分别被传递给match
函数,当找到匹配元素时停止操作。
Find
查找满足条件的元素并返回第一个元素。
FindAll
查找所有满足条件的元素并返回。
FindIndex
查找满足条件的元素并返回第一个元素序号。
IndexOf
查找指定的元素,并返回第一个元素的序号。
排序
void Reverse()
反转整个列表的元素排列顺序。
void Sort()
void Sort( Comparison<T> comparison )
void Sort( IComparer<T> comparer )
使用comparison
对列表排序。
使用comparer
进行排序。
Dictionary
System.Collections in mscorlib
代表非一般性的键值对(key/value)的容器。每一个键值对储存在一个DictionaryEntry
对象中。
每个键值对必须具有唯一的键名,实现类型可以决定是否允许键名为null。值可以是null且不要求唯一性。
IDictionary
的实现类型分为三类:只读、固定长度、可变长度。
属性
按键名key访问元素:
Object this[ Object key] { get; set; }
键名和值
ICollection Keys { get; }
ICollection Values { get; }
值的顺序与Keys
返回的键名的顺序对应。
DictionaryEntry
定义字典的键值对。
Object Key { get; set; }
Object Value { get; set; }