值类型和引用类型
值类型:int bool double long short byte char struct(结构)enum(枚举)。。。。。
引用类型:string 自定义类 interface(接口) delegate(委托)。。。。
String 和 StringDuilder
string 是不可变的,因此每次运算时都会重新创建一个string对象,大量的字符串相连会产生大量的中间字符串,字符串时对象,对象的产生是慢的,而且会占用大量的内存;
stringDuilder内部实现了字符串拼接不会有中间字符串的缺陷
object.ReferenceEquals(object,object); 判断是不是有相同的实例
字符串暂存池(拘留池intern)
作用:
当创建一个字符串的时候,如果发现这个字符串在内存中已经存在了,那么就会直接引用该字符串的地址,不会再重新创建一个
解决什么问题
程序中大量使用字符串,有不少重复性的,为了降低内存的占用。Net将代码中的声明的字符串放到字符串拘留池中,值相同的字符串共享同一个实例。字符串是不变的。不是所有的字符串都在拘留池中
作用范围
动态字符串默认是不在字符串拘留池中(即stringDuilder和string s=s1+s2+s3不支持这种特性)
类和结构是
相同点
。NetFrameWork中的通用类型系统的两种基本构造。两者在本质上都是数据结构
区别
类是一种引用类型,创建类的对象时,对象赋值到的变量只保存对该内存的引用。
将对象引用赋给新的变量时,新的变量引用的是原始对象。通过一个变量做出更改将反映在另一个变量中因为两者引用同一个数据。
结构是一种值类型,创建结构时,结构赋值到变量保存该结构的实际数据,将结构赋给新的赋给新的变量时,将复制该结构,因为,新的变量和原始变量包含同一数据的两个不同的副本。对一个副本的更改不影响另一个副本。
封装
作用
封装有时候被称为面向对象的编程的第一支柱或原则。根据封装的原则,类和结构可以指定其每个成员对于该类或结构外部的代码的可访问性。
好处
可将无意在类和程序集外部使用的方法和变量隐藏起来,以减小编码的错误或遭恶意性利用的可能性。
成员
所有方法、字段、常量、属性和事件都必须在类型的内部进行声明;这些称为类或结构的成员。与其他语言不同的是,c#中没有全局变量或方法。即使是作为程序入口点的Main方法也必须在类或结构内部进行声明。
在类或结构中所有不同的成员
字段,常量,属性,方法,构造函数,析构函数,事件,索引器,运算符,嵌套类型
访问修饰符
Public 公有()
Private 私有(只能在本类中访问)
Internal (只能在本程序集中访问)
Protected 受保护的(只能在本类或是在他子类中访问)
访问级别约束
- 子类的访问级别不能比父类高
- 类中的属性和字段的访问级别不能比所对应的类型的访问级别高
- 方法的的访问级别不能比方法的参数和返回值的访问级别高
继承
类(二非结构)支持继承的概念
接口
类和结构可以继承多个接口。从接口继承意味着该类型要实现该接口中定义的所有方法
什么是接口
接口就是定义了一些未实现的成员(即接口定义了一种能力),需要实现接口的子类来实现,是多态的一种手段
注意事项
1.接口中的方法不能声明public。Private等
2.接口中能声明:方法、属性、索引器(索引器本质上也是方法)不能声明字段(因为字段是实现)
3.一个接口变量可以指向实现了这个接口的类的对象。不能指向没有实现这个接口的类的对象
泛型类型
可以使用一个或多个类型参数来定义类和结构。
静态类型
可以将类(不是结构)声明为静态。静态类只能包含静态成员,不能使用new进行实例化;类和结构都可以包含静态成员;
嵌套类型
类或结构可以嵌套在其他类或结构中。
部分类型
可以在一个代码文件中定义类、结构或方法的一部分,而在另一个代码文件中定义另一部分
匿名类型
在不方便或没有必要创建命名类的情况下,可以使用匿名类型
扩展方法
通过创建一个单独的类型,然后将该类型的方法当作始类型的方法来用,可以在不创建派生类的情况下对类进行扩展
静态类和非静态类
静态类与非静态类基本相同
区别
静态类不能被实例化。也就是说,不能使用new关键字创建静态类类型的变量。因为 没有实例变量,所以要使用本身访问静态类的成员
运算符重载(关键字operator(“ɔpəreitə”))
实例:
{
static void Main(string[] args)
{
Person p1 = new Person() { Age = 10 };
Person p2 = new Person() { Age = 11 };
Person p = p1 + p2;
Console.WriteLine(p.Age);
Console.ReadKey();
}
}
class Person
{
public int Age
{
get;
set;
}
//implictiy/
public static Person operator+(Person p1, Person p2)
{
return new Person() { Age = p1.Age + p2.Age };
}
}
重写方法(overrider)
为什么要重写方法?实现多态
用virtual、abstract关键字用来标记方法为可重写的
Overrider关键字来重写
Virtual方法(虚方法)和abstract方法(抽象方法)
区别
1.virtual方法在父类中必须有实现哪怕是一个空的实现;abstrcat方法在父类中不能有任何实现(抽象方法必须是public)
2.virtual方法在子类中可以被重写也可以不被重写;abstract方法在子类中必须被重写(但是当子类也是抽象类时可以继续把方法标记为abstract,不需要重写)
3.一个类中如果包含任何一个抽象成员,那么这个类必须标记为抽象类
委托和接口
委托
委托是一种数据类型
定义委托 delegate void SayDetegate(sting name)和定义方法类似与类是一个级别的!
区别
1.委托只能有一个方法,因为委托就是方法的指针,如果待定的代码用一个函数就可以搞定,那么用委托就很好。接口中可以定义多个方法,如果待定的代码中需要多个函数那就用接口。
2.委托传递的只是一个方法,而接口中可以传递很多成员
运用原则
能用接口就用接口,委托一般只是定义事件的时候用
文件操作相关的类
File 作文件
文件整体操作
文件拷贝
File.Copy(“C:\1.txt 原路径”,“D:\1.txt 复制到”,true)(true表示如果文件存在,则覆盖)
判断文件是否存在
File.Exists()
文件移动(剪切),重命名
File.Move(“源路径”,“移动到得路径”)
删除文件(如果文件不存在就会报错)
File.Delete(“要删除的路径”)
创建文件
File。Create(“创建到那”)
文件的读写
读取所有行 返回 string[] Encoding(按什么编码读)
File.readAllLines(“要读哪的”,Encoding.Default);
读取所有文本 返回string Encoding(按什么编码读)
File.readAllText(“要读哪的”,Encoding.Default);
读取文件 返回Byte[]
File.readAllBytes(“要读哪的”);
将string[]数组按行写入文件
File.WriteAllLines(“要写到那”,new string[],Encodin.Default)
将字符串全部写入文件
File.WriteAllText(“要写到那”,string);
将 Byte[]全部写入文件
File.WriteAllBytes(“要写到那”,new bype[])
File 类得到FileStream文件流
File.open() 返回FileStream
File.OpenRead() 返回只读的FileStream
File.OpenWrite() 返回只写的FileStream
FileStream stream=new FileStream(“路径“)
Directory 作文件夹(即操作目录)
创建目录
Diretory.CreateDirectory(“创建到那”)
判断目录是否存在
Directory.Exists(“要删除的目录路劲“)
删除空目录
Directory.Delete(“要删除的目录路劲“)
删除非空目录
Directory.Delete(“要删除的目录路劲“)
剪切(不跨磁盘)和重命名
Directory.Move(“起始位置“,”要移动到那“)
重命名File.Move(@“c:\1.txt”,@”c:\2.txt”);
Directory没有copy方法(要实现的话要自己写递归)
获得指定目录下的所有目录(即文件夹)
Directory.GetDirectories(“路径”)
获得指定目录下的所有文件
Directory.GetFile(“路径”)
//获得当前应用程序的目录
Directory.GetCurrentDirectory();
//返回当前目录的所在磁盘
Directory.GetDirectoryRoot(“path”);
//返回当前计算机上的所有逻辑驱动器
Directory.GetLogicalDrives();
返回指定路径的父路径(参数可以是绝对路径或相对路径)/返回目录对象DirectoryInfo
Directory.GetParent(“.”);
Path对返回的路径进行操作
更改路径字符串中的扩展名(只是字面上的更改,没有真实修改)
Path.changeExtension(“路径” ,”exe”)
合并两个路径
Path.Combine(“path1”,”path2”);
获得指定文件路径名
Path.GetDirectoryName(“路径”)
获得指定文件的扩展名
Path.GetExtension(“路径”)
获得指定文件的名称
Path.GetFileName(“路径”)
获得没有扩展名的文件名
Path.GetFileNameWithoutExtension(“路径”)
返回指定路径的绝对路径
Path.GetFullPath(“路径”)
获得当前系统的临时文件夹路径
Path.GetTempPath();
获得唯一的临时文件名
Path.GetTempPathFileName()
FileInfo /DirectoryInfo对象(比file和directory功能更强)
Stream(abstract)(stri:m) 流,流的祖宗,是抽象类
FielStream 文件流
读取大文件的例子
string targetPath = @"d:\gfm.avi";
FileStream fs = File.OpenRead(sourcePath);
Stopwatch watch = new Stopwatch();//测速(效率)的方法
using (fs)
{
using (FileStream fsout = File.OpenWrite(targetPath))
{
watch.Start();
while (true)
{
//每次读取的字节数
byte[] byts = new byte[1024000];
//Read方法 表示想从fs文件流中读取byts.Length个字节到byts数组中。
//返回值r是表示这次实际读取的个数
int r = fs.Read(byts, 0, byts.Length);
if (r == 0)
{
break;
}
fsout.Write(byts, 0, r);
}
watch.Stop();
}
}
MemoryStream(“meməri stri:m ”) 内存流
//由于这里不需要把对象序列化到磁盘
//只是在内存中使用一下,所以直接创建一个内存流即可
//无需创建FileStream
MemoryStream ms = new MemoryStream();
using (ms)
{
bf.Serialize(ms, this);
//反序列化
//反序列化前要把ms流的位置在移动到开始位置。
ms.Position = 0;
Person p = (Person)bf.Deserialize(ms);
return p;
}
NetworkStream 网络流
StreamReader 快速读取文本文件
StreamReader reader = new StreamReader("1.txt");
//File.ReadAllText();File.ReadAllLines();返回一个string[]数组两个方法方法与reader.ReadToEnd();//都是一次性全部读取
string str = reader.ReadToEnd();
Console.WriteLine(str);
//只要还没有读取到流末尾,就继续循环
while (!reader.EndOfStream)
{
string s = reader.ReadLine();
Console.WriteLine(s);
Console.WriteLine("================================");
}
StreamWriter 快速写入文本文件
实例
using (sw)
{
for (int i = 0; i < 10; i++)
{
sw.WriteLine(i);
}
}
GZipStram 压缩流
//读取c:\big.txt文件流
FileStream fstxt = new FileStream(@"c:\big.txt",FileMode.Open);
using (fstxt)
{
//将来要将压缩后的文件写入的那个流
using (FileStream fsout = new FileStream(@"c:\big1.txt", FileMode.Create))
{
//建立一个压缩流,指向的是c:\big1.txt
GZipStream zip = new GZipStream(fsout, CompressionMode.Compress);
using (zip)
{
while (true)
{
byte[] byts = new byte[10240];
//从big.txt读取数据岛byts数组
int r = fstxt.Read(byts, 0, byts.Length);
if (r == 0)
{
break;
}
//将压缩后的数据写入到big1.txt
//在这里做的压缩
zip.Write(byts, 0, r);
}
}
}
}
Console.WriteLine("ok");
解压:
FileStream fssource = new FileStream(@"c:\big1.txt", FileMode.Open, FileAccess.Read); //File.OpenRead(@"c:\big1.txt");
using (fssource)
{
//建立一个解压后的文件
FileStream fstarget = new FileStream(@"c:\bignew.txt", FileMode.Create, FileAccess.Write); //File.OpenWrite(@"c:\bignew.txt");
using (fstarget)
{
//这里注意,在创建GZipStream流的时候,
//需要传入一个已经被压缩的文件的流fssource
using (GZipStream zip = new GZipStream(fssource, CompressionMode.Decompress))
{
while (true)
{
byte[] byts = new byte[1024];
//从已经被压缩的文件中读取一定数量的字节
//其实是在这里就做了解压了。
int r = zip.Read(byts, 0, byts.Length);
if (r == 0)
{
break;
}
//把读取的数据写入到新流当中。
fstarget.Write(byts, 0, r);
}
}
}
}
对象序列化 和 反序列化[Serialize]( ˈsɪəri:əˌlaɪz)
什么事序列化 什么是反序列化
对象序列化是将对象转换为二进制数据,反序列化是将二进制数据还原为对象
作用
序列化和反序列化是为了保证对象的持久化
能序列化和反序列化的条件
- 对象本身是否可以序列化
- 对象的父类是否可以被序列化
- 对象中的成员是否可以被序列化
序列化用到了BinaryFormatter类(“ˈbaɪnəri:, ˈfɔ:mætə”] )
序列化实例
BinaryFormatter bf = new BinaryFormatter();
FileStream strem = File.OpenWrite(“序列化到那”);
Using(strem)
{
bf.Serialize(stream,p);
}
反序列化实例
BinaryFormatter bf = new BinaryFormatter();
FileStream fs = File.OpenRead(“反序列化的路径”)
Using (fs)
{
Object obj = bf.DesSerialize(fs);
Ponser p = (Ponser) obj;
}
程序集Assembly(əsembli)
什么是程序集
程序集是。Net的一个概念。.net中生成dll和exe文件都是程序集 英文名字叫Assembly(əˈsembli) 公用的Assembly放在AGC中(全局程序集缓存)
所有.net类都是定义在某个Assembly(əsembli)中的,.net基本类是定义在mscorlib.dll中exe也可以看做是类库,也可以引用。Exe也是Assembly。.net中的exe和bll的区别就是exe中包含入口函数,其他没有区别,exe中也可以当成bll那样引用、也可以被反编译。
Exe和dll的区别
Exe有程序入口(即有main方法)而dll没有
程序集的好处
- 程序中只引用必须的程序集,减小程序的尺寸
- 程序集可以封装一些代码,只提供必要的访问接口
GAC(全局程序集缓存)
通过GAC可以在许多应用程序之间共享程序集,GAC随.Net运行库一起自动安装。组件通常存储在C:\WINNT\Assembly中
Xml与html
Xml可扩展标记语言(extensible markup language)
Html超文本置标记语言(Hypertext markup language)
区别
都是用来对数据的操作,xml更注重于对数据的存储,比如以什么样的格式来存储数据;
html更注重数据的表现,以什么样的格式来展现数据;xml中的元素必须关闭!xml中元素的属性值必须用引号、
xml的好处
容易读懂,格式标准任何语言都内置了xml分析引擎,不用单独进行文件分析引擎的编写。方便各种程序之间的数据交换。用普通的二进制传输数据的缺点是,解析方式各异
Xml的规范
- 大小写敏感。严格区分大小写
- 有开始标签就必须有结束标签
- xml只能有一个根节点