C#基础知识解读.docx
《C#基础知识解读.docx》由会员分享,可在线阅读,更多相关《C#基础知识解读.docx(45页珍藏版)》请在冰豆网上搜索。
C#基础知识解读
一、C#
1.对象和转换
A.对象分类、创建和指向
类别
说明
值类型
简单类型
有符号整型:
sbyte,short,int,long
无符号整型:
byte,ushort,uint,ulong
Unicode字符:
char
IEEE浮点型:
float,double
高精度小数:
decimal
布尔型:
bool
引用类型
类类型
基类:
object
Unicode字符:
string
ClassC{….}
接口类型
InterfaceI{….}
数组类型
一维和多维数组
委托类型
DelegateTD(…)
枚举类型
EnumE{…}
结构类型
StructS{…}
引用类型特征:
1.必须在托管堆中为引用类型变量分配内存
2.必须使用new运算符来创建引用类型变量。
new运算符返回创建对象的地址,并保存在变量中
3.在托管堆中分配的每个对象都有与之相关的附加成员,这些成员必须被初始化
4.引用类型变量是由垃圾回收机制来管理的
5.多个引用变量可以引用同一个对象
6.引用类型被赋值前的值都是null
值类型的特征:
1.值类型变量都存储在堆栈中
2.访问值类型变量时,都是直接访问其实例
3.每个值类型变量都有自己的数据副本,因此对一个值类型变量的操作不会影响其他变量
4.复制值类型变量时,复制的是变量的值,而不是变量的地址
5.值类型变量的值不能为null,必须有有一个确定的值
6.值类型是从System.ValueType类继承而来,C#中值类型也包括结构类型和引用类型
值类型和引用类型的区别:
值类型的变量直接包含数据,而引用类型的变量存储对数据的引用。
B.对象转换
1.隐式转换(不会丢失数据),不存在Char类型的隐式转换,因此其他类型不会自动转换为Char类型
2.显示转换,包括所有隐式和显示转换,总是可以使用强制转换表达式从任何数值类型到任何其他数值类型,显示转换是不安全的,可能导致数据丢失
3.装箱和拆箱
装箱:
将值类型转换为引用类型;拆箱:
将引用类型转换为值类型
装箱:
从任何“值类型”到类型object
从任何“值类型”到类型System.ValueType
从任何“值类型”到“值类型”实现的任何“接口类型”
从任何“枚举类型”到System.Enum类型
将一个值类型变量v装箱为一个引用类型o时,需要进行如下的几步操作:
1.在托管堆创建一个对象实例o,给它分配内存
2.将v的值复制到对象实例o中
3.将o的地址压入堆栈中,此时它指向一个引用类型
UsingSystem;
ClassBoxing
{
PublicstaticvoidMain()
{
inti=10;
objectobj=i;
Console.WriteLine(“1.值为{0},装箱对象为{1}”,i,obj);
i=20;
Console.WriteLine(“2.值为{0},装箱对象为{1}”,i,obj);
}
}
运行结果:
1.值为10,装箱对象为10
2.值为20,装箱对象为10
拆箱:
从类型object到任何类型
从类型System.ValueType到任何值类型
从任何接口类型到实现了该类型的任何值类型
从System.Enum类型到任何枚举类型
拆箱包括两个步骤:
首先检验该对象实例是否是某个给定的值类型的装了箱的值,然后将值从实例中复制出来,并赋值给值类型变量。
UsingSystem;
ClassUnboxing
{
PublicstaticvoidMain()
{
Inti=10;
Objectobj=i;
Console.WriteLine(“装箱:
值为{0},装箱对象为{1}”,i,obj);
intj=(int)obj;//doublej=(double)obj;
Console.WriteLine(“拆箱:
装箱对象为{0},值为{1}”,obj,j);
}
}
结果为:
装箱:
值为10,装箱对象为10
拆箱:
装箱对象为10,值为10
注意:
拆箱必须符合类型一致原则
可空类型:
以值类型为基础类型来构造的,可空类型的基础类型必须是非可空的值类型。
可空类型可以表示基础类型的所有值和一个额外的空值,可空类型的实例有两个公共只读属性:
HasValue为true表示实例为非空;Value表示可空类型的基础类型值。
例:
int?
x;int?
y=null;
包装与解包
包装就是将T类型的值打包在类型T?
的实例中,例:
int?
=123;
解包就是获取包含在类型T?
的实例中的类型为T的值的过程,例:
inti=123;int?
x=i;
类的转换
1.隐式转换
从任何引用类型到object类
从任何类S到任何类T(S是从T派生的)
从任何类S到任何接口T(S实现了T)
从任何接口S到任何接口T(S是从T派生的)
从null到任何引用类型
2.显式转换
从object到任何其他引用类型
从任何类S到任何接口T(S未密封并且S不实现T)
从任何接口S到任何类T(T为密封或T实现S)
从任何接口S到任何接口T(S不是从T派生的)
is运算符用于动态检验对象的运行时类型是否与给定类型兼容
as运算符用于将一个对象显示地转换为一个给定的引用类型,与强制转换不同,as运算符不发生异常。
它的规则是:
如果指定的转换不可能实施,则运算结果为null
2.集合
AList
BDictionary
集合
集合是基于System.Colletion.ICollection接口、System.Collection.IList接口、System.Collection.IDictionary接口来实现的。
IList接口和IDictionary接口都是从ICollection接口派生的。
对于基于IList接口的集合(如Array、ArrayList、List)或者直接基于ICollection接口的集合(如Queue、Stack、LinkedList)来说,每个元素只有一个值。
对于基于IDictionary接口的集合来(如Hashtable和SortedList类)来说,每个元素都包含一个键和一个值。
System.Collection.ICollection继承了System.Collections.IEnumerable,而IEnumerable接口仅仅包含一个名为GetEnumerator的方法,返回一个能够访问集合中数组的列举器对象。
对象类型的集合位于System.Collections命名空间;泛型集合类位于System.Collection.Generic命名空间;专用于特定类型的集合类位于System.Collection.Specialized命名空间。
集合可以根据集合执行的接口组合为列表、集合和字典。
1.列表
创建列表:
ListintList=newList();
Listracers=newList();//Racer:
类
使用Capacity属性可以获取和设置集合的容量:
intList.Capacity=20;
集合中元素的个数可以用Count属性读取。
只要不把元素添加到列表中,元素个数就是0;如果已经将元素添加到列表中,且不希望添加更多的元素,就可以调用TrimExcess()方法,去除不需要的容量。
但是如果元素个数超过容量的90%,TrimExcess()将什么也不做。
初始化:
ListintList=newList(){1,2};
ListstringList=newList(){"one","two"};
添加元素:
ListintList=newList();
intList.Add
(1);intList.Add
(2);
ListstringList=newList();
stringList.Add("one");stringList.Add("two");
Racergraham=newRacer("Graham","Hill","UK",14);//Racer是类
Raceremerson=newRacer("Emerson","Fittipaldi","Brazil",14);
Racermario=newRacer("Mario","Andretti","USA",12);
Listracers=newList(20);{graham,emerson,mario};
racers.Add(newRacer("Michael","Schumacher","Germany",91));
racers.Add(newRacer("Mika","Hakkinen","Finland",20));
racers.AddRange(newRacer[]{newRacer("Niki","Lauda","Austria",25)
newRacer("Alian","Prost","France",51});
Listracers=newList(newRacer[]{newRacer("Jochen","Rindt","Austria",6)
newRacer("Ayrton","Senna","Brazil",41});
racers.Insert(3,newRacer("Phil","Hill","USA",3));
访问元素:
foreach(Racerrinracers)
{
Console.WriteLine(r);
}
List还提供了ForEach()方法,它用Action参数声明publicvoidForEach(Actionaction);
publicclassList:
IList
{
privateT[]items;
//...
publicvoidForEach(Actionaction)
{
if(action==null)thrownewArgumentNullException("action");
foreach(Titeminitems)
{
action(item);
}
}
//...
}
为了给ForEach传送一个方法,Action声明为一个委托,它定义了一个返回类型为void、参数为T的方法。
publicdelegatevoidAction(Tobj);
racers.ForEach(Console.WriteLine);
删除元素:
racers.RemoveAt(3);//删除第四个元素
方法RemoveRange()可以从集合中删除许多元素。
它的第一个参数指定了开始删除的元素索引,第二个参数指定了要删除的元素个数。
intindex=3;
intcount=5;
racers.RemoveRange(index,count)
要从集合中删除有指定特性的所有元素,可以使用RemoveAll()方法
搜索:
IndexOf(),如果在集合中找到该元素,这个方法就返回该元素的索引。
如果没有找到该元素,就返回-1;intindex1=racers.IndexOf(mario);
搜索有某个特性的元素,该特性可以用FindIndex()方法来定义。
FindIndex()方法需要一个Predicate类型的参数:
publicintFindIndex(Predicatematch);Predicate类型是一个委托,它返回一个布尔值,需要把类型T作为参数。
intindex2=racers.FindIndex(newFindCountry("Finland").FindCountryPredicate);
intindex3=racers.FindIndex(r=>r.Country=="Finland");
还有Find(),FindLast(),FindAll();
排序:
racers.Sort();
类型转换:
使用List类的ConvertAll()方法,可以把任意类型的集合转换为另一种类型
Listpersons=racers.ConvertAll(
r=>newPerson(r.Firstname+""+r.Lastname));
2.队列
Queue和Queue类的成员
说明
Enqueue()
在队列一端添加一个元素
Dequeue()
在队列的头部读取和删除一个元素。
如果在调用Dequeue()方法时,队列中不再有元素,就抛出InvalidOperationException异常
Peek()
在队列的头部读取一个元素,但不删除它
Count
返回队列中的元素个数
TrimExcess()
重新设置队列的容量。
Dequeue()方法从队列中删除元素,但不会重新设置队列的容量。
要从队列的头部去除空元素,应使用TrimExcess()方法
Contains()
确定某个元素是否在队列中,如果是,就返回true
CopyTo()
把元素从队列复制到一个已有的数组中
ToArray()
ToArray()方法返回一个包含队列元素的新数组
3.栈
Statck和Statck类的成员
说明
Push()
在栈顶添加一个元素
Pop()
从栈顶删除一个元素,并返回该元素。
如果栈是空的,就抛出InvalidOperationException异常
Peek()
返回栈顶元素,但不删除它
Statck和Statck类的成员
说明
Count
返回栈中的元素个数
Contains()
确定某个元素是否在栈中,如果是,就返回true
CopyTo()
把元素从栈复制到一个已有的数组中。
ToArray()
ToArray()方法返回一个包含栈中元素的新数组
Stackalphabet=newStack();
alphabet.Push('A');
alphabet.Push('B');
alphabet.Push('C');
foreach(chariteminalphabet)
{
Console.Write(item);
}
4.链表
LinkedList是一个双向链表,其元素指向它前面和后面的元素
LinkedListNode的属性
说明
List
返回与节点相关的LinkedList
Next
返回当前节点之后的节点。
其返回类型是LinkedListNode
Previous
返回当前节点之前的节点
Value
返回与节点相关的元素,其类型是T
LinkedList的成员
说明
Count
返回链表中的元素个数
First
返回链表中的第一个节点。
其返回类型是LinkedListNode。
使用这个返回的节点,可以迭代集合中的其他节点
Last
返回链表中的最后一个元素。
其返回类型是LinkedListNode。
使用这个节点,可以逆序迭代集合中的其他节点
AddAfter()
AddBefore()
AddFirst()
AddLast()
使用AddXXX方法可以在链表中添加元素。
使用相应的Add方法,可以在链表的指定位置添加元素。
AddAfter()需要一个LinkedListNode对象,在该对象中可以指定要添加的新元素后面的节点。
AddBefore()把新元素放在第一个参数定义的节点前面。
AddFirst()和AddLast()把新元素添加到链表的开头和结尾
重载所有这些方法,可以添加类型LinkedListNode或类型T的对象。
如果传送T对象,则创建一个新LinkedListNode对象
Remove()
RemoveFirst()
RemoveLast()
Remove()、RemoveFirst()和RemoveLast()方法从链表中删除节点。
RemoveFirst()删除第一个元素,RemoveLast()删除最后一个元素。
Remove()需要搜索一个对象,从链表中删除匹配该对象的第一个节点
Clear()
从链表中删除所有的节点
Contains()
在链表中搜索一个元素,如果找到该元素,就返回true,否则返回false
Find()
从链表的开头开始搜索传送给它的元素,并返回一个LinkedListNode
FindLast()
与Find()方法类似,但从链表的结尾开始搜索
documentList=newLinkedList();
priorityNodes=newList(10);
for(inti=0;i<10;i++)
{
priorityNodes.Add(newLinkedListNode(null));
}
5.有序表
如果需要排好序的表,SortedList
SortedListbooks=newSortedList();
books.Add(".NET2.0WroxBox","978-0-470-04840-5");
books.Add("ProfessionalC#2005with.NET3.0","978-0-470-12472-7");
可以使用foreach语句迭代有序表。
枚举器返回的元素是KeyValuePair类型,其中包含了键和值。
键可以用Key属性访问,值用Value属性访问。
foreach(KeyValuePairbookinbooks)
{
Console.WriteLine("{0},{1}",book.Key,book.Value);
}
SortedList类的属性,如下表所示:
SortedList的属性
说明
Capacity
使用Capacity属性可以获取和设置有序表能包含的元素个数。
该属性与List类似:
默认构造函数会创建一个空表,添加第一个元素会使有序表的容量变成4个元素,之后其容量会根据需要成倍增加
Comparer
Comparer属性返回与有序表相关的比较器。
可以在构造函数中传送该比较器。
默认的比较器会调用IComparable接口的CompareTo()方法来比较键。
键类型执行了这个接口,也可以创建定制的比较器
Count
Count属性返回有序表中的元素个数
Item
使用索引器可以访问有序表中的元素。
索引器的参数类型由键类型定义
Keys
Keys属性返回包含所有键的IList
Values
Values属性返回包含所有值的IList
SortedList类的方法:
SortedList的方法
说明
Add()
把带有键和值的元素放在有序表中
Remove()
RemoveAt()
Remove()方法需要从有序表中删除的元素的键。
使用RemoveAt()方法可以删除指定索引的元素
Clear()
删除有序表中的所有元素
ContainsKey(),
ContainsValue()
ContainsKey()和ContainsValue()方法检查有序表是否包含指定的键或值,并返回true或false
IndexOfKey(),
IndexOfValue()
IndexOfKey()和IndexOfValue()方法检查有序表是否包含指定的键或值,并返回基于整数的索引
TrimExcess()
重新设置集合的大小,将容量改为需要的元素个数
TryGetValue()
使用TryGetValue()方法可以尝试获得指定键的值。
如果键不存在,这个方法就返回false。
如果键存在,就返回true,并把值返回为out参数
6.字典
1.Dictionary
字典表示一种非常复杂的数据结构,这种数据结构允许按照某个键来访问元素。
字典也称为映射或散列表。
字典的主要特性是能根据键快速查找值。
也可以自由添加和删除元素,这有点像List,但没有在内存中移动后续元素的性能开销。
可以使用的最主要的类是Dictionary。
这个类的属性和方法与上面的SortedList几乎完全相同,用作字典中键的类型必须重写Object类的GetHashCode()方法。
只要字典类需要确定元素的位置,就要调用GetHashCode()方法。
GetHashCode()方法返回的int由字典用于计算放置元素的索引。
例:
publicstructEmployeeId:
IEquatable
{
privatereadonlycharprefix;
privatereadonlyintnumber;
publicEmployeeId(stringid)
{
if(id==null)thrownewArgumentNullException("id");
prefix=(id.ToUpper())[0];
intnumLength=id.Length-1;
number=int.Parse(id.Substring(1,numLength>6?
6:
numLength));
}
publicoverridestringToString()
{
returnprefix.ToString()+string.Format("{0,6:
000000}",number);
}
publicoverrideintGetHashCode()
{
return(number^number<<16)*0x15051505;
}
publicboolEquals(EmployeeIdother)
{
return(prefix==other.prefix&&number==other.number);
}
}
publicclassEmployee
{
privatestringname;
privatedecimalsalary;
privatereadon