1、 自定义泛型
l 泛型的目的也是为了代码重用(算法重用)
classMyListGeneric<T>
{
T[] arr = new T[100];
public T this[int index]
{
}
}
l 泛型接口:
(1) 与其他泛型相似,实现不同类型参数的泛型接口是不同的接口
(2) 可以在非泛型类型中实现泛型接口
实现泛型接口的两种方式:
(1) 封闭类型
(2) 开放类型
l 泛型方法:泛型方法可以在泛型和非泛型类以及结构和接口中声明。
public void PrintData<S,T>(S p,T t)where S:Person
{
…
}
要调用泛型方法,应该在方法调用时提供类型实参
MyMethod<short,int>();
MyMethod<int,long>();
l 泛型约束
public class Person<T,T1,TC,TK,TV,TU>
whereT1:struct //约束T1必须是值类型
whereT:class //约束T必须是引用类型
whereTC:new() //这个类型必须带有一个无参的构造函数(1、构造函数不能是私有,2、类型不能是抽象的)
whereTK:Car //这里约束了TK类型,必须是Car类型或者是Car类型的子类
whereTV:IComparable //约束类TV必须是实现IComparable接口的类型
whereTU:T //约束了TU必须是T的子类
2、 装箱拆箱
l 装箱:将值类型转换为引用类型
l 拆箱:将引用类型转换为值类型
举例:
int n = 10;
object o = n;//装箱
int m =(int)o; //拆箱
//以下代码发生了类型转换,但绝对不是装箱或拆箱
//由于字符串类型和int类型在内存上根本不存在“交集”
int n = 10;
string s1 = Convert . ToString(n);
int m = int . Parse(s1);
l 注意:装箱的时候使用什么类型来装箱,拆箱的时候还必须使用对应的类型来拆箱。
例2:
// 由于int32是结构,结构是值类型
// 接口是引用类型
// 由于int32实现了IComparable接口,所有可以在int32与IComparable之间发生类型转换。int32到IComparable实现了装箱,IComparable到int32实现了拆箱
int n1 =10;
IComparablecom = n1; //装箱
int n =(int) com; //拆箱
l 装拆箱与否的时间比较
3、 foreach
任何类型想用foreach循环遍历,就必须在当前类型中存在GetEnumerator()方法,该方法一般通过IEnumerable接口实现。这个方法的作用不是用来遍历的,而是获取一个对象,这个对象才是用来遍历的。
public classPersonEnumerator:IEnumerator<Person>
foreach内部原理:
IEnumerator etor= p . GetEnumerator();
while(etor.MoveNext())
{
string str = etor.Current.ToString();
}
4、 文件操作常用类型
(1)类型:
File //操作文件,静态类,对文件整体操作。拷贝、删除、剪切等。
Directory//操作目录(文件夹),静态类
DirectoryInfo//文件夹的一个“类”,用来描述一个文件夹对象(获取指定目录下的所有目录时返回一个DirectoryInfo数组)
FileInfo//文件类,用来描述一个文件对象。获取指定目录下的所有文件时,返回一个FileInfo数组
Path//对文件或目录的路径进行操作(字符串)
Stream//文件流,抽象类
FileStream
StreamReader
StreamWriter
(2)Path类:其中的方法基本都是对字符串的操作,与实际文件没关系
ChangeExtension()改扩展名
Path.Combine(s1,s2); 将两个路径连接起来
GetFileName() 获取文件名
GetDictionaryName() 获取目录名
GetFileNameWithoutExtention() 获取文件名不包括扩展名
GetExtension()
GetFullPath()
GetTempPath() 获得当前用户的临时目录
GetTempFileName() 创建一个随机文件名,并在临时目录下生成
l 获取当前exe文件执行的路径
string exePath =Assembly.GetExecutingAssembly().Location.ToString();
string txtPath =Path.GetDirectoryName(exePath) + “1.txt”;
(3)Directory类
CreateDirectory() 创建目录
GetDirectories() 获取当前目录下所有直接子目录
GetFiles() 获取当前目录下所有直接文件
Exists() 判断某目录下是否存在某文件夹
Delete() 删除某目录,目录不存在则报异常,所以先判断。只能删除空目录
Directory.Delete(path,true); true表示将当前目录及里面的所有内容删除
Move() 可以实现重命名
DirectoryInfo类
(4)在程序中写相对路径不要直接写,这样可能不准确。比如:用户打开了OpenFileDialog对话框等。
5、 递归:就是方法自己调用自己
如果没有停止条件,则肯定会死递归,最后报异常,栈溢出。一般递归肯定有终止条件。
6、 操作文件
(1)File类
产生乱码的原因(只有文本文件才会有乱码):文件存储的时候采用一种编码格式,读取的时候采用另一种编码格式。
ASCII、gb2312、UTF-8国际码表、Big5繁体中文、GBK简体中文(兼容gb2312)
Encoding.Default表示采用计算机默认的“区域和语言选项”中的编码格式
EncodingInfo[] infos = Encoding.GetEncodings()返回所有支持的编码
方法:
Exists() 文件是否存在
Delete() 删除文件,如果文件不存在也不报异常
fs.Flush() 将内存中的文件流写入磁盘
(3) StreamReader类
//第一个参数:bytes表示要将文件中的字节读取到该数组中
//第二个参数:从bytes的第几个索引开始存放
//第三个参数:一次最多读取的字节数
int r = fs . Read(bytes,0,bytes.Length);
l 通过文件流读取磁盘上的文件
//1、创建文件流
FileStream fsRead = new FileStream(“1.txt”,FileMode.Open);
//2、创建缓冲区
byte[] bytes = new byte[fsRead.Length]; //大文件的读取bytes的长度可指定为具体值
//3、开始读取
int r = fsRead.Read(bytes,0,bytes.Length);
//4、关闭文件流,释放资源
fsRead.Close();
fsRead.Dispose();
l 通过文件流写入文件
1、 创建文件流
FileStream fs = new FileStream(@”C:\mywords.txt”,FileMode.OpenOrCreate);
2、 创建byte[]
byte[] bytes =System.Text.Encoding.UTF8.GetBytes(msg);
3、 将bytes中的内容写入文件中
fs.Write(bytes,0,bytes.Length);
4、 关闭文件流
fs.Close();
fs.Dispose();
7、 字符串与byte数组的转换
byte[] bytes =System.Text.Encoding.UTF8.GetBytes(msg);
string msgNew =System.Text.Encoding.UTF8.GetString(bytes)
思考:Convert.ToString()没发生装拆箱,那么内部怎么实现?
作业:自己写一个类型,用foreach循环
把File的每个方法试一遍
写一个大文件拷贝的代码
文件操作
TreeView