第一天
1. Console.ReadKey()吸收键盘输入的下一个任意字符。
2. Convert.---为转换变量的类型;
3.Console.ReadLine,写入的为string类型;并只能输入一个。若想输入为汉子,之后Convert
4.计算是否为质数的方法 private static bool IsPriem(int i)
{
int j;
if (i < 2)
return false;
for(j=2;j< i;j++)
{
if (i % j == 0)
return false;
}
return true;
}
5.定义数组时int[] numbers= { 1, 3, 5, 7, 90, 2, 4, 6, 8, 10 };
调用数组时int maxNum = GetMaxArray(numbers);
6.强制改变参数类型(int)7.9,将7.9转化为整形的;
7.输出两位小数Console.WriteLine("该数组的平均值为:{0:0.00}", sumer);
8. WriteLine();一个是数据写在一行上,下一个数据换行
Write();所有数据写在一行上Console.Write(nums[i]+"\t");
9.冒泡排序
for (i = 0; i < nums.Length-1;i++)
{
for (j = 0; j
{
if(nums[j]
{
temp = nums[j];
nums[j] = nums[j +1];
nums[j + 1] = temp;
}
}
}
10.求关键字的索引
while ((index = text.IndexOf(kayWord,index)) != -1)
{ (这是一个方法IndexOf)
count++;
Console.WriteLine("索引是{0},总共出现了{1}次.",index, count);
index = index + kayWord.Length;
}
11.定义集合listName的方法:List listName = new List();
集合的优点为:存多少数据都可以,而数组只能存有限个成员。
12.将字符串变为字符数组的方法:char[]chs=str.ToCharArray();
将字符数组变为字符串的方法:string newDate = new string(chs);
13.继承的方法:public classTeaceher:Person
重写方法:public virtual void SayHi(){}
public override void SayHi(){}关键词为virtual和override
14.创建一个类类型的数组:ItcastClassa = new ItcastClass();括号重要
15.索引
public class ItcastClass
{
private string[] _names= { "老杨", "老苏", "老马", "老牛", "老虎" };
public string this[int index]//固定形式
{
get
{
return _names[index];
}
set
{
_names[index] = value;
}
}
}
16. 让comBox1显示第一个的方法
privatevoid Form1_Load(object sender, EventArgs e)
{
comboBox1.SelectedIndex=0;
}
计算器的核心代码;
if (comboBox1.SelectedIndex> 0)//判断是否选择的为符号
{
int number1 = Convert.ToInt32(txtNumber1.Text.Trim());
int number2 = Convert.ToInt32(txtNumber2.Text.Trim());//取两个数的值
switch (comboBox1.Text)
{
case "+":txtSum.Text = (number2 + number1).ToString(); break;
case "-":txtSum.Text = (number2 - number1).ToString(); break;
case "*":txtSum.Text = (number2 * number1).ToString(); break;
case "/":txtSum.Text = (number2 / number1).ToString(); break;
default:
break;
}
}
else
{
17. MessageBox.Show("请选择运算符");//当未选择符号时,显示的内容(通知并指示用户的消息框)
}
第二天
1.反转数组的方法
string[] country = { "中国", "美国", "巴西", "澳大利亚", "加拿大" };
string str;
for (int i = 0; i <= country. Length /2; i++)
{
str = country[i];
country[i] = country[country.Length - 1 - i];
country[country .Length - 1 -i] = str;
}
2.控制winform内的各种控件的方法
foreach (Control item in Controls)//该循环和for差不多,但不可以改变循环内的值 (意思是form里面的所有控件)
{
if (item is Label)
{ (Label是一类控件,可以更换)
item.Text = "帅";
}
}
3. 随机数 随机生成10个1-100数中飞重复数字放入ArrayLise数组中
ArrayList array =new ArrayList();//实例化需要头文件(Using.System.Collections)
(定义随机数) Random r = new Random();//伪随机数,有种子存在
int count = 0;
while (array.Count<10)
{
int num = r.Next(1, 101);//在什么范围的方法
if(!array.Contains(num))//数组是否包含某个数的方法
{
array.Add(num);//数组添加数的方法
}
count++;
}
5.规范
多行注释 /*
*
*
*/
单行注释 //
文档注释在类的上面一行敲三个\\\,会自动出现.
6.static在方法中的作用,以此修饰的方法的时候,为静态方法,只能通过类名调用。
而未经修饰的方法,要用对象调用。
7.新建类要注明访问权限。
类中构造函数也要注明访问权限/
定义类对象时的方法:Student stu = new Student("李阳",'男',21);
8.构造函数定义:publicTeacher(string name,char gender,int age)
类的继承方法:public class Student:Person//不必声明继承权限
类继承中初始化字段的方法:public Student(string name,char gender,int age):base(name,gender,age) 不是基 类 名字而是关键字base
9. 快速操作的方法:Cirl+.
10. winform运用面向对象的方法,先根据题意写出所需类,再在winform框中点击控件进行调用编码。然后再对所有的控件赋值例如:labPlayer.Text= p.FistName;
直接定义属性,不写出字段: public stringFistName 可以像字段一样使用。
{
get;
set;
}
可以将一段代码直接提取为一个方法用快捷键即可。
11.一个可以简化的方法 private void button1_Click(object sender, EventArgse)
{
Button btn = (Button)sender;
//该行代吗为中心代码
Start(btn.Text);
}然后将所需操作的控件属性中闪电标志里的click选定为button1_Click即可。
12.字段的属性中get和set函数称为访问器,分为只读,只写,可写可读访问器。
13.索引器的写法
public string this[int index](必须为中括号)
{ (相当于对象的地址)
get //( 必须带着所需的函数,不必带着参数)
{
string str = ""; (必须赋初值)
switch (index)
{
case 0:str = _name; break;
case 1:str = _age;break;
default:
break;
}
return str;(在类中返回)
}也可加上Set 函数进行通过下标赋值
索引器可重载,public string this[string kay]这样写的话,可以进行p[“name”]这样访问。
写索引的时候,系统会将this变为Item关键字,如果在类中自己重新定义一个Item会报错。
14,添加引用 要添加项目才可以,点新添加的项目,有一个为引用,选择添加引用并选择所想添加的项目,便可以在新项目中使用另一个项目中所写的类(该类的返回值也要为公有的),但注意需要添加命名空间
using.类名;才可以。
15.静态方法只能使用静态成员,或者本方法中定义的字段。并多个对象共享一个成员。
16.构造函数补充之一些基础小知识。
class Program
{
static void Main(string[] args)
{
Person p = new Person();//会调用Person的构造函数
Console.ReadKey();
}
}
public class Person
{
int num = 10;//系统会将该行代码放入无参构造函数里面,所以经过上述操作后会被执行
}
17,Csharp 中只能单继承,object是C#中最基础的类。
18.可以通过this方式调用本类的构造函数或成员,调用构函例如:
public Person(string name,char gender,intage)
{
_name = name;
_gender = gender;
_age = age;
}
public Person(string name):this(name,'男',10)
{}
19.若子类没有重写父类的数据成员,则this和base没有区别,若重写了父类的数据成员,则this调用子类的,base 调用基类的成员。
20.Cshaarp中类中的成员如果不写访问权限,默认为私有的。
Internal访问权限在一个程序集中可用。
Protected internal在程序集和子类中可用
21.注意访问级别约束问题.
第三天
1.字段的类型转换方法:case 1:str= _age.ToString();break;可以用Tostring 等方法进行调用函数转化。
2. 静态方法调用是通过类名.方法名();如果在本类中,直接方法名();也可以使用。静态方法不能是虚方法。
3.非重点,若父类和子类中有相同的方法名,会报警告,在子类中的该方法上添加一个new关键字即可,起到截断作用,将子父类的方法分开。
4.小技巧,若想再写一个主函数,svm后再按两次Tab键即可。
for两次Tab键后为正方向的循环,forr两次Tab键后为反方向的循环。
5.“方法签名”是指方法的名字和参数列表,不包含返回值类型。
6.方法里面声明的叫做变量,方法外面的叫做字段和属性。
7.C# 中没有全局变量,不能再类外声明变量。
8.静态类的知识点:
静态类中只能定义静态成员,
并且静态类不可以实例化(因为在反编译代码中他是一个抽象(abstruct)的类),
不能被继承(因为静态类是被封装(sealed)的类在反编译的中间代码中可以观察到)。
静态类的构造函数不能有参数,不能有访问修饰符(默认为私有的),再在前面加上static关键词即可。
并且只能用一次构函。(用处不大)
9.多态中的重写案例:
classProgram
{
static void Main(string[] args)
{
Person per = new Person();
Console.WriteLine(per);//该处调用的为per.Tostring();方法,若未重载则输出作用域名。
Console.ReadKey();
}
}
publicclass Person
{
string _name;
public override string ToString()//对Tostring方法的重写,即前面的输出为“加油“
{ return "加油!"; }
}
10.“多态“的实现:包含三种:接口,abstract抽象,virtual虚方法
1.虚方法多态如下:
虚方法的注意事项:
( 父类中必须有实现
子类中可以不重写
可以在普通类中实现
)
父类将方法改为虚方法(virtual)public virtual void Say();
子类重写(override)该方法,并要保持方法除关键字外其余完全相同public overridevoid Say()
在主函数中父类对象实例化子类,Person p = new Teacher();
通过父类对象调用重写的函数对哪个子类实例化,便调用那个子类的该函数。
2.抽象方法多态如下:
抽象类的注意事项:
(抽象方法不能有主体public abstractvoid Say();
抽象方法只能在抽象类中定义。
抽象类不能实例化。
抽象类中可以有普通成员,字段和方法。
抽象类如果被继承了,里面的所有抽象的成员必须被非抽象子类重写。若为抽象子类则不一定实现。
抽象类为子类而活。
)
抽象方法的多态实现:(在需要相同方法,但内容不一样,则抽象多态)
定义一个父类为抽象类,并定义所需多态的方法。public abstract class Amianl
在其子类中重写该方法。public override void Say(){。。}
在主函数中定义父类 对象对子类的实例化Amianl p = new Dog();
将该对象调用方法,为实例化子类的方法。p.Say();
3,接口方法实现多态(下文有)
总:遇到多态问题时,先考率接口,再抽象类,再虚函数。
11.is返回值为bool类型。比如:If(per is Person)说明per这个对象是不是Person类的对象。
12.面向对象方法的感想:定义一个类库,在类库中添加所需要的类,然后在所操作的项目中引用该类库。
方法返回类型可以是类类型,
private static JiSuan Show(string str, int number1, int number2)
{
JiSuan ji = null;
switch (str)
{
case "+": ji = new Add(number1,number2); break;
case "-": ji = new Sub(number1,number2); break;
default:
break;
}
return ji;
} 此中将基类对象对不同子类进行实例化,实现了多态。
13.值类型与引用类型的讲解:
值类型:(不能为null的类型)包括int,double,long,short,char,结构,枚举等。。。
值类型几乎存在栈上面
值类型赋值时是在栈上另外开辟一个空间存储。
引用类型:包括string,数组,类类型,接口等。。。。
引用类型的内容几乎在堆上面,但会在栈上面开辟个空间存放地址。
引用类型赋值时,是在栈上面重开个空间存放该改内容的地址,两个空间指向同一
个堆上的内容。
传参知识点:若在传参的时候前面加了ref,则不管是值类型还是引用类型都只传递地址。
若值类型传递时为ref传递参数(必须在实参和行参处都加上ref例如public staticvoid Add( ref int num); Add(ref number) ; ),则实参会发生改变,否则,实参不会改变,仅形参改变。
若引用类型传递时,不为ref传递,也是将地址传过去,实参值也会发生改变。
对于引用类型数组的传递,赋值是把头地址传过去,就是说将其内容完全覆盖。
第四天
1.接口
接口不能实例化。
接口的成员不能有主体(大括号),不能有任何修饰符,系统会隐式转换为public和abstract。
接口可以有属性,方法,索引器等,不能有字段。
接口的调用:public class MaQue:Bird,IFly; 逗号和接口名字,类似c++中类的多继承。并且接口应放在所继承类之后。
接口可以对子类进行实例化,相当于父类对子类的实例化,调用的为子类中的方法。
接口中所有的成员必须在子类中全部实现,除非子类是抽象类(可以在类中将接口中的成员抽象为抽象方法,使其在子类中实现)。
接口与接口也可以类似于继承,其中的方法不用实现。定义多个职责单一的接口,组合使用。
接口的使用时候:几个类不能抽象出一个统一的父类,但还都需要一个相同的方法。
接口的单一职责原则。
子类实现接口时,返回值方法名参数类型都不能变,与重写差不多。
显示实现接口 (void IDengji.Dengji(){})
显示实现的接口,只能通过接口变量来调用 IDengji deng = new Chinese();
(因为显式实现接口系统将其弄为私有的 deng.Dengji();
显式实现接口可以解决重名的问题。
2.枚举
枚举的关键字enum,定义方法enum Gender
{
男,(一个一行,用逗号分隔)
女 (最后一个后面什么也不加)
}
一般将枚举写在类外。
枚举的内容的本质为数字。除却赋值的,其余所代表的int 值都不变
调用方法,通过名字. 调用。
枚举的好处:可以屏蔽一些单词的问题,通过点就可以找出你所要用的单词,不必苦记。
可以使一些数据规范化,例如性别,如若让人输入,则五花八门,不便查询和计。运用枚举后只让在枚举的类型里选择,则数据就规范化了。
标志枚举
3.结构
结构的关键词:struct定义如下: struct Person
{
publicstring name;
publicint age;
}
一定要加public修饰词才可。
类比:int double 都是结构类型的,非类类型的。
4.C# 是语言,.NET是技术。Java即使语言也是技术
5.装箱 拆箱
装箱:值类型直接转引用类型
拆箱:引用类型强转为值类型。以后会详细介绍。
6.类型转换
简单:int num=10;double num1=num;为隐式类型转换
double num2=(double)num;为强制转换
用方法转换:string s=”90”;int num=Convert.ToInt32(s);//会报异常
int num=int.Parse(str);//会报异常,和上个一样
bool b=int.TryParse(str,out num);//不会报错,返回bool类型,若成功则将转化后的值存到num里面,并返回true.若不成功则num=0;返回false.
7.异常处理
万不得已的时候:try(会占资源,所以尽量不用)
{
////放出现异常的代码,当执行到代码出现异常后,该代码后面的语句都不执行。
}
catch(Exception ex)//////Exception为一个系统类,ex为自定义的
{
throw;////为自动添加的语句,将错误抛出,给程序员看的
Console.WriteLine(ex.Message);/////自己手动加上的语句,输出系统提示的错误提示信息。
}//////catch语句可以有多个,但try语句就只能一个
最好用别的方法处理,比如Convert出现异常时就可以改为TryParse.
finally{/////这里面的代码什么时候都会执行,若代码在异常语句之后,则后续不执行。
}
8.可变数组
前言:所有的数据成员都可以转化为object类型的,因为object是所有类的父类。
若形参设定为object类型的数组或变量,则可以传任何类型。
要点:可变参数数组必须为形参的最后一个参数
关键词params例如:int sum =Show(1,2,3,4,5,5,6,7);
public staticint Show(params int []num){}
9.out 和ref关键字
out是把方法内的值传到方法外面;
使用out时,当调用这个方法时,在外部的变量可以不赋值。
在方法内部,必须要为out所修饰的变量赋初值。
例如:(out在传参方面有很大的不同)
static void Main(string[] args)
{
int num;
Add( out num);
Console.WriteLine(num);
Console.ReadKey();
}
public static void Add(out intnum1)
{
num1 = 10;
num1++;
}
out使用技巧小案例:(部分)
int password = Convert.ToInt32(Console.ReadLine());
string tip;
Check(name, password, out tip);
Console.WriteLine(tip);
Console.ReadKey(true);
}
}
public static void Check(string name,int password,out string tip)
{
if (name == "admin" && password == 123)
{
tip = "登陆成功!";
}
对于out和ref,使用他们时,实参和形参都必须加上关键词
/////////////////////////////////////////////////////
对于ref将地址传到形参,不管是值类型还是引用类型。
ref要在外部对变量赋初值,方法内部不用。
10.方法重载
与参数的类型和顺序(不同类型)有关;
若两个形参参数类型相同,两个都有out或ref或params其中的一个,则不为重载。
若两个形参的参数类型相同,一个有上述修饰符,一个没有,则他们为重载。
11.是否为同一个对象的判断(内容一样不代表为同一个对象)
1.可以通过==或p1.Equals(p2)【为object的方法,在这个方法里首先判断是否内容相同,再调用RfE方法,还有就是string类型的将==和Equals重写了】方法来判断。(不准确)(以后少用)
2.object.ReferenceEquals(p1,p2);(准确)(尽量用)
12.常用类库String(大小写一样)
字符串的不可变特性:不能通过索引修改他的值。
而string s=”q”; s=’sd’;是重新开辟一个空间,将s的地址改为新开辟的地址,就相当于修改了值。
字符串的拘留池特性:每次对字符串变量赋值(该值只针对于常量“a”,不针对于变量a)时,会将该值放在拘留池中,下一次对另一个字符串类型的变量赋值时,先在拘留池中找有没有相同的值,如果有则将该值取出,赋值给该变量,这就导致这两个变量变成了同一个对象。若没有找到相同的值,则会将付的值放入拘留池。
字符串常用属性和方法:1.Length返回字符串的长度
2.if(string.IsNullOrEmpty(str))//该方法判断字符串str是否为空。
(null是不在栈上存地址,“ ”是开了个什么都没存的空间)
3. str.ToCharArray();将字符串变为字符数组。
4.str.ToLower();变为小写str.ToUpper();大写,返回类型为string
5. intindex=str.IndexOf("为");在str字符串中找到‘为‘字,并返回索引值,赋值给ingdex. LastIndexOf();找到最后的。
、 6 str =str.Substring(3);//从第三个截取到最后一个
str = str.Substring(3,4);.//从第三个截取4个后停止。
7.string str = "20110--12--34";string[]strs= str.Split('-');将str里面的-切掉返回值为string 数组;该方法会将删除的东西变为空字符,占用数组空间string[]strs = str.Split(new char[]{'-'},StringSplitOptions.RemoveEmptyEntries);会将其完全删除,不留痕迹。(可以同时切除多个不同的,写入char数组即可,string数组也可以,去除一个字符串)
8. str = str.Join("*",strs);//将strs数组里面的每一项与下一项的中间添加一项*;
9.string str=string.Format("{0}","hua");//类似于WriteLine但F有返回值,W没有。为静态方法,因为是通过string 类调用的。后期会用到。
10. str.Contains("为");//查看str数组里是否有‘为’字,返回类型为bool类型。
11.string str1 = str.Replace("为", "位");//将str里面的为字换为位字,并返回替换后的字符串。
13.读文件操作写文件
关键词File ,需要命名空间using.system.IO;
例如:string[] name = File.ReadAllLines("salary.txt",Encoding.Default);
(有好几种,此为读一行) (避免出现乱码)
第五天
1. @的用法
写文件的路径时,需要两个\\但只有\,可以在路径前加一个@“路径”。
若想声明一个标识符的变量 但系统会报错,则在前加@即可。int @int=10;
2.获取文件名
两种方法:
1. string name = @"C:\ProgramData\ppcrlconfig600.dll";//@的用法
int index = name.LastIndexOf("\\");//两个\\相当于\
string n = name.Substring(index + 1);\\截取index后的字符
Console.WriteLine(n);
Console.ReadKey();
2. string name = @"C:\ProgramData\ppcrlconfig600.dll";
Console.WriteLine(Path.GetFileName(name));//Path需要IO命名空间
Console.ReadKey()
3.比string好点的数据类型StringBuilder(拼接大量字符串时用这个拼接,不要用string)
ps:在后期写网址的时候会用到。对于string类型的开启空间过多。
StringBuilder 不需多开辟空间,操作StringBuilder sb = new StringBuilder();
sb.Append("
");
sb.Append("
");
sb.Append("
=hahhahah=
");
sb.Append("");
sb.Append("");
stringBuillder不是string类型的最后需要转换Console.WriteLine(sb.ToString());
4.GC垃圾回收器
1. GC.Collect();//手动将程序中的垃圾回收。程序会有卡顿。
2. Person per = new Person();
per.Name = "sk";
WeakReference wrf = new WeakReference(per); // WeakReference 为弱引用,释放后还可以再用,就是用wrf替换了per。
object o = wrf.Target;//重要
5.foreach 遍历(为只读的,不能修改循环内的值)
1.对于该遍历通过分析,发现,如果能被foreach遍历,那么就必须有GetEnumerator()方法,但是,后来又发现这个方法不属于List这个类,是属于IEnumerable接口。如果让自己的类也实现IEnumerable这个接口,就可以有GetEnumerator这个方法,就可以通过foreach遍历。
2.foreach的真正含义:(当遇到不能遍历的对象的时候)
手写foreach代码:(这个只针对于集合的遍历,对于别的有好多写法)
List list = new List();
list.Add(1);
list.Add(2);
list.Add(3);
IEnumerator ie = list.GetEnumerator();//调用集合的Get。。
while (ie.MoveNext()//调用该接口的方法,此方法为移动到下一个
{
Console.WriteLine(ie.Current);//Current为属性,作用为显示当前值
}
Console.ReadKey();//本程序展现了foreach的本质过程与方法
前言:IEnumerable 通过List泛型集合,发现,这个方法在IEnumerable这个接口中
现在实现这个接口,但是通过观察发现,这个方法有个返回值IEnumerator接口
代码:class Program(观看yield关键词,可将下属代码化简,在6-10天笔记中)
{
static void Main(string[] args)
{
Person per = new Person();
foreach (var item in per)//发现不能遍历,通过错误查看没有某个方法。
{ Console.WriteLine(item); }
Console.ReadKey();
}
}
public class Person: IEnumerable//最后发现该方法在这个接口,所以该类将其实现
{
string[] names = { "yang", "hua", "kai" };
public IEnumerator GetEnumerator()//发现返回值为一个接口,则考虑新建类实现该接口并在此返回其对象。
{ return new MyIEnumerable(names);}
}
public class MyIEnumerable : IEnumerator//实现该接口的类
{
string[] name;
int index=-1;
public MyIEnumerable(string[]names)
{name = names;}//将所需操作的对象通过构造函数传递过来。
public object Current//以下三个方法为实现的接口,内容通过大胆仔细推演得出
{ get //该方法为显示当前内容,可直接调用
{ return name[index];}
}
public bool MoveNext()
{ index++;
if (index>=name.Length)
{return false; }
else
{return true;}
}
public void Reset()
{index = -1;}
5.集合
1.集合命名空间:
using System.Collections;(非泛型集合)
using System.Collections.Generic;(泛型集合)
2. 常用集合
“类似数组”集合:ArrayList、List////////////T为类型
“键值对”集合(“哈希表”集合):Hashtable、Dictionary//常用的
“堆栈”集合:Stack、Stack(LIFO)
“队列”集合:Queue、Queue(FIFO)
“可排序键值对”集合:(插入、检索没有“哈希表”集合高效)
SortedList、SortedList(占用内存更少,可以通过索引访问)
SortedDictionary (占用内存更多,没有索引,但插入、删除元素的速度比SortedList快)
Set 集合:无序、不重复。HashSet,可以将HashSet类视为不包含值的 Dictionary集合。与List类似。SortedSet(.net4.0支持,有序无重复集合)
“双向链表”集合:LinkedList,增删速度快
3.ArrayList集合的定义域使用(不经长用,因为涉及到装拆箱,效率低)
1.定义为:ArrayList arrayList = new ArrayList();//括号内可以放好多种东西。
2.对于添加为:arrayList.Add();和arratlist,AddRange()//括号内必放东西,什么类型都可以。
3.用法: int[] nums = { 1, 2, 3 };
ArrayList arr = new ArrayList(nums);//现在集合里面有三个
arr.Add(nums);//4个添加的是不管是什么,集合都将其看作一个整体,集合就多一个成员。
arr.AddRange(nums);//七个,添加的为数组几个元素,集合就多几个成员。
arr.Remove(7);//将集和中的7数字移除
arr.RemoveAt(7);//将集合中的索引为7的数据移除
arr.Clear();//清空集合
arr.Reverse();//反转集合
arr.Sort();//给集合排序
4.特殊用法:ArrayList ar = new ArrayList() { "a", "b", "c"};//相当于在进行实例化的时候就对集合进行了初始化。
5.泛型集合List和字典Dictionary;(常用)(推荐用)
1.T为某个数据类型
2.Dictionary<中间为键值对>,与哈希表不同处在于定义方式不同Dictionarydic = new Dictionary();//括号里面为kayh和value的类型。ps:这里面的kay也不能重复,且无序。
3.两者都可以foreach遍历。
6.数组与别的类型的父类
数组的父类为Array类,int和double等的父类为ValueType类
7.var具有推断的能力(会在foreach循环里面出现)
8.哈希表(键值对:kay和value)(集合的一种)
1.哈希表为字典的一种。
2.哈希表用for循环遍历不合适,要通过foreach遍历。
3.哈希表的kay不能重复。
4.哈希表通过kay来存value值。没有了kay,就没有value(内部对应索引,也相当于通过索引调用)
5.哈希表在显示的时候无序。(相当于无序执行)
6.定义和用法:usingSystem.Collections;//哈希表所需头文件
Hashtable h = new Hashtable();//关键词类
h.Add("1", "haha");//这两个参数都为object类型的,第一个为kay,第二个为value。
h.Add(4, "34");
Console.WriteLine(h["1"]);//通过kay来获取对应的value值。
bool a=h.ContainsKey(objectkay);看看表中有没有这个kay.返回bool.
bool a=h.ContainsValue(objectvalue);//与上述类似
h.Remove(object kay);//移除该kay,也相当于该value值也没有了。
foreach (var item in ht.Keys)//遍历显示出集合的kay值
{
Console.WriteLine(item);//var需要根据类型修改
}
foreach (object item inht.Values)//遍历显示出集合的value值
{
Console.WriteLine(item);
}
foreach (DictionaryEntryitem in ht)//var改为类型字典类型
{
Console.WriteLine(item.Key+item.Value);//遍历显示所有值。
}
9.字符串(string)可以通过索引访问字符串里面的东西
10.字典的制作方法之一(键值对的存储方法)
string str = "1壹 2贰3叁 4肆 5伍 6陆 7柒 8捌 9玖 0零";
string[]strs=str.Split(newchar[]{ ' '},StringSplitOptions.RemoveEmptyEntries);
Dictionary dic = new Dictionary();//定义一个字典(集合)
for (int i = 0; i < strs.Length; i++)
{
dic.Add(strs[i][0], strs[i][1]);//循环加入
}
第六天
在winform中读取文件,可以将其放在文本框程序里面。
1.若遍历时显示的为命名空间,则改用foreach循环,将item.。。分别显示即可。
2. string[] txts = lins[i].Split(new char[]{ '=' }, StringSplitOptions.RemoveEmptyEntries);
if(!dic.ContainsKey(txts[0][0]))
{
dic.Add(txts[0][0], txts[1][0]);
}
3制作字典时。 string chanese = "";
for (int j = 1; j
{
if(!chanese.Contains(lins[j]))
{
chanese += lins[j];
}
}
if (!dic.ContainsKey(lins[0]))
{
dic.Add(lins[0],chanese);//以上步骤可以将相同单词的不同意思,连在一起。
}
else
{
if(!dic.ContainsValue(chanese))
{
dic[lins[0]] +=chanese;//这步可以将不同行相同单词的不同意思连在一起
}
}
4.装箱拆箱详细补充
1. 找IL中间代码的box和unbox字眼,其中的IL代码中的ConCat方法为重要参考
2.若想装箱必须有间接或直接继承关系
3.拆箱应与装箱时的类型相同
4. intnum = 10;
object a = num;//装箱
int num1 = (int)a;//拆箱
double num2 = (double)a;//拆箱失败,因为装进去前与拆箱后的类型不一致。
string n = num.ToString();//不为装箱(类似)
Console.WriteLine(num);//未发生装箱,因为调用的为形参为int类型的方法
Console.WriteLine(num+"haha");//发生了装箱,因为先调用了一个东西
objecto = 10;//装箱
5. intn = 10;
object o = n;
n = 100;//不为拆箱,为重新复制而已
5.自定义泛型
1.泛型十分灵活,有多种形式。可以为泛型字段,泛型方法。泛型类等。。
2.<>里面的叫做类型参数
2.可以减少拆箱装箱的次数,因为用集合时,传进的参数都要转化为object类型,拿出时要拆箱效率低。
3.可以代码重用
4.用法如下:
class Program
{
static void Main(string[] args)
{
MyList m = new MyList();
//将T定义为int类型,调用别的时,T应保持一致
m.Asy2(12);//保持一致
m.Say("e");//将Y定义为了string类型
}
}
public class MyList
{
T a;//泛型属性,T定义的为什么类型,a就为什么类型
public void Say(Y a )//泛型方法
{//Y为什么类型()内就要填什么类型
//也可以像正常方法调用
Console.WriteLine("haha");
}
public T Say1()
{ return //需要返回一个T类型的值; }
public void Asy2(T m)
{ }//参数类型应与实例化时T所赋予的类型一致
public void Say3(T a)
{ }//Y写方法时自己定义,T应与上方保持一致
}
5 补充 public class MyL
{//<>内可以存放多个类型参数
public void Add(Y a,K b)
{}//方法也可以
}
6.自定义泛型的约束
1. 其中一个定义如下:
public class My where T :struct
{
}
2.所有类型
public class Person
where T1 : struct //约束T1必须是值类型
where T : class, new()//约束T必须是引用类型
where TC : new() //这个类型必须带有一个无参数的构造函数【要求:1.构造函数不能为私有,2.类型不能是抽象的。】
where TK : Car //这里约束了TK类型,必须是Car类型或者是Car类型的子类
where TV : IComparable //约束类TV必须是实现IComparable接口的类型。
whereTU : T //约束了TU必须是T的子类。或者是T类型。
3.补充
多个约束时: public class My whereT :struct where K :class
只要中间空一格就可以。(也可以折行,类似于2)
7.集合中对象的排序方法:
static void Main(string[] args)
{
List list = new List();
。。。。。。。。。。。。。。。
list.Add(p1);
list.Add(p2);
list.Sort();//对集合中的对象排序
foreach (var item in list)
{
Console.WriteLine(item.Name);//用foreach遍历,输出名字
}
Console.ReadKey();
}
publicclass Person:IComparable//若想实现该排序,该对象所对应的类必须实现该接口
{
。。。。。。。。。。。。。
public int CompareTo(object obj)
{
return ((Person)obj).Age - this.Age;//该方法返回值为int,该方式为从小到大排,反过来就为从大道到排列
}
}
8.泛型集合比较器(接上述7的排序)7和8有一个就可以
1.list.Sort();方法有多个重载,其中一个可以在括号里添加一个比较器。
2.需要定义一个类实现一个泛型接口IComparer<>//<>内放所需比较对象的类名。
3.定义与实际操作如下: MySortms = new MySort();
list.Sort(ms);
。。。。。。。
public class MySort : IComparer //IComparer
{
public intCompare(Person x, Person y)
{
returnx.Age - y.Age;//返回和Icomparable接口的方法一样。
}
}
9.Path类常用方法(操作(目录)字符串的类)
1.该类为静态类,不能实例化。
(以下方法用的时候再看即可,VS里面都有提示)
2. string path=@"D:\ProgramFiles\Maticsoft\Codematic2\TextStyle\ASPX.xshd";
//把这个路径下的文件的后缀名改变,这个路径的文件名不会真的改变
//因为Path这个类是针对字符串进行操作的------我可以做假文件
string str= Path.ChangeExtension(path, ".jpg");//(文件路径,想修改成的后缀)
Console.WriteLine(str);
Console.ReadKey();
3. string str=Path.Combine(string path1,string path2)
将两个路径合成一个路径,比用+好,可以方便解决不加斜线的问题,自动处理路径分隔符的问题
4.string str=Path.GetDirectoryName(@"D:\ProgramFiles\Maticsoft\ASPX.xshd");
获取这个文件的路径,文件名除外
5. string st= Path.GetExtension(path);
//获取文件的后缀名
6. string str=Fath.GetFileName(string path)
得到文件路径的文件名部分
7. 只获取文件名
//string st = Path.GetFileNameWithoutExtension(path);
8. 获取这个文件的绝对路径
// string st = Path.GetFullPath(path);
9. 获取电脑临时目录,还有临时文件的绝对路径
string st = Path.GetTempPath();
10.Directory类常用方法:(操作目录的类)
1.需要头文件IO;(几乎所有的对文件的操作的类都需要IO)
2.其中全为静态方法,通过类名调用。
3.和Path结合最好
4.应注意其中所有方法的重载。
5.可以通过指定路径创建一个文件。删除指定路径的文件。判断文件夹是否存在。得到指定路径文件夹里面的文件夹的名称包括其路径,返回值为字符串数组。搜索文件夹
6.具体操作如下:
Directory.CreateDirectory("1");//创建了文件
Directory.Delete("1");//删除目录--如果目录不存在,则报异常,先判断是否存在
// 获得这个目录下的所有的子目录
string[] dires = Directory.GetDirectories(@"E:\20131115讲课视频");
string path = @"C:\Users\xy\Desktop\1115作业\第二天";
// 搜索文件夹
//在这个路径下搜索所有的“”内的文件夹
string[] dires = Directory.GetDirectories(path, "1||2");//正则表达式的时候看看
// 这个目录下的所有文件--全路径
//在这个路径下搜索所有的rar文件
string[] dires = Directory.GetFiles(path, "*.rar");
for (int i = 0; i < dires.Length; i++)
{ Console.WriteLine(dires[i]); }
//获得该路径的父目录,包括绝对和相对路径
DirectoryInfo newstr = Directory.GetParent(path);
Console.WriteLine(newstr);
11.相对路径和绝对路径
1.相对路径为可以改变的路径。
2.绝对路径为不可改变的路径。
12.获取当前程序集所在目录的方法(路径为相对路径)(常用)
string str=Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location);
(该方法为获取该文件的绝对路径)
string str1 = Path.Combine(str, "a.exe//所需加的文件名称");
Console.WriteLine(str1);
(Assembly.GetExecutingAssembly().Location为获取当前程序集所在目录)
13.yield关键字
1. yield(yield含义:生产, 出产, 带来)
yield return 表达式
yield break;
当yield语句所在的方法的返回值为IEnumerable时,表示自动生成一个可迭代类型
当yield语句所在的方法的返回值为IEnumertor时,表示自动生成一个迭代器(枚举器)
2.可简化foreach遍历对象时的代码://(返回值可以不是泛型)
public IEnumerator GetEnumerator()//第一种方法,遍历时最好用第一个方法。
{
for (int i = 0; i < _name.Length; i++)
{ yield return _name[i]; }
}
public IEnumerable Enumerable1() //第二种方法
{
for (int i = 0; i <_name.Length; i++)
{ yield return _name[i];}
}
14.文件操作类:File小文件内部操作(大文件用流),Directory对目录操作,Path对路径字符串操作
第七天
1.资源管理器winform控件与属性的使用简介
1.TreeView控件,可以添加节点和子节点。
2.窗体属性中在上方有一个为AcceptButton的属性,选中其中一个按钮控件名称后,单击回车键就相当于点了该按钮控件。
3.每个控件中都有许多的属性和方法,属性可以更改,方法可以编码,双击进入即可,编写运用这个方法想要发生的事情。
4.Tag属性(需要调用)想一个口袋,想装什么就装什么。
2.资源管理器
publicpartial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string path = @"D:\学习视频(重要)\1115.NET(郑承良学长)\第一阶段";
LoadDictionary(path, tvRoot.Nodes);//要养成使用方法的习惯
}
public void LoadDictionary(string path, TreeNodeCollection nodes)
{
string[] str = Directory.GetDirectories(path);//子目录的全路径
foreach (string item in str)
{
TreeNode tn = nodes.Add(Path.GetFileName(item));
LoadDictionary(item, tn.Nodes);//递归
}
string[] file = Directory.GetFiles(path,"*.txt");//只读取txt文件
foreach (string item in file)
{
TreeNode tn1 = nodes.Add(Path.GetFileName(item));//tn1里面存的是节点
// MessageBox.Show(item);//为跳出一个文本框显示提示信息
tn1.Tag = item;//将路径存在每个节点的Tag里面
}
}
private void tvRoot_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgse)
{
//判断是否选定了节点
if (tvRoot.SelectedNode.Tag != null)
{
string files =tvRoot.SelectedNode.Tag.ToString();//object类型需要转换
textBox1.Text = File.ReadAllText(files);//整体读取文件
}
}
}
3.File类的使用(对文件的操作和读写方法)
1.常用方法
File.Create("1.txt");//创建文件的,如果这个路径下有这个文件,则覆盖了 File.Delete("1.txt");//删除指定路径下的文件,如果该文件不存在也不发生异常
bool result = File.Exists("1.txt");//判断该路径下是否存在这个文件,返回bool
string path = @"E:\20131115讲课视频\07-20131124C#基础加强\代码\2\fa.txt";
//路径必须有文件名
File.Copy("1.txt", path, true);//如果目标路径中已经存在了要复制的文件则报异常.
// Copy方法有三个重载,如果用三个参数,则会把目标文件覆盖了
File.Move("1.txt", path);//剪切,剪切后可以改成路径的文件名
2.其他方法(读写)
//把整个文本文件的内容看成是一个字符串
string str = File.ReadAllText("1.txt", Encoding.Default);
// 把文件文件的内容一行一行的读取出来
string[] str = File.ReadAllLines("1.txt", Encoding.Default);
// 把字符串的内容写入到这个文件中,以单个的字符串来写入
File.WriteAllText("1.txt", "嘎嘎");
File.WriteAllText("1.txt", "以第二个重载来写入", Encoding.UTF8);//最后一个参数为以什么编码写入
byte[] bytes = File.ReadAllBytes("1.txt");//读取这个文件的字节
File.AppendAllText("1.txt", "哈哈哈");//把字符串追加到目标文件中.不是覆盖
File.WriteAllBytes("2.txt", bytes);//以字节的方式进行写入,若无文件则会建立
4.把字符串变为字节数组:byte[]b=System.Text.Encoding.UTF8.GetBytes("haha");反之亦然
5.FileStream流类(大文件的读取与写入)
1.Stream类为所有流的父类,为一个抽象类。
2.把文件变成流的形式进行传输;
2. FileStream的Position属性为当前文件指针位置,每写一次就要移动一下Position以备下次写到后面的位置。Write用于向当前位置写入若干字节,Read用户读取若干字节。
3.以流对文件操作,需要关闭文件或清楚缓存。using自动调用Dispose方法。
使用 using()//括号内写对文件操作的初始步骤。using就可以自动对文件的关闭进行操作
{//对文件的操作
} //要想使用using该类(类似Person)必须实现Idisposable接口才可以
4.以字节,流的方式把内容写入到了文件中
using (FileStream fs = new FileStream("1.txt",FileMode.Create, FileAccess.Write))
{//文件名 //创建文件 //文件的访问权限设置
string str = "我的天";
//如何把字符串转换成字节...
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(str);
fs.Write(bytes, 0, bytes.Length);//第二个参数为偏移量平常都写0
}
5.以字节,流的方式读文件 //FileStream的第六个重载
using (FileStream fs = new FileStream("1.txt", FileMode.Open, FileAccess.Read))
{//打开文件
byte[] bytes = new byte[fs.Length];//根据fs.Length获取流的长度,看下方介绍
fs.Read(bytes, 0, bytes.Length);//将读的内容放到字节数组里
string s = System.Text.Encoding.UTF8.GetString(bytes);//将字节数组转化为字符串
Console.WriteLine(s);
Console.ReadKey();
}
(对于byte[] bytes = new byte[],中括号内写每次读多少字节,1024*1024为1M)
6.File和FileStream类的区别
1.File对大文件不可,它是将内容直接放入内存中。
2.FileStream是通过字节有过程的将内容读取与写入。
3.大文件用FileStream,小文件用File
7.读取文件时乱码的原因(编码)
1.(只有文本文件才会乱码)
2.文本文件存储时采用的编码,与读取时采用的编码不一致,就会造成乱码问题。
3.解决:1.检查要读取的文件的编码2.读取文件时,采用对应的编码
4.码表(不要求掌握)
ASCII:英文码表,每个字符占1个字节。(正数)
GB2312:兼容ASCII,包含中文。每个英文占一个字节(正数),中文占两个字节(负数)
GBK:简体中文,兼容gb2312,包含更多汉字。英文占1个字节(正数),中文占两个(1个负数,1个可正可负)GB18030
Big5:繁体中文
Unicode:国际码表,中文英文都站2个字节。
UTF-8:国际码表,英文占1个字节,中文占3个字节。
5.若想通过编码头进行判断文件的编码,只能判断出是否为UTF-8编码,因为该编码不管内容一不一样,他的通过byte[]b= File.ReadAllBytes("1.txt");得到的数组前三项为239,187,191
8.大文件移动(可以做成窗体程序)
static void Main(string[] args)
{
using (FileStream fsRead = new FileStream(@"D:\学习视频(重要)\1115.NET(郑承良学长)\红蜘蛛.rar",FileMode.Open, FileAccess.Read))//将读写嵌套起来
{
using (FileStream fsWrite = newFileStream(@"D:\学习视频(重要)\1115.NET(郑承良学长)\笔记\1.rar", FileMode.Create, FileAccess.Write))
{
byte[] bytes = new byte[1024* 1024 * 5];//每次读5M
int count =fsRead.Read(bytes, 0, bytes.Length);//count存所读的字节
while (count>0)
{
fsWrite.Write(bytes, 0,bytes.Length);
count =fsRead.Read(bytes, 0, bytes.Length);//再接着读5M
Console.Write("*");//显示进程
}
}
}
Console.WriteLine("文件移动完毕!");//最后的提示(最好放在这)
Console.ReadKey();
}
9.文件的加密与解密(在文件移动的基础上)
在上述代码中的一段:实质是在复制文件时根据一个算法改变文件的字节,解密时根据算法将原本的字节重新改变过来。例如下方的代码的算法,加密和解密用一个程序就可以了。
while (count>0)
{
for (int i = 0; i
{
bytes[i] = (byte)(255- bytes[i]);
}
fsWrite.Write(bytes, 0,bytes.Length);
count =fsRead.Read(bytes, 0, bytes.Length);//再接着读5M
Console.Write("*");//显示进程
}
10.文件读写的另一种方式StreamReader和StreamWriter(父类不为Stream)
1.也使用using进行操作,和FileStream流差不多
2.也是进行流操作。
2.使用此方法可以避免乱码(一行一行的字节读取),比如使用Fs的话,可能将一个汉字读成两部分造成乱码(因为一个汉字占两个字节)
3.读文件的方式
using (StreamReader s1 = new StreamReader("1.txt", Encoding.Default))//具有多个重载
{
//第一种读取方式,建议使用
while (!s1.EndOfStream)//为一个属性
{
string st = s1.ReadLine();
Console.WriteLine(st);
}
//第二种方式
string s = s1.ReadToEnd();
Console.WriteLine(s);
}
//第三种方式
string line = null;
while((line=sr.ReadLine())!=null)
{
Console.WriteLine(line);
}
}
4.写文件的方式
using (StreamWriter s = new StreamWriter("1.txt"))
{
s.Write("你好哈");//具有多个重载
}
第八天
1.一个拼接东西的小方法:stringa = string.Format("{0}|{1}", s[0], int.Parse(s[1])*2);
2.压缩流类 GzipStream
对于压缩是将相同的地方压缩,并且运用算法进行压缩
3.对象序列化与反序列化
1.序列化的原因:将一个复杂的对象转换流,方便我们的存储与信息交换
2.要序列化的类型必须标记为:[Serializable]
若序列化为一个子类对象,该对象的父类和子类都必须标记为: [Serializable]
若该类型引用了什么成员,该类型中的所有成员的类型也必须标记为:[Serializable]
序列化只会对类中的字段序列化。(只能序列化一些状态信息。)
几乎所有的系统定义的类型都已经添加了序列化的标志词。
3. 不建议使用自动属性:自动属性为 string Gender//这即为属性又为字段
因为若使用反序列化的时候会出错{
get;
set;
}
3.序列化的过程:
static void Main(string[] args)
{
//1.定义一个序列化器
BinaryFormatter fs = new BinaryFormatter();
//2.定义一个对象
Person p = new Person();
p.Name = "李阳";
p.Age = 18;
//3.定义一个流StreamWriter不可以,父类不为Stream
using (FileStream s = new FileStream("1.txt", FileMode.Create,FileAccess.Write))//写
{ //4.进行序列化
fs.Serialize(s, p);//调用该方法序列化,无返回值
}
}
}
[Serializable]//该标识符必须添加
public class Person{}//为一个类
4.反序列化
static void Main(string[] args)
{
//定义一个序列化器
BinaryFormatter fs = new BinaryFormatter();
//定义一个对象
Person p = new Person();
//定义一个流
using (FileStream s = new FileStream("1.txt", FileMode.Open, FileAccess.Read))//读
{ //进行反序列化
object obj = fs.Deserialize(s);//调用该方法反序列化,返回值为object类型
p = (Person)obj;//强制转换
}
Console.WriteLine(p.Name);
Console.ReadKey();
}
[Serializable]////////
public class Person{}//
**4.正则表达式 (所需类Regex,需要手动写入一个命名空间)(foreach循环)
0.匹配的含义(一个一个往后找,匹配完一组后进行后续操作后,再找看还有没有匹配的组,如果有继续替换,直到找不到匹配项为止);
1.元字符. 代表除\n以外的所有中的一个字符,例如:正则表达式“b.g”能匹配如下字符串:“big”、“bug”、“b g”,但是不匹配“buug”,“b..g”可以匹配“buug”。
2.元字符[] 匹配括号中的任何一个字符(集合,字符集合),例如正则表达式“b[aui]g”匹配bug、big和bag,但是不匹配beg、baug
使用连字符“-”来指定字符的区间来简化表示,例如正则表达式[0-9]可以匹配任何数字字符,这样正则表达式“a[0-9]c”等价于“a[0123456789]c”就可以匹配“a0c”、“a1c”、“a2c”等字符串;
可以制定多个区间,例如“[A-Za-z]”可以匹配任何大小写字母,“[A-Za-z0-9]”可以匹配任何的大小写字母或者数字。
元字符.在[]内表示为单一的一个.,不代表任何。
若想使用”-“,则将其放在[]的最后。
3.元字符| 将两个匹配条件进行逻辑“或”运算。例如:‘z|food’ 能匹配 “z” 或 “food”或者zood(一种类型)(因为这其中包括z)。‘(z|f)ood’ 则匹配 “zood” 或 “food”。其优先级最低。
4.元字符() 改变优先级,定义提取组。
将 () 之间括起来的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域,这个元字符在字符串提取的时候非常有用。把一些字符表示为一个整体 。
5.元字符* 匹配 0-多个 在它之前的第一个表达式,和通用符*没有关系。
等价于{0,}
例如正则表达式“zo*”(等同于z(o)*)能匹配“z” 、“zo”以及 “zoo”;因此“.*”意味着能够匹配任意字符串。"z(b|zb、zbc、zcb、zccc、zbbbccc。"z(ab)*"能匹配z、zab、zabab(用括号改变优先级)。
6.元字符+ 匹配前面的子表达式一次或多次,和*对比(0到多次)。等价于{1,}
例如正则表达式9+匹配9、99、999等。 “zo+”能匹配“zo”以及 “zoo” ,不能匹配"z"。
7.元字符? 匹配前面的子表达式零次或一次 ,等价于:{0,1}(也可表示可有可无的意思)
例如,“do(es)?” 可以匹配 “do”或 “does” 。【colou?r、favou?r】一般用来匹配“可选部分”。(终止贪婪模式)注意唯一的三元表达式的作用
8.元字符{} {n} :匹配确定的 n 次。“zo{2}”→zoo。例如,“e{2}”不能匹配“bed”中的“e”,但是能匹配“seed”中的两个“e”。
{n,} :至少匹配n次。例如,“e{2,}”不能匹配“bed”中的“e”,但能匹配 “seeeeeeeed”中的所有“e”
9.元字符^ 表示必须以其后面的内容开始才匹配。 匹配一行的开始。例如正则表达式“^regex”能够匹配字符串“regex我会用”的开始,但是不能匹配“我会用regex”。 ^abc,匹配一个正则表达式的开始abcjflkdsjfkdsjf。
取非,[^0-9]表示不能是0-9内的数字
10.元字符$ 表示正则表达式必须以其前面的内容结尾才匹配,匹配行结束符。例如正则表达式“浮云$” 能够匹配字符串“一切都是浮云”的末尾,但是不能匹配字符串“浮云呀”
11.\组成的字符 \d[0-9] 一样的 \d数字 \d{3}--------234
\D[^0-9] ---非数字 \D{3} ------qrw \d\D---所有的字符
\s----空白符 ,即一些看不到的符号,空格,回车。。。
\S 非空白符 \s\S---所有的字符
\w 表示的是除了特殊符号以外的任意一个字符,数字,字母,下划线。。。
\W 特殊符号组合Shift键的为特殊符号,加号也是。 \w\W---所有的字符 例如\w 帅也可以
\b 代表单词的边界,hoole you一个单词的最后一个字母后面不再是字母,则为边界 ,其在C#里面代表退格符,所以要小心。。。。
12. \*、\+、\.、\[、\-、\{2,3}、\\d... 加上\转义符之后就表示通用符了,没有了其自身的特变含义。 对于*.+类的元字符,若想使用其本身,1.\\*或@“\*”
对于\d等的来说,则需使用@“\\d”才可。
对于\本身来说,若想用\本身,则@“\\”或“\\\\”,因C#和表达式两层才可
13.注意事项:匹配的意思是若无开头和结尾的要求,那么需要检索的字符串中有一部分并且一群字母之间没有元字符则表示一个整体
^good$这种类型的只能是good才可以goodgood也不可以,这为完全匹配
14.正则表达式所需调用的常用方法
判断是否匹配:Regex.IsMatch(“字符串”,”正则表达式”);可用类调用,也可实例化调用
字符串提取:Regex.Match(“字符串”,“要提取的字符串的正则表达式”);//只能提取一个(提取一次)
字符串提取(循环提取所有):Regex.Matches(),(可以提取所有匹配的字符串。)
字符串替换:Regex.Replace(“字符串”,”正则”,”替换内容” 输出为一个与输入字符串基本相同的新字符串,唯一的差别在于,其中的每个匹配字符串已被替换字符串代替(一个一个往后找,匹配完一组后,再找看还有没有匹配的组,如果有继续替换)
(替换的方法) 1.str= Regex.Replace(str,"a+", "");替换为空字符串,为删除a.也相当于将a其余的东西提取出来。相当于string.Spilt();
(方法内部用组) Replace(str,"(.+)=(.+)", "$1是$2");前面()分组后,后面想用第几组就$几,
14.反向引用(正则表达式内部用组)
在正则表达式替换时,通过$1、$2、...来引用分组信息,而在正则表达式中,引用分组信息通过\1、\2、...这种引用方式就是“反向引用”。“
引用分组信息”,其实就是将分组匹配到的信息保存起来,供后续使用。
输出为一个与输入字符串基本相同的新字符串,唯一的差别在于,其中的每个匹配字符串已被替换字符串代替。
代码:一需要该模式的字符串,重叠,,就要想到反向引用
string str = "啊啊啊洋洋洋";
string newStr= Regex.Replace(str, @"(.)\1+", "$1");//可进行配合
15.正则表达式实际运用之对字符串操作(对字符串操作)
1. 提取组
正则表达式中用()将要提取的内容括起来,然后就可以通过Match的Groups属性来得到所有的提取元素,注意Groups的序号是从1开始的,0为提取的整体。
代码 static void Main(string[] args)
{
string str = "我的邮箱是yhbe@itcast.cn和yhb@126.com";
MatchCollection m=Regex.Matches(str, @"([0-9a-zA-Z_.-]+)(@[a-zA-Z0-9]+(\.[a-z]+))");
foreach (Match item in m)//调用Matches方法抽取所有的匹配项
{//var要变为Match
if (item.Success)//运用属性判断是否抽取
{
Console.WriteLine(item.Groups[0].Value+"===="+item.Groups[1].Value+ "===="+ item.Groups[2].Value+ "==="+item.Groups[3].Value) ;
}
}
Console.ReadKey();
}
2. 字符串提取之多行模式
释义:多行模式为你操作的文件或者什么东西的内容为很多行的,用ReadText的时候,系统会将其变为一行,并在每行的间隔的地放添加\d\r来分隔。所以要对对行操作时,要注意\d\r字符。
$匹配必须出现在字符串或行的末尾,或出现在字符串或行末尾的 \n 之前。$ 定位标记指定前面的模式必须出现在输入字符串的结尾或输入字符串的结尾处的 \n 之前。
如果将 $ 与RegexOptions.Multiline 选项一起使用,则匹配也会出现在一行的末尾。 请注意 $ 匹配 \n,但不匹配 \r\n(回车换行组合,或 CR/LF)。 若要匹配 CR/LF 字符组合,请在正则表达式模式中包含 \r?$。
所需的一个属性:Regex.Matches(str, "([A-Za-z]+\r?)$",RegexOptions.Multiline);
例如:“([A-Za-z]+\r?)$“该正则表达式为提取每行的最后一个单词。^单个可以提取每行第一个东西。
2.找出数字的正则表达式为@"\d+";阻止贪婪模式的技巧
16.贪婪模式+和*
1.+、*的匹配默认是贪婪(greedy)的:尽可能多的匹配,直到“再贪婪一点儿”其后的匹配模式就没法匹配为止。
2. 在+、*后(紧接着的后面)添加?就变成非贪婪模式(? 的另外一个用途):让其后的匹配模式尽早的匹配
3. 一般开发的时候不用刻意去修饰为非贪婪模式,只有遇到bug的时候发现是贪婪模式的问题再去解决。如果匹配的结果比自己预想的要多,那么一般都是贪婪模式的原因。
16.小应用(提取网址中的所有邮箱)
需:命名空间using System.Net;
using System.Text.RegularExpressions;
static void Main(string[] args)
{
WebClient wc = new WebClient();
string str = wc.DownloadString("http://localhost:8080/留下你的Email.htm");
MatchCollection m = Regex.Matches(str, @"[a-zA-Z0-9_.-]+@[a-zA-Z0-9]+(\.[a-zA-Z]+){1,2}"); //记住
foreach (Match item in m)
{
if (item.Success)
{
Console.WriteLine(item.Value);
}
}
Console.WriteLine(m.Count);
Console.ReadKey()
第九天
内容以整合到第八天内知识点
第十天
一.正则表达式之环视(了解就可)
1.包括的形式
(?=):肯定顺序环视,向右:(?=\d)向右必须为数字
(?!):否定顺序环视,向右:(?!\d)向右必须不为数字//\d都要在该标识符的右边
(?<=): 肯定逆序环视,向左:(?<=\d)向左必须为数字//\d都要在该标识符的右边
(?
2.环视的括号不算组。
二.UBB翻译(字符串替换案例)
原因:为了防止用户用恶意代码留言,大部分论坛都不允许使用HTML语句做为回帖内容(或者进行了转义),但是这限制了用户的发挥,比如用户无法粘贴超链接、无法粘贴图片地址,无法把自己发送的文字进行加粗,改变字号。为了解决这个问题,人们设计出了UBB代码,它提供了有限的、无危害的功能,用户只要遵循代码规则就可以实现用户想要的功能
百度网替换为百度网
//灰色部分为一个百度网的超链接。//蓝色为UBB需要翻译的东西将其翻译为灰色部分。
三.敏感词汇的判定感想
将敏感的词汇经过剪切和一些步骤将其拼接为一个正则表达式(通过方法和“+”),最后将输入的信息与该正则表达式匹配即可。
对于敏感词汇表,可以适当添加一些正则表达式的字符,来扩大敏感词的范围,达到更好的效果。
四.闲话
五大浏览器:谷歌,IE(垃圾),火狐,W3Cfuns(编译软件),空中,苹果。
***五.委托(delegate)(代码重用和千里之外夺人贞操)(本质类)(不能重载)
1.定义:委托是一种数据类型,像类一样(可以声明委托类型变量)。委托具有类似于string一样的不可变性
1.本质:其实就是一个类把方法包装了一下,委托都继承自System.MulticastDelegate,而System.MulticastDelegate又继承自System.Delegate
2.作用,使方法可以作为参数进行传递 就是委托。想做但不知道做什么
2以后用委托变量的时候,一定要先判断是否为NULL,if语句不能少。
并且以后用委托时,不需要定义了,用系统的委托Action和Func,因为委托占资源。
3.系统的委托介绍
Action a = M;//有多个参数,但无返回值。
a(100, 'h');
Func f = M2;//当<>内为一个参数时,仅有返回值
int ff = f();
Func f = M3;//<>内有多个参数时,最后一个为返回值类型,其余的为参数类型
intff = f(100);
3.委托的定义(有参无参,有无返回值)要根据所要操作的方法来定义的。无函数主体。
4.代码:public delegatevoid MyDelegate();//类外定义委托,
class Program
{
static void Main(string[] args)
{
Do(Say);//静态方法直接方法名调用
}
public static void Say()//委托所要操作的方法,所被委托根据的方法
{ Console.WriteLine( "大家好哈");}
public static void Do(MyDelegate hhh)//委托作为类型,方法作为参数传递
{ hhh();//直接加括号调用
Console.WriteLine("哈哈哈");
}}
5.夺人贞操于千里之外:理解后委托就好了。
6.委托在方法中调用时,其实内部是调用了InVoke方法。
7. MyDelegate md = DoSth;//可以把方法名字直接赋值给这个委托变量
8. MyDelegate md=new MyDelegate(DpSth);//也可以直接new,并给他方法
9.多播委托
1. 组合的委托必须是同一个类型
相当于创建了一个按照组合的顺序依次调用的新委托对象。
委托的组合一般是给事件用的,用普通的委托的时候很少用
2. ResultDelegate M1 = T1;
M1 += T2;
M1 += T3;//这是将方法存进去,并不调用该方法。
M1 += T4;
M1 -= T2;
int r = M1();//运行到这里的时候,是将每一个方法都调用一遍
Console.WriteLine(r);//方法的可加减即为委托。
3.
Delegate[] des = M1.GetInvocationList();//得到所有的方法,存到一个Delegate类类型的数组里面。
foreach (Delegate item in des)//进行遍历即可
{
ResultDelegate res = (ResultDelegate)item;//需要进行强制转化
Console.WriteLine(res());
}
10.匿名方法
1.只用一次的方法,无方法名,有主体,要加分号。
2.代码public delegate string MyDelegate(int a);//先定义一个委托
MyDelegate mdl = delegate (int b) //根据委托定义匿名方法----有参数
{
return “hua”;//有string类型的返回值
};
mdl();//通过委托调用
11.lambda表达式(就相当于一个方法)
1.根据委托来写的,返回值与参数
2.代表性字符=>,其后跟表达式(intnum1, int num2) => num1 - num2该部分相当于一个方法
3.代码
public delegate int MyAdd(int num1,int num2);//先定义委托
static void Main(string[] args)
{
MyAdd mas = (int num1, int num2) => num1 - num2;//lambda表达式
int sum= Add(10, 20,mas);
Console.WriteLine(sum);
Console.ReadKey();
}
public static int Add(int number1,int number2,MyAdd ma)
{
return ma(number1, number2);
}
4.另一种案例
List list = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9};
IEnumerable e= list.Where(x => x > 5);//灰色部分相当于函数
foreach (int item in e)
{
Console.WriteLine(item);
}
六.加号“+”的用法
加号可以将一些东西接起来,字符串相加等。
以后实验后再补充。
七.显示当前时间和日期的代码
System.DateTime.Now可以直接输出,为DateTime类型,ToString后可以看为一个字符串。
八.窗体传值
1.窗体的构造函数可以重载,一定要继承)public Form2(string s,MyDelegatemdl):this()
2.关闭本窗体的函数this.Close();对本窗体的操纵都用this.
3.委托的重要性,可以通过定义方法进行跨东西传值。
4.窗体可以在另一个窗体实例化Form2 form2 = new Form2(str,Show);相当于类。
第十一天
***一.事件(通过委托实现的,委托才是事件能正常执行的核心内容)
1.委托可以+,+=,-=,也可以直接调用。而事件只可以+=,-=两种,不可以直接调用。
2.事件的关键词event在定义,在定义委托变量的时候,在访问限制符和委托名之间
3.本质:event会自动生成一个private delegate变量和两个函数: add和remove,C#编译器用这两个方法支持+=和-=操作符。
4.代码:public delegatevoid MyDelegate(object sender, MyEventArgs e);//第一步
public event MyDelegate _mdl;//_mdl便为一个事件//第二部
_mdl(this, mea);//第三部的使用
5.委托和事件的区别
委托和事件没有可比性,因为委托是数据类型,事件是对象(可以理解为对委托变量的封装。)
因为对于事件来讲,外部只能“注册自己+=、注销自己-=”,外界不可以注销其他的注册者,外界不可以主动触发事件,因此如果用Delegate就没法进行上面的控制,因此诞生了事件这种语法
事件是用来阉割委托实例的。事件只能add、remove自己,不能赋值。事件只能+=、-=,不能=、不能外部触发事件。
事件的作用与委托变量一样,只是功能上比委托变量有更多的限制
二.程序集(不为程序,要打包之后才为)
1.含义:程序集是.net中的概念。.net中的dll与exe文件都是程序集。程序集(Assembly),可以看做是一堆相关类打一个包,相当于java中的jar包(*)。
2. 类型元数据(描述在代码中定义的每一类型和成员,二进制形式)
程序集元数据(程序集清单、版本号、名称等)
IL代码(这些都被装在exe或dll中)
资源文件。
每个程序集都有自己的名称、版本等信息。这些信息可以通过AssemblyInfo.cs文件来自己定义。
三.反射(需要添加命名空间using System.Reflection)
1. 反射无处不在,我们天天在使用。Vs的智能提示,就是通过反射获取到类的属性、方法等。还有反编译工具也是通过反射实现
2. 反射就是动态获取程序集的元数据(提供程序集的类型信息)的功能。
3. 就是动态获取程序集中的元数据来操作类型的
4. 反射就是直接通过.dll来创建对象,调用成员。
四,type类.(需要添加命名空间using System.Reflection)(invoke为调用的意思)
1. Type类实现反射的一个重要的类,
2.通过它我们可以获取类中的所有信息包括方法、属性等。可以动态调用类的属性、方法3.Type是对类的描述。
3.插件:拓展主程序功能的dll文件
4.其中的方法:
Personper = new Person();
Type t = per.GetType();
MethodInfo[] me = t.GetMethods();//返回所有的方法
MemberInfo[] p = t.GetMembers();//返回所有公共的成员
EventInfo[] p = t.GetEvents();//返回所有的事件
Type type=ass.GetType("MyClass.Person");//根据这个命名空间下的类名获得这个类的类型
5.ps:添加类库,在解决方案里面添加,就像新建一个项目一样
6.通过Assembly类进行读取类库的内容并对提取的内容进行操作
Assemblyass= Assembly.LoadFile(path);//path为读取dell文件的路径//加灰的 部分为获取改路径下的文件
Type[]types= ass.GetExportedTypes();//获得公共类型的类
7.动态创建对象
1. Activator.CreateInstance(Type t)会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果类没有无参构造函数就会报错。
2.动态建立对象的过程
Assembly ass= Assembly.LoadFile(path);//根据这个程序集的类获得path路径下的文件,才可以进行下一步操作。
Type type=ass.GetType("MyClass.Person");//根据这个命名空间下的类名获得这个类的类型//可以将“”替换为变量//第一步
object dd= Activator.CreateInstance(type);//genjv这个Type对象创建type类的对象//dd中存着Person这个类的对象。//第二步
8.Type类的方法:在编写调用插件的程序时,需要做一系列验证。
1. IsAssignableFrom(type c);方法
Assembly ass = Assembly.LoadFile(path);
Type typDog = ass.GetType("MyClass.Dog");
Type typAnimal = ass.GetType("MyClass.Animal");因为Dog类继承Animal类
bool result = typDog.IsAssignableFrom(typAnimal);//返回值为错误
//(直译:是否可以将c赋值给.前面的东西)判断当前的类型的变量是不是可以接受c类型变量的赋值。即括号里的东西是否为.前面类型的子类,或者接口。。。同等级的也为错,自身判断自身可以
2. IsInstanceOfType(object a);方法
Type typChinese = ass.GetType("MyClass.Chinese");
object objPerson = Activator.CreateInstance(typPerson);//根据该type创建该类型的对象 //因为typChinese不能实例化出objPerson对象
bool result= typChinese.IsInstanceOfType(objPerson);//返回值为错误
//判断对象a是否是当前类的实例(当前类可以是o的类、父类、接口)
3. .IsSubclassOf(type a);方法
。。。。。。//接上述代码
boolresult = typChinese.IsSubclassOf(typPerson);
//判断当前类是否是c的子类。类的事,没有接口的事。
4. IsAbstract属性
。。。。。。
Type typFly = ass.GetType("MyClass.IFly");
bool result= typFly.IsAbstract;
//判断是否为抽象的,含接口。
5.补充:TypetypDog = ass.GetType("MyClass.Dog");
Type typDog =typof(Dog);
//两个方法的结果相同
6.获取类中的方法并调用(例题)
Type typ = typeof(Person);
object obj= Activator.CreateInstance(typ);
// MethodInfo me= typ.GetMethod("Show",System.Type.EmptyTyple);//得到无参的方法
MethodInfo me = typ.GetMethod("Show",newType[] {typeof(string) });
//得到有参的函数
// me.Invoke(obj,null);//调用无参无返回值的方法。
me.Invoke(obj,new object[] { "haha"});//调用有参无返回值的方法
//若为有参的方法,则需用一个object类型的变量接收一下。
MethodInfo method = type.GetMethod("SayHi",BindingFlags.NonPublic);
//得到类型中的私有成员的方法
第十二天
一.插件(反射的应用)
1. 主程序
private void Form1_Load(object sender, EventArgse)
{
//窗体加载的时候扫描指定的目录
//获取当前运行的路径
string ass = Assembly.GetExecutingAssembly().Location;
//通过该属性将当前程序集的路径返回,否则就是程序集了
string dic = Path.GetDirectoryName(ass);
string path = Path.Combine(dic, "Lid");
string[] files = Directory.GetFiles(path, "*.dll");
foreach (string item in files)
{
//加载改路径下的文件
Assembly asa = Assembly.LoadFile(item);
Type[] types = asa.GetTypes();
Type edit = typeof(IEditPlus);
for (int i = 0; i
{
if(edit.IsAssignableFrom(types[i]) && !types[i].IsAbstract)//判段插件是否继承接口,和插件里面的该类型是否为抽象的
{
IEditPlus editPlus = (IEditPlus)Activator.CreateInstance(types[i]);
ToolStripItem tsiItem =stp.DropDownItems.Add(editPlus.Name);//为菜单按钮的属性
tsiItem.Tag = editPlus;
tsiItem.Click +=new EventHandler(tsiitem_Click);//添加单击事件
}
}
}
}
private void tsiitem_Click(object sender, EventArgs e)
{
ToolStripItem tsi = sender as ToolStripItem;//一定要写上,不然不为实例
IEditPlus edit = tsi.Tag as IEditPlus;
edit.Execute(textBox1);//直接把文本框给接口的方法了
}
2.接口(新建类库)
namespace记事本.Interface
{
publicinterface IEditPlus
{
// 接口的名子
string Name
{get;}
/// 对文本框进行操作
void Execute(TextBox tb);
}
}
3.插件(新建类库)
public class ConvertToUpper : IEditPlus
{
public string Name
{
get
{
return "小写变大写";
}
}
public void Execute(System.Windows.Forms.TextBox tb)
{
tb.Text = tb.Text.ToUpper();
}
}
二.对象与集合的初始化器
1.对象: Student stu= newStudent(){ Id = 1, Name = "YJingLee", Age = 22 };
更方便给对象赋值,在构造函数之后执行赋值,直接大括号。数组也可以。
2.集合: List num = new List(){ 0, 1, 2, 6, 7, 8, 9 };
List< Student > stus= new List
{ newStudent{Id=1,Name="YJingLee",Age=22},
newStudent{Id=2,Name="XieQing",Age=25},
};
三:浅拷贝,深拷贝
浅拷贝:整个拿过去复制一份,拿到另一个空间就完了。
深拷贝;复制一份之后又开了个空间赋值了点东西。