字符串
字符串string:是不可变的数据类型
1:字符串的长度函数(Length)
2:字符串的比较函数(==(重载了比较运算符))
3:字符串的连接函数(+(重载了+运算符))
字符串stringBuild:可变的数据类型(当我们对字符串进行频繁的删除操作时,效率比string高)
4:正则表达式(功能主要是检索和匹配)
委托(委托看成是一种类型,可以赋值为一个方法的引用)
使用委托两步:
1:定义一个委托(delegate)
2:创建委托实例
2:内置委托类型:Action委托(泛型Action)(返回值为void)和Func委托(泛型Func)
3:多播(广播)委托:
多播(广播)委托只能得到最后一个方法的结果
委托不能为空
4:匿名方法:关键字(delegtate)没有名字的方法只能赋值给一个委托
deletgate(参数1,参数2){};
5:Lambda表达式(相当于匿名方法的简写形式)
lambada参数不需要声明类型和函数名()=>{};
如果只有一个参数可以这样写a=>参数自己定义,例如a=>23(23作为这个方法的返回值)
lambada表达式可以直接访问外部参数
6:事件event
public delegate void MyDelegate();定义一个委托类型
public MyDelegate mydelegate;声明了一个委托类型的变量
public Event MyDelegate mydelegate;声明了一个事件(在声明的委托变量前加Event)
事件只能作为类的成员来声明(在方法中声明事件是错误的)
事件基于委托,为委托提供了一个发布/订阅机制,可以看成是一个特殊签名的委托
7:观察者设计模式(猫(被观察者)捉老鼠(观察者))
事件只能在类(定义事件的类)的内部调用(触发),不能再类的外部调用(触发),事件可以在外部类注册
委托可以在外部触发,但是别这样用因为自己发生改变只有自己知道
Linq(数据查询)1:扩张方法2:查询表达式
1:from子句:查询操作的数据源和范围变量
2:select子句:指定查询结果的类型(创建一个临时对象new{})和表现形式(返回的是一个集合)
3:let子句:创建一个新的范围变量保存子表达式的结果
例如集合masterList
from m in masterList
let a = return m.age>8
where a
select m
创建了一个临时的范围变量保存子表达式的结果
4:orderby子句:排序结果(扩展方法OrderBy)
5:两个集合可以联合查询(扩展方法SelectMany)
6:where子句:过滤条件(扩展方法Where)
7:group by子句:对结果进行分组(按照自身的字段进行分组)
例如:集合masterList中age进行分组
from m in masterList
group m by m.age into g
select new{cout=g.Count,key=g.key}
by:表示的是按照那个字段分组
into:将分组的结果保存在标识符g中
g.key表示的是按照那个字段分的组(在这里是age)
8:into子句:提供一个临时标识符,对查询结果进行分组(分类)操作,可以理解成将join子句group子句select子句结果保存在这个临时标识符中
9:join on子句:集合联合查询(on后面跟联合的条件)
10:量词操作符扩展方法any和扩展方法all(两个方法判断集合是否满足某个条件)
反射和特性
程序是用来处理数据的,文本和特性都是数据,程序(类的定义和bcl中的类)本身也是数据
有关程序及其类型(自定的类)的数据叫元数据(元数据保存在程序集中)
程序在运行时可以查看其他程序集或其本身的元数据
1:反射:一个运行的程序查看本身的元数据或者其他程序集的元数据的行为叫做反射
使用Type(抽象类)类获取程序中类的信息(Type对象存储了类的数据(函数和成员变量))
2:特性:可以应用的类/方法
Obsolete(废弃的)特性(应用在方法前面)
Conditional特性(应用在方法前面)
调用者信息特性:放在参数的前面
DebuggerStepThrough特性:(应用在方法前面)
3:创建自定义特性:
1:特性类的后缀以Attribute结尾
2:需要继承System.Attribute
3:一般声明成sealed(密封的)
4:不需要定义方法,定义字段和属性
5:特性类表示的目标是该特性类应用到的目标结构有哪些(是引用到类还是方法还是参数上)
在定义的特性类前面加特性[AttributeUsage(AttributeTarget.Class)](表示应用到类上)
线程/任务/同步
启动应用程序那就启动了一个进程
cpu(工厂) 进程(车间) 线程(车间中的工人)
进程可以有多个线程,进程的内存空间是被(线程)共享的
线程的启动方式:异步执行(同时执行)
1:通过委托启动线程
Action a = test
a.BeginInvoke(null,null)开启一个新的线程执行a所引用的方法
如果方法有一个参数a.BeginInvoke(参数1,null,null)
如果要获取方法的返回值
可以定义一个死循环
IAsyncResult ar = a.BeginInvoke(参数1,null,null)
IAsyncResult可以获得当前线程的状态
where(ar.IsCompleted == false)
{
//线程没有执行完
}
int res = a.EndInvoke(ar)//取得异步线程的返回值
检测线程的结束通过句柄和回调函数
通过ar获取线程的等待句柄
bool isEnd = ar.AsyncWaitHandle.WaitOne(1000)//1000毫秒线程没结束返回false,否则true
if (isEnd)
{
int res = a.EndInvoke(ar)//取得异步线程的返回值
}
通过回调函数检测a.BeginInvoke的倒数第2个参数是一个委托类型的参数(回调函数)
倒数第一个参数用来给回调函数传递参数
回调函数该方法有一个参数:参数类型为IAsyncResult ar
将Func a = ar.AsyncState as Func;将参数转换为委托类型
2:通过Thread类启动线程
创建一个线程
Thread t = new Thread(方法)
执行线程
t.Start()
怎样给线程传递参数
在Start方法中传递参数:t.Start(参数1)
第二种方法创建一个类类中定义一个方法和需要的数据Thread t = new Thread(类的方法)
3:后台线程和前台线程
Thread创建的线程是前台线程,线程池创建的线程为后台线程
只要前台线程在运行,则应用程序就在运行
将线程设置为后台线程t.IsBackground = true
当前台线程结束了(应用程序关闭),运行的后台就会结束
终止一个线程t.Abort()
等待线程结束t.Join假设在main线程执行t线程的Join函数,
main线程睡眠等待t线程执行完毕后再执行
4:线程池创建线程 ThreadPool创建的线程为后台线程
ThreadPool.QueueUserWorkItem(方法)开启一个工作线程
ThreadPool.QueueUserWorkItem(方法,方法的参数)开启一个工作线程
5:任务启动一个线程
创建一个任务(任务相当于对线程进行了封装)
Task t = new Task(方法)传递一个需要任务(线程)执行的方法
启动一个任务
t.Start()
用任务工厂创建和启动一个任务
TaskFactory t= new TaskFactory()
Task t = t.StartNew(方法)
6:任务的其他知识
连续任务:任务1依赖任务2,那么任务2执行完才开始执行t1
Task t2 =t1.ContinueWith(方法11)t1执行完才会执行方法11
任务层次结构(任务有父子关系(任务中开启另一个任务))
7:线程问题:争用条件和死锁
争用条件:两个线程同时访问同一块内存:解决方法给这一块内存加锁(lock(内存))
死锁:
Socket编程(网络通信)
服务器:
1:创建 socket
Socket tcpserver = new Socket(AddressFamily.InterNetwork,
ScoketTyep.Strem,ProtocolType.Tcp)
2:绑定id和端口号
IPAdress ipdress = new IPAdress(new byte[]{192,168,0,112)
EndPoint point = new IPEndPoint(ipdress,8888);IPEndPoint对ip和端口做了封装
tcpserver.bind(point)
3:开始监听(等待客服端连接)
tcpserver.Listen(100)
4:这个方法可以让当前线程暂停直到有客服端连接,才会执行Accept后面的代码
Socket clentSockt = tcpserver.Accept()返回值为连接到的客服端的socket
5:发送消息
string message = "你好"
byte[] data= Encoding.UTF8.GetBytes(message)//对字符串进行编码,得到一个字符串的字节数组
clentSockt.send(data)
客服端:
1:创建 socket
Socket tcpCliet = new Socket(AddressFamily.InterNetwork,
ScoketTyep.Strem,ProtocolType.Tcp)
2:发起连接请求
IPAdress ipdress = IPAdress.Parse("192.168.0.112")
EndPoint point = new IPEndPoint(ipdress,8888);IPEndPoint对ip和端口做了封装
tcpCliet .conncet(point)//通过ip和端口
3:接收数据
byte[] data = new byte[1024]
int length = tcpCliet.Receive(data)data数组用来接收数据length返回值表示接收了多少数据
string message = Encoding.UTF8.GetString(data,0,length)将字节数组转换为字符串
聊天室:
服务器端:
1:创建 socket
Socket tcpserver = new Socket(AddressFamily.InterNetwork,
ScoketTyep.Strem,ProtocolType.Tcp)
2:绑定id和端口号
IPAdress ipdress = new IPAdress(new byte[]{192,168,0,112)
EndPoint point = new IPEndPoint(ipdress,8888);IPEndPoint对ip和端口做了封装
tcpserver.bind(point)
3:开始监听(等待客服端连接)
tcpserver.Listen(100)
4:这个方法可以让当前线程暂停直到有客服端连接,才会执行Accept后面的代码
while(true)
{
Socket clentSockt = tcpserver.Accept()返回值为连接到的客服端的socket
创建一个客服端的类保存连接的客服端的Socket
Client client = new Client(clentSockt )把与每个客服端通信的逻辑放到client类处理
在服务器创建一个链表保存客服端的Socket
clientList.add(client )
}
Socket编程:UDP协议
服务器端:
1:创建 socket
Socket udpserver = new Socket(AddressFamily.InterNetwork,
ScoketTyep.Dgram,ProtocolType.Tcp)
2:绑定id和端口号
IPAdress ipdress = new IPAdress(new byte[]{192,168,0,112)
EndPoint point = new IPEndPoint(ipdress,8888);IPEndPoint对ip和端口做了封装
udpserver.bind(point)
3:接收数据
EndPoint remoteEndPoint = new IPEndPoint(IPAdress.any,0)
byte[] data = new byte[100];
int length = udpserver.ReceiveFrom(data,ref remoteEndPoint);
ReceiveFrom这个方法会把数据的来源(客服端的ip和端口)放到第二个参数
只要有数据才会执行ReceiveFrom方法后面的代码否则会等待
string message = Encoding.UTF8.GetString(data,0,length)将字节数组转换为字符串
客服端:当与服务器端建立连接会分配端口
1:创建 socket
Socket udpClicnt = new Socket(AddressFamily.InterNetwork,
ScoketTyep.Dgram,ProtocolType.Tcp)
2:直接发送数据
string message = "123"
byte[] data= Encoding.UTF8.GetBytes(message )
IPAdress ipdress = IPAdress.Parse("192.168.0.112")
EndPoint serverPoint = new IPEndPoint(ipdress,8888)
udpClicnt.sendTo(data,serverPoint)这个方法会把数据发送到服务器
tcplistener和tcpclient和udpclient只是对Socket进行了一层封装
tcplistener(服务器)
1:通过构造一个TcpListener对象时就会创建Socket和Bind
TcpListener listener = new TcpListener(IPAdress.Parse(192.168.1.88),7788)
2:开始进行监听
listener.Start()
3:等待客服端的连接
TcpClient clinet = listener.Start.AcceptTcpClient()
4:取得客服端发过来的数据
通过网络流来进行数据交换(read/write函数)
NetworkStream stream = clinet.GetStream();得到一个网络流,从这个网络流中获得客服端的数据
byte[] data = new Byte[1024];保存接收的数据
int length = stream.Read(data,0,1024)
string message= Encoding.UTF8.GetString(data,0,length)
5:释放资源
stream.Close()
client.Close()
listener.Close()
tcpclient(客服端)
1:通过构造一个TcpClient对象时就会跟服务器建立连接
TcpClientlistener = new TcpClient("192.168.1.88",7788)
通过网络流来进行数据交换
NetworkStream stream = clinet.GetStream();获得网络流进行数据的交换
string message = "123"
byte[] data = Encoding.UTF8.GetBytes(message)
stream.Write(data,0,data.Length)
stream.Close()
client.Close()
UdpClient
服务器
1:创建UdpClient
UdpClient udpClient = new UdpClient(new IPEndePoint(IPAdress.Parse(192.168.1.88),7788))
2:接收数据
IPEndePoint point = new IPEndePoint(IPAdress.any,0)
byte[] data = udpClient.Receive(ref point)
string message = Encoding.UTF8.GetString(data)
udpClient.Close()
客服端
1:创建UdpClient对象
UdpClient udpClient = new UdpClient()
string message = "123"
byte[] data = Encoding.UTF8.GetBytes(message)
udpClient.Send(data,data.Length,new IPEndePoint(IPAdress.Parse(192.168.1.88),7788))
udpClient.Close()
文件操作
1:通过FileInfo和DirectionInfo读取文件和文件夹的属性
创建FileInfo对象
FileInfo info = new FileInfo("1.txt")
创建DirectionInfo对象
DirectionInfo info = new DirectionInfo("test")
if (info .Exists() == false)如果文件不存在创建文件夹
info.Create("test")
2:通过File读写文件(获取文件的内容)文件(文本文件和非文本文件)
File不需要创建File的对象通过类名调用函数进行读写
3:通过FileStream读取二进制文件的内容
需要创建一个FileStream对象
创建文件流用来读写数据
FileStream file = new FileStream("t.txt",filemode.Create)
4:使用StreadReader和StreamWriter读取文本文件的内容
StreadReader(文件读取流)
StreadReader reader = new StreadReader("t.txt")
string str = reader.ReadLine();
reader.Close()关闭流
StreamWriter(文件写入流)
StreamWriter writer = new StreamWriter("t.txt")
writer.WirteLine("1111111111")
writer.Close()
Xml/Json/Excel
Xml的使用
xml本质上是一个文本文件
Xml:可扩展的标记语言,用来存储和传输数据
Xml:只有有一个根元素,根元素下包含子元素
Xml元素是从开始标签到结束标签的部分
XmlDocument是专门用来解析xml文档的
XmlDocument doc = new XmlDocument()
//选择要加载的xml文档的名字
doc.Load("skill.txt")或者doc.LoadXml(File.ReadAllText("skill.txt"))
得到根结点(xmlnode用来代表一个结点)
XmlNode rootNode = doc.FirstChild()
//得到根结点下面的所有子节点
XmlNodeList skillist = rootNode.ChildNodes;
//创建一个类Skill用来存储xml文档中的数据
List s = new List()
foreach (XmlNode s in skillist)
{
XmlNodeList flist = s.ChildNodes;//得到s结点下面的所有结点
foreach (XmlNode schild in flist)
{
Skill skills = new Skill();
if (schild.Name == "id")//通过Name的属性可以获取一个结点的名字
{
int id = Int32.Parse(schild.InnerText)获得xml元素(结点)的内容
skills.ID = id;
}elseif (schild.Name == "name")
{
string name = schild.InnerText获得xml元素(结点)的内容
skills.Name = name;
skills.Lange = schild.Attributes[0].value;获取该标签(name)的属性
}
s.add(skills)
}
}
XmlElement元素继承自XmlNode
假设有标签Name可以
foreach (XmlNode schild in flist)
{
XmlElement ele = schild["Name"]通过字符串字符串索引器获得元素
然后ele.InnerText获得元素的内容
}
//XmlAttributeCollection col = schild.Attributes获取属性的集合
假设有标签两个属性damage="10" lange = "22"
int damge = Int32.Parse(col["damage"].value)
int lange = Int32.Parse(col["lange "].value)
Json的使用
数据保存在键值对中,数据由逗号分隔花括号保存对象,方括号保存数组
Json的只能有一个数组或者一个对象
解析Json
两种引入litjson库的方法
1:在vs中添加外部库在项目下面的引用中添加
2:引用->打开netget程序包->联机里面搜索litjson
使用JsonMapper解析跟泛型解析
jsonData 在这里代表一个对象或者数组
JsonData jsonData =JsonMapper.ToObject(File.ReadAllText("s.txt"))
foreach(JsonData temp in jsonData )
{
通过索引器取得键值对的值
JsonData value = temp["id"]
int id = Int32.Parse(value.Tostring())
}
泛型解析
Skill[] jsonData =JsonMapper.ToObject(File.ReadAllText("s.txt"))
foreach(Skill temp in jsonData)
{
}
将一个对象转换为json文件
假如有一个对象
Playe p = new Player()
p.Name = "123"
string json = JsonMapper.ToJson(p);
Excel操作
通过Oledb操作Excel
1:连接数据源
string filename = "1.xls"
String connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source="+filename+";"+"Extended Properties='Excel 8.0;HDR=Yes;IMEX=2'";
OleDbConnection connection = new OleDbConnection(connectionString )
2:打开连接
connection.Open()
string sql = "select * from [Sheet1$]"
OleDbDataAdapter adapter = new OleDbDataAdapter(sql,connection)
DataSet set = new DataSet()用来存放查询到的数据(用来存放DataTable(表格))
adapter .Fill(set)将查询的结果(结果是个DataSet)存放到set中
connection.Close()
取数据
DataTableCollection tableColection = set.Tables()获取当前集合中所有的表格
DataTable table = tableColection[0]因为只有一张表格
取得表格中的数据
取得table中的数据
DataRowCollection rowCollection = table.Rows;返回一个行的集合
遍历行的集合,取得每一个行的datarow对象
foreach(DataRow row in rowCollection )
{
取得row中前8列的数据
for(ini = 0; i<7;i++)
{
console.write(row[i]+" ")
}
}