黑马程序员C#学习笔记
错误的理解希望能够得到大家的指正,谢谢!
/*实现了IDisposable接口的所有的对象在使用完以后要进行Dispose()资源的释放,可以使用using(){}进行资源管理*/
//创建连接是非常耗时的,因此不要每次操作都创建连接。SQL语句中的关键字应该大写。
//1个数据库能够承载的连接是有限的,所以SqlConnection在程序中不能一直保持Open。
//对于数据库来说,连接是最宝贵的资源,用完了以后一定要Close、Dispose。
// 类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。
//元数据:用于描述要素、数据集或数据集系列的内容、覆盖范围、质量、管理方式、数据的所有者、数据的提供方式等有关的信息。元数据最本质、最抽象的定义为:data about data(关于数据的数据)。它是一种广泛存在的现象,在许多领域有其具体的定义和应用。
//元数据在软件构造领域定义:在程序中不是被加工的对象,而是通过其值的改变来改变程序的行为的数据。它在运行过程中起着以解释方式控制程序行为的作用。在程序的不同位置配置不同值的元数据,就可以得到与原来等价的程序行为。
.NET Framework基础类型:
.NET所有类型都继承自System.Object。C#类型体系包含两种类型:值类型,引用类型。
值类型继承自System.ValueType。而System.ValueType继承自System.Object。
指针:在信息工程中指针是一个用来指示一个内存地址的计算机语言的变量或中央处理器(CPU)中寄存器(Register)。
指针一般出现在比较近机器语言的语言,如汇编语言或C语言。在使用一个指针时,一个程序既可以直接使用这个指针所存储的内存地址,又可以使用这个地址里存储的变量或函数的值。
寄存器:寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址。寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。
C#中使用指针:为了保持类型安全,默认情况下C#不支持指针运算。不过可以通过使用unsafe关键字来定义允许使用指针的不安全上下文。
C#中的不安全代码不一定是危险的,只是其安全性无法由CLR进行验证。编译不安全代码时需要使用csc /unsafe *.cs。
class Program { unsafe static void Method(int* parameter)//声明一个int类型的指针 { *parameter += *parameter;//指针相加 } unsafe static void Main() { int parameter = Convert.ToInt32(Console.ReadLine()); Method(¶meter); Console.WriteLine(parameter); Console.ReadKey(true); } }
值类型:值类型直接存储值
一种由类型的实际值表示的数据类型。如果向一个变量分配值类型,则该变量将被赋以全新的值副本。
C#中的值类型包括结构类型和枚举类型两大类以及byte、int、long、float、double、char、boolean。
引用类型:引用类型存储的是对值的引用
由类型的实际值引用表示的数据类型。如果为某个变量分配一个引用类型,则该变量将引用(或"指向")原始值,不会创建副本。
引用类型包括类、接口、委托和装箱值类型。C#有两个内置的引用类型:object类型和string类型。
常量与变量:
常量:常量又叫常数,主要用来存储在程序运行的过程中值不会改变的数据。常量被声明为字段,通过const关键字声明,常量必须在声明时赋值。
变量:变量是指在程序运行的过程中值可以改变的数据。
数据类型转换:
显示类型转换:显示类型转换是将高精度数值转换为低精度数值,必须指明将要转换的目标类型。由于数据类型的差异,有可能丢失部分数据。
隐式(自动)类型转换:隐式类型转换又称自动类型转换,是将低精度数值转换为高精度数值,可以直接赋值而不用指明将要转换的目标类型。
进制转换:
int i = 10;Console.WriteLine("十进制转二进制:"+Convert.ToString(i, 2));Console.WriteLine("十进制转八进制:"+Convert.ToString(i, 8));Console.WriteLine("十进制转十六进制:"+Convert.ToString(i, 16));Console.WriteLine("二进制转十进制:"+Convert.ToInt32("1010",2));Console.WriteLine("八进制转十进制:"+Convert.ToInt32("10",8));Console.WriteLine("十六进制转十进制:" + Convert.ToInt32("a",16));Console.ReadKey(true);
C#中运算符的使用:
算术运算符:+、-、*、/、%
Console.WriteLine(10 +0.5+.5);//"+"运算符用于两个数值相加,当其中一个或两个操作数都是字符或字符串时,表示相连Console.WriteLine("10" + 5);Console.WriteLine('a' + "10");int i = -10;Console.WriteLine(-i);//"-"运算符可以是一元运算符也可以是二元运算符Console.WriteLine(10 - 0.5 - .5);//一元运算符表示只用一个参数的运算,二元运算符表示符号左右两边用到了两个参数Console.WriteLine(10 * i);//"*"运算符用于计算操作数的积Console.WriteLine((double)6 / 25);//"/"运算符用于计算操作数的商Console.WriteLine(100 % 6);//"%"运算符用于计算操作数的余数Console.ReadKey(true);
赋值运算符:=、+=、-=、*=、/=、%=、??
int i = 100;//"="运算符表示将右边的值赋给左边的变量或常量i += 10;//"+="运算符等同于 i=i+10i -= 10;//"-="运算符等同于 i=i-10i /= 10;//"/="运算符等同于 i=i/10i *= 10;//"*="运算符等同于 i=i*10i %= 3;//"%="运算符等同于 i=i%10Console.WriteLine(i);int? x = null;//int? 可空类型,表示一个可能是空,也可能是int的结构int y = x ?? 10;//如果x是null,则y=10,否则y=xConsole.WriteLine(y);Console.ReadKey(true);
关系运算符:==、!=、>、<、>=、<=、
关系运算符用于实现对两个值的比较运算,关系运算符在完成对两个操作数的比较运算后会返回一个代表运算结果的布尔值。
bool result = 2 == 1;Console.WriteLine(result);Console.WriteLine(2 != 3);Console.WriteLine(5 > 6);Console.WriteLine(6>=5);Console.ReadKey(true);
逻辑运算符:&&、||、!
Console.WriteLine(true||false);//逻辑或运算,运算符左右有一个true则结果为true,否则为falseConsole.WriteLine(true && false);//逻辑与运算,运算符左右有一个false则结果为false,否则为trueConsole.WriteLine(!true);//逻辑非运算,对布尔值取反Console.ReadKey(true);
条件运算符:?:
static void Main(string[] args){ Console.Write("用户名:"); string userName = Console.ReadLine(); Console.Write("密码:"); string password = Console.ReadLine(); bool result = (userName == "admin" && password == "admin"); string strInfo = result ? "登录成功!" : "登录失败!";//result为true时就把"登录成功!"赋给strInfo Console.WriteLine(strInfo); Console.ReadKey(true);}
移位运算符:<<、>>
左移位运算:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
在数字没有溢出的前提下,对于正数和负数,左移n位就相当于乘以2的n次方。
右移位运算:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。
对于正数和负数,右移n位就相当于除以2的n次方。
class Program{ static void Main(string[] args) { //1111111111111111111111111111111111111111111111111111111110011100 << 3 //=1111111111111111111111111111111111111111111111111111110011100000 (-100 << 3 = -800) //0000 1100 1000 >> 3=0000 0001 1001 (200 >> 3 = 25) int one = -100, two = 200; int temp = one << 3;//将变量one的值左移3位。 Console.WriteLine("-100 << 3 = " + temp.ToString()); temp = two >> 3;//将变量two的值右移3位。 Console.WriteLine("200 >> 3 = " + temp.ToString()); Console.ReadKey(true); }}
is 运算符:
is运算符用于检查变量是否为指定的类型,如果是返回true,否则返回false。
class Program{ static void Main(string[] args) { int i = 10; bool result = i is int;//判断变量 i 是否为整型 Console.WriteLine(result.ToString()); Console.ReadKey(true); }}
枚举类型:
class Program { enum 功夫 //使用enum创建枚举 { 降龙十八掌 = 0, 如来神掌 = 1, 葵花宝典 = 2, 九阳神功 = 3, 独孤九剑 = 4, 太极拳 = 5 } static void Main(string[] args) { Console.WriteLine("小子,我看你骨骼惊奇,必是练武奇才,将来维护宇宙正义与和平的重任就交给你了!"); int 学习 = 0; if (学习 > 5 || int.TryParse(Console.ReadLine(),out 学习)==false) { Console.WriteLine("你什么也没有学会!"); } else { switch (学习) { case (int)功夫.降龙十八掌: Console.WriteLine("你学会了降龙十八掌!"); break; case (int)功夫.如来神掌: Console.WriteLine("你学会了如来神掌!"); break; case (int)功夫.葵花宝典: Console.WriteLine("你学会了葵花宝典!"); break; case (int)功夫.九阳神功: Console.WriteLine("你学会了九阳神功!"); break; case (int)功夫.独孤九剑: Console.WriteLine("你学会了独孤九剑!"); break; case (int)功夫.太极拳: Console.WriteLine("你学会了太极拳!"); break; default: Console.WriteLine("你什么也没有学会!"); break; } } Console.ReadKey(true); } }
Char类的使用:
class Program{ static void Main(string[] args) { char a = 'a', b = '8', c = 'L', d = '.', e = ' ', f = ' '; Console.WriteLine("IsLetter方法判断a是否为字母:{0}", Char.IsLetter(a)); Console.WriteLine("IsDigit方法判断b是否为数字:{0}", Char.IsDigit(b)); Console.WriteLine("IsLetterOrDigit方法判断c是否为字母或数字:{0}", Char.IsLetterOrDigit(c)); Console.WriteLine("IsLower方法判断a是否为小写字母:{0}", Char.IsLower(a)); Console.WriteLine("IsUpper方法判断c是否为大写字母:{0}", Char.IsUpper(c)); Console.WriteLine("IsPunctuation方法判断d是否为标点符号:{0}", Char.IsPunctuation(d)); Console.WriteLine("IsSeparator方法判断e是否为分隔符:{0}", Char.IsSeparator(e)); Console.WriteLine("IsWhiteSpace方法判断f是否为空白:{0}", Char.IsWhiteSpace(f)); Console.ReadKey(true); }}
流程控制语句:
选择结构:
if(boolean ) {语句块} else{语句块} switch(表达式) {case 常量表达式: 语句块 break; default:语句块 break;}
循环结构:
while(boolean){语句块} 、do{语句块}while(boolean) for(声明int类型变量并赋值;判断产生循环的条件;要循环的表达式){语句块} foreach(类型 循环变量名 in 集合){语句块}
跳转语句:
break(终止循环)语句只能应用在switch、while、do...while、for或foreach语句中,break语句应用于循环作用域中。continue(忽略本次循环,继续下次循环)语句只能应用于while、do...while、for或foreach语句中,continue语句应用于循环作用域中。goto语句用于将控制转移到由标签标记的语句。goto 标签; 标签: 语句块return语句用于终止当前执行的方法、可以有返回值。
数组:
一维数组:
int[] arr;/*声明数组*//*初始化数组*/ int[] arr = new int[5];/*表示数组长度是5*/int[] arr = { 1, 2, 3 };int[] arr = new int[] { 1, 2, 3};
二维数组:
int[,] arr;/*声明数组*//*初始化数组*/int[,] arr1 = new int[3, 3];int[,] arr2 = new int[2,2] {{1,2},{3,4}};static void Main(){ int[,] arr = new int[,] { { 1, 3 }, { 2, 4 }, { 5, 7 }, { 6, 8 } }; Console.Write("数组的行数:" + arr.GetLength(0));//输出二维数组的行数 Console.Write("\t数组的列数:" + arr.GetLength(1));//输出二维数组的列数 Console.WriteLine(); Console.WriteLine("循环输出数组中的元素:"); for (int y = 0; y < arr.GetLength(1);y++ ) { Console.Write("\t第" + y + "列"); } Console.WriteLine(); for (int i = 0; i < arr.GetLength(0);i++ )//遍历二维数组 { string str = ""; for (int x = 0; x < arr.GetLength(1);x++ ) { str = str + Convert.ToString(arr[i, x])+"\t"; } Console.WriteLine("第"+i+"行: "+str); } Console.ReadKey(true);}
ArrayList:动态数组,可以动态的添加和删除元素。ArrayList的容量可以根据需要自动扩充,只能是一维的形式。
class Program{ static void Main() { int[] arr = new int[] { 1, 2, 3, 4, 5, 6 }; Array.Reverse(arr);//反转整个一维数组中元素的顺序 foreach (int i in arr) { Console.Write(i); } Console.WriteLine(); ArrayList list = new ArrayList(arr);//实例化ArrayList动态数组并赋初值 list.Add("你好!");//增加数据到动态数组中 list.AddRange(arr);//添加集合到动态数组的末尾 Console.WriteLine(list.Contains(5));//判断指定元素是否在数组中 Console.WriteLine(list.IndexOf(5));//输出指定元素在数组中的索引位置,如果没有找到输出-1 list.Insert(0, "Hi!");//插入数据到指定的位置 list.Remove("你好!");//"你好!"被看做是一个元素,根据元素内容移除一个指定的元素 list.RemoveAt(1);//根据元素的索引移除一个指定的元素 list.RemoveRange(1, list.Count - 1);//移除指定范围内的所有元素 foreach (object obj in list) { Console.Write(obj); } list.Clear();//移除所有元素 Console.ReadKey(true); }}
哈希表Hashtable:散列表也叫哈希表。它表示键/值(key,value)对的集合。
class Program{ static void Main() { Hashtable htable = new Hashtable();//实例化Hashtable对象 htable.Add(1, "你好!");//向哈希表中添加元素 htable.Add(2, "很好!"); for (int i = 0; i <= htable.Count;i++ ) { Console.Write(htable[i]); } Console.WriteLine(); htable.Remove(1);//移除元素的键 Console.WriteLine(htable[2]);//输出哈希表中指定键的值 htable.Clear(); htable.Add("姓名", "张耕明"); htable.Add("年龄", 26); Console.WriteLine("\t键\t值"); foreach (DictionaryEntry dicEntry in htable) { Console.WriteLine("\t" + dicEntry.Key + "\t" + dicEntry.Value); } Console.WriteLine(htable.ContainsKey("姓名"));//判断哈希表中是否包含指定的键 Console.WriteLine(htable.ContainsValue("张耕明"));//判断哈希表中是否包含指定的值 Console.ReadKey(true); }}
静态和非静态:
static class 静态类//静态类不能实例化,只能包含静态成员和静态方法,静态成员或方法只能由类来访问{ private static string _str; static 静态类()//静态构造函数不能带有参数,不能有访问修饰符,在调用类成员时执行 { _str = "Static Class!"; } public static void StaticDemo() { Console.WriteLine(_str); } }class 非静态类{ private string _str;//非静态字段只能由对象来访问
public 非静态类(string source) { this._str = source;//this等同于类的实例对象:“非静态类 c = new 非静态类();” } public void Demo() { Console.WriteLine("非静态方法!---" + this._str); }
}静态类.StaticDemo();非静态类 noStaticDemo = new 非静态类("非静态构造函数!");noStaticDemo.Demo();
特性:特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性。
class Program { static void Main(string[] args) { MemberInfo info = typeof(Demo);//提供对成员元数据的访问
//Attribute.GetCustomAttribute(类的元数据, 要搜索的自定义属性的类型或者基类型)
特性 attribute = (特性)Attribute.GetCustomAttribute(info, typeof(特性));
attribute.Show(); Console.ReadKey(true); } } [AttributeUsageAttribute(AttributeTargets.All, AllowMultiple = true, Inherited = false)]//可应用任何元素、允许应用多次、不继承到派生类 class 特性 : System.Attribute { private string _name; public string Name { get { return _name; } } private int _age; public int Age { get { return _age; } } public 特性(string name, int age) { this._name = name; this._age = age; } public void Show() { Console.WriteLine("姓名:{0},年龄:{1}", _name, _age); } } [特性("张耕明", 28)] public class Demo { }
序列化和反序列化:序列化就是指将对象状态转换为可存储或可传输格式的过程,而反序列化则是从物理介质或流上获取数据,并还原为对象的过程。
[Serializable]//指示一个类可以序列化 public class 序列化和反序列化 { public string Name { get; set; } public int Age { get; set; } public 序列化和反序列化(string name, int age) { this.Name = name; this.Age = age; } public static void BinarySerialize(序列化和反序列化 source) { FileStream fs = new FileStream("MySerialize.bin", FileMode.Create); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(fs, source);//执行二进制序列化 fs.Dispose(); } public static 序列化和反序列化 BinaryDeserialize() { FileStream fs = new FileStream("MySerialize.bin", FileMode.Open, FileAccess.Read, FileShare.Read); BinaryFormatter formatter = new BinaryFormatter(); 序列化和反序列化 serialize = formatter.Deserialize(fs) as 序列化和反序列化;//执行二进制反序列化 fs.Dispose(); return serialize; } }序列化和反序列化.BinarySerialize(new 序列化和反序列化("张耕明", 28));//序列化序列化和反序列化 deserialize = 序列化和反序列化.BinaryDeserialize();//反序列化Console.WriteLine("姓名:{0},年龄:{1}", deserialize.Name, deserialize.Age);序列化和反序列化 serialize = new 序列化和反序列化("张耕明", 29);= new typeof(序列化和反序列化));StreamWriter streamW = new StreamWriter("Myserialize.");//执行streamW.Dispose();FileStream fileStream = new FileStream("Myserialize.", FileMode.Open);序列化和反序列化 = as 序列化和反序列化;//执行Console.WriteLine("",
属性和方法:
属性是实体的描述性性质或特征,具有数据类型、域、默认值三种性质。属性有访问器,当读取属性时执行get访问器的代码块;当向属性分配一个新值时执行set访问器的代码块。不具有set访问器的属性被视为只读属性,不具有get访问器的属性被视为只写属性,同时具有get和set访问器的属性是可读可写属性。属性不能作为ref参数或者out参数传递。
访问级别:
public:公共的、全局的,表示不限制对该类成员的访问
private:私有的,表示只有该类本身可以访问
protected:受保护的,表示只有该类本身和他的子类可以访问
internal:内部的,表示程序集内可访问
构造函数(方法)和析构函数:
构造函数:构造函数是在创建给定类型的对象时执行的类方法。构造函数具有与类相同的名称,它通常用来初始化新对象的数据成员。
析构函数:是以~加类名来命名的,.NET Framework类库有垃圾回收功能。当某个类的实例被认为是不再有效,并符合析构条件时,.NET Framework类库的垃圾回收功能就会调用该类的析构函数实现垃圾回收。一个类中只能有一个析构函数,并且无法调用析构函数,它是被自动调用的。
class Program{ string id, name; ~Program()//析构函数 { Console.WriteLine("垃圾回收!"); Console.ReadLine(); } public Program() { id ="01"; name = "未命名"; } public Program(string id, string name) { this.id = id;
this.name = name; } static void Main() { Program p = new Program();//使用没有参数的构造函数 Program p1 = new Program("001", "张耕明");//使用有参数的构造函数 Console.WriteLine(p.name); Console.WriteLine(p1.name); Console.ReadKey(true); } }
方法的重载:方法的重载要求参数的类型不同或者参数的个数不同,与方法的返回值无关。
class Program { static void Main(string[] args) { Program.说("Computer"); Program.说("联想", 5); Console.ReadKey(true); } static void 说(string 姓名) { Console.WriteLine("电脑说:我的名字是{0}。" ,姓名); } static void 说(string 品牌,int 年龄 ) { Console.WriteLine("电脑说:我诞生于{0}公司,现在{1}岁了!", 品牌, 年龄); } }
结构:结构是一种值类型,通常用来封装一组相关的变量。C#中使用struct关键字来声明结构,struct不能从class继承,也不能作为class的基类。
支持接口继承。
class Program { public struct Rectangle//定义一个矩形结构 { private double _width; private double _height; /// <summary> /// 构造函数,初始化矩形的宽和高 /// </summary> /// <param name="x">矩形的宽</param> /// <param name="y">矩形的高</param> public Rectangle(double x, double y) { _width = x; _height = y; } /// <summary> /// 计算矩形的面积 /// </summary> /// <returns>矩形面积</returns> public double Area() { return _width * _height; } } static void Main() { Rectangle rectangle = new Rectangle(3.5, 10);//使用构造函数实例化矩形结构并赋初值 Console.WriteLine("矩形的面积是:" + rectangle.Area()); Console.ReadKey(true); } }
深拷贝和浅拷贝:
class 深拷贝和浅拷贝 { private string _shallow; /// <summary> /// 浅拷贝 /// </summary> public void ShallowCopy() { 深拷贝和浅拷贝 instance1 = new 深拷贝和浅拷贝(); 深拷贝和浅拷贝 instance2 = instance1;//浅拷贝,拷贝对象和源对象都指向同一个实例 instance1._shallow = "Hello C#!"; instance2._shallow = "Shallow Copy!"; Console.WriteLine("浅拷贝:{0}、{1}", instance1._shallow, instance2._shallow); } /// <summary> /// 深拷贝 /// </summary> public void DeepCopy() { int a = 100; int b = a;//深拷贝,拷贝对象和源对象相互独立,不共享任何实例数据 a = 500; b = 1000; Console.WriteLine("深拷贝:{0}、{1}", a, b); } }
装箱与拆箱:
class 装箱与拆箱 { public void Demo()//装箱只发生在值类型,引用类型本身就已经装在箱子里了(箱子指托管堆) { int i = 0; object obj = i;//装箱就是在托管堆中创建值类型的实例,然后返回一个新对象的地址 i = (int)obj;//拆箱就是获取箱子中原本属于值类型的指针 Hashtable hashTable = new Hashtable();//大量的装箱与拆箱会造成多余的对象,会影响系统性能。 for (int x = 0; x < 10; x++) { hashTable.Add(x, obj); } int y = 10;//值类型使用时避免隐式的和引用类型转换,尽可能以显示的方式来实现 object o = y.ToString();//ToString方法由int类型重写,因此不会装箱 }List<int> 泛型集合 = new List<int>();//在操作值类型时尽量使用泛型集合来代替非泛型集合,会得到性能上的提升泛型集合.Add(1);//不会发生装箱
使用using:
using System;//引入命名空间using T = System.Threading;//使用using创建命名空间别名class Demo{ public Demo() { T.Thread.Sleep(1000); }}using (SqlConnection sqlConn = new SqlConnection()) { }//强制资源清理
面向对象:面向对象程序设计可以被视作一种在程序中包含各种独立而又互相调用的单位和对象的思想。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象。因此它们都可以被看作是负有责任的角色。面向对象的编程方式具有封装、继承和多态性等特点。
未完待续..
TAG: