《C#入门经典v6》读书笔记1 C#语言
2016-03-30 16:46
489 查看
前言
我说会C#,实际都是皮毛。买了《C#入门经典》(v6)和《C#高级编程》(v9),决定系统地学一遍。这是我的读书笔记而已,不是什么教程,如果有错误,还请各路大神指正。希望自己坚持看完这两本书,做好笔记,补缺补漏。
第1章 C#简介
Framework 框架Compact 精简的
OOP(Object-Oriented Programming,面向对象编程)
CTS(Common Type System,通用类型系统)指如int等最基础的数据类型
CLR(Common Language Runtime,公共语言运行库)负责管理用.Net库开发的所有程序的执行
CIL(Common Intermediate Language,通用中间语言)
JIT(Just-In-Time,准时、实时、即时)
GAC(Global Assembly Cache,全局程序集高速缓存)
WPF(Windows Presentation Foundation,Windows呈现基础,取代原来的Windows Form)
WCF(Windows Communication Foundation,Windows通讯平台)
ASP.NET Active Server Pages.NET
ADO.NET Active Data Object.NET
IDE(Integrated Development Environment,集成开发环境)
概念
托管代码 类型安全
第2章 编写C#程序
Console Application 控制台应用程序第3章 变量和表达式
unsigned 无符号#region 代码块(可折叠) #endregion
@逐字指定字符,除双引号外。
基础类型中,string是引用类型,可指定null,其他类型为值类型。
数学运算符 - 取反,+ 不变。
int i = -3; k = +i;//k=-3 k = -i;//k=3
++运算符放在操作数前面时,操作数在任何其他表达式计算前受到影响,而++运算符放在操作数后面时,操作数在完成表达式计算后才受到++运算符影响。例子见P36。
int i = 3, j = 3,k=0; k = i++;//k=3 k = ++j;//k=4
为命名空间取别名。
using SL = System.Linq;
第4章 流程控制
逻辑运算符 && || 与 & | 功能一样,但推荐使用前者(性能较高)。int i = 0; bool a = (i != 0) && (2 / i > 0);//i为0时,不计算(2 / i > 0) bool b = (i != 0) & (2 / i > 0);//i为0时,仍计算(2 / i > 0),引发除0错误
goto语句有用但最好不用。
int i = 5; goto lable2; i++;//未执行 lable2: i--;//i为4
第5章 变量的更多内容
IntelliSense 智能感知JaggedArray 锯齿数组
char存储的是数值,所以char被当做个数值类型。
checked/unchecked 用于类型转换时,表达式的溢出检查。(不检查时,出现溢出则数据丢失)。
int i = 10000; byte k = checked((byte)i);
enum 定义枚举,详见P81。
enum Day:short//默认基础类型是int { Monday=1,//默认从0开始 Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
数组定义,详见P88。
//一维数组 const int constSize = 5; int[] array1 = { 1, 2, 3, 4, 5 };//合法,数组默认值{ 1, 2, 3, 4, 5 } int[] array2 = new int[constSize];//合法,数组默认值为int的默认值0 int[] array3 = new int[constSize] { 1, 2, 3, 4, 5 };//合法,数组默认值{ 1, 2, 3, 4, 5 } int size = 5; int[] array4 = new int[size];//合法,数组默认值为int的默认值0 int[] array5 = new int[size] { 1, 2, 3, 4, 5 };//【非法】,此处size应使用常量值(因为已初始化元素) //矩形数组(每行的元素个数相同) int[,] array6 = new int[3, 4];//二维数组,3行4列 int[, , ,] array7 = new int[1, 2, 3, 4];//多维数组 //锯齿数组(数组的数组,每行的元素个数可能不同) int[][] array8 = new int[][] { new int[]{1}, new int[]{1,2}, new int[]{1,2,3} };
foreach循环与for循环的主要区别:foreach循环只可只读访问数组元素,而不能修改。
以下标方式访问string的字符时,可读不可写。
string s = "abc"; char c = s[1];//合法,c='b' s[1] = 'j';//非法,s[1]只读
string.PadLeft() 用于字符串对齐。
string s = "abc",a,b; a = s.PadLeft(10);//在s左部填充空格以达到长度10 b = s.PadLeft(10,'-');//在s左部填充'-'以达到长度10
第6章 函数
parameter 形式参数(函数定义的一部分)argument 实际参数(调用代码传递给函数的参数)
参数数组,用params关键字为函数指定一个(只能一个)特殊参数,该参数只能是函数定义的最后一个参数。
static int Sum(params int[] nums)//params参数数组必须是参数定义中的最后一个参数 { int sum = 0; foreach (int n in nums) { sum += n; } return sum; } //使用 int sum=Sum(1,2,3,4);//可以指定任意多个int参数
ref参数:用作ref参数(引用参数)的变量有两个限制:已初始化过的非const变量。
out参数:用作out参数(输出参数)的变量可以是未赋值的变量。在函数使用out参数时,应将其看做是尚未赋值的变量。详见P113。
函数签名:函数名+参数。(唯一标志)
函数重载:函数名相同,但函数签名不同。
Main()函数与命令行参数的使用。详见P120。
delegate委托。委托是定义一个函数的类型(指定参数和返回类型),之后可将匹配该类型的函数作为该类型的变量来使用。详见124。
delegate double MyDelegate(int a, int b);//声明委托,指定参数与返回类型 double Multiply(int x, int y) { return x * y; }//与委托匹配的函数1 double Divide(int x, int y) { return x / y; }//与委托匹配的函数2 //使用 MyDelegate d; double result; d = new MyDelegate(Multiply);//实例化委托,此时d实际上就是函数Multiply result = d(1, 2);// 1*2 d = new MyDelegate(Divide);//实例化委托,此时d实际上就是函数Divide result = d(1, 2);// 1/2
第7章 调试和错误处理
Toggle BreakPoint 插入断点 (Toggle 开关)SEH(Structured Exception Handling,结构化异常处理)
非中断模式调试:诊断输出(C#功能,Debug.WriteLine()+Trace.WriteLine())+ 跟踪点(VS功能)
中断模式调试:配置断点(断点可以配置几种中断条件)+ Debug.Assert()
Debug.WriteLine() 只能用于调试模式(Debug),将文本写到Output输出窗口。
Trace.WriteLine() 可用于调试+发布模式(Release),将文本写到Output输出窗口。
System.Diagnostics.Debug.WriteLine("a debug message");//仅在调试模式起作用 System.Diagnostics.Trace.WriteLine("a trace message");//在调试+发布模式均起作用
第8章 面向对象编程简介
UML(Unified Modeling Language,统一建模语言)IDisposable接口与using关键字释放资源。P162。
基类(父类)派生出派生类(子类),派生类继承基类。
seal 密封类,不能用作基类,所以没有派生类。
基类的成员可虚拟(virtual),由派生类重写(override)实现。
abstract 抽象类,不能直接实例化,需被继承。抽象类有抽象成员(需被重写)和非抽象成员(有具体实现)。
interface接口,用于定义通用功能,不可自己实现。
abstract class(抽象类)与interface(接口):
在语法、用法上十分相近,但本质上不同:
抽象类:共性对象(强调属性,是对有相似属性的对象的概括,主要用作对象系列的基类)
接 口:相同功能(强调功能,完全不同的类也可以具有相同的功能)
virtual与abstract:详见P193。
均用于基类中指定成员可被派生类用override关键字重写,区别是:
virtual修饰的方法必须有方法体(实现),abstract修饰的方法不能有方法体(声明);
virtual可以被派生类重写或不重写,abstract必须被重写;
只有抽象类才可使用abstract修饰方法;
第9章 定义类
finalize 完成;结束DLL(Dynamic Link Library,动态链接库,又称“应用程序拓展”)
class类、interface接口;几种修饰关键字:internal (程序集内部访问)/ public、abstract / sealed
类型比较object.GetType() == typeof(Object)。P181。
无参数构造函数为默认构造函数。
定义的类如果没有使用基类,则只继承于基类System.Object(C#中别名object)。实例化派生类时,基类调用其默认构造函数。因此,实例化一个类时,总是首先调用System.Object.Object()。
值类型与引用类型:值类型(简单类型+结构体struct),引用类型(string+类class),详见P195。
关于对象复制,详见P197+P254。
shallow copy 浅度复制:System.Object的MemberwiseClone(),对引用类型对象复制的是引用。
deep copy 深度复制:实现ICloneable接口的Clone()方法,详见P254。
第10章 定义类成员
refactoring 重构implementation 实现
readonly关键字:表明字段只能由构造函数或初始化赋值语句进行赋值。
const成员也是静态的,所以不需要static修饰。
字段与属性的区别:
//私有字段,camelCasing private int number;//字段 //公共字段,PascalCasing public string Name;//字段 public int Number//属性 { get { return number; } protected set //可为访问器设置访问性 { //属性控制 if (value > 0) { number = value; } else { //抛出异常提供控制权 throw new ArgumentOutOfRangeException("Number", value, "Number 必须大于0"); } } }
自动属性:由编译器声明对应私有字段
public int Number { get; protected set; }
隐藏基类方法:派生类继承方法前加关键字new。
接口的实现。P217。(隐式、显式实现区别,特殊属性访问器)
第11章 集合、比较和转换
capacity 容量indexer 索引符
boxing 封箱/装箱
unboxing 拆箱
operator overloading 运算符重载
implicit / explicit 隐式/显式
CollectionBase、DictionaryBase:自定义集合类可继承这两个类,详见P242。
yield关键字:在迭代器块中选择在foreach循环中使用的值。
封箱/装箱:封箱可以看作是浅度复制的过程,值类型封箱引用新副本,引用类型封箱引用源引用类型。
is运算符:用于检查对象是否可以转换为指定类型(基类或接口),可以转换运算符返回true。
classa.GetType()== typeof(ClassA):用于检查对象是否就是指定类型(而不是其派生类等)。
as运算符:用于把一种类型转换为指定的引用类型。以下两句代码等价,但有不同:as运算符进行类型转换失败时返回null,而不抛出异常。详见P279。
return cards.Clone() as Cards; return (Cards)cards.Clone();
运算符重载:P264
//运算符重载 public static bool operator ==(Card c1, Card c2) { return (c1.suit == c2.suit) && (c1.rank == c2.rank); } public static bool operator !=(Card c1, Card c2) { return !(c1==c2);//调用其他运算符减少代码量和错误可能 } //重写该方法可以确保任何比较技术得到的结果相同 public override bool Equals(object obj) { return this == (Card)obj;//具体比较操作 } //重写该方法可以确保任何比较技术得到的结果相同 public override int GetHashCode() { return 13 * (int)suit + (int)rank;//根据状态,返回对象实例的唯一int值 }
IComparable接口:在要比较对象的类中实现CompareTo(),比较对象与对象,如:a.CompareTo(b)
IComparer接口:在单独的比较类(比较器)中实现Compare(),如:comparer.Compare(a,b)
arrayList.Sort():使用项的CompareTo()进行默认排序,或传入一个比较器(实现IComparer接口的类)实例进行自定义排序,如arrayList.Sort(comparer)。详见P274。
implicit / explicit 关键字:用于指定隐式/显式类型转换,详见P279。
public static explicit operator ClassA(Class2 obj) { ClassA returnObj = new ClassA(); checked { returnObj.val = obj.val; }//在显式转换中建议使用checked检查溢出 return returnObj; }
第12章 泛型
generic 通用的;一般的N/A(Not Applicable,不适用(不是Not Available))
predicate 断言;判定
System.Nullable:可空类型,用于使值类型为空null。
//以下两句代码等价 System.Nullable<int> nullableInt1 = null; int? nullableInt2 = null;
??运算符:可用于为可空类型提供默认值,不需要使用if判断。
op1 ?? op2 //等价于下句 op1 != null ? op1 : op2 //当op1非空时返回op,1,否则返回op2
泛型元素:类、方法、接口、委托,如:
List<T>、Dictionary<K,V>//泛型类 IComparer<T>、IComparable<T>//泛型接口 Comparison<T>、Predicate<T>//泛型委托 ...//泛型方法
default关键字:定义泛型类中根据T是值类型/引用类型赋予值类型默认值/null。
where关键字:约束可用于实例化泛型类的类型。
协变关键字out:协变类型参数只能用作返回值或者属性get访问器(输出)。
抗变关键字in:抗变类型参数只能用作方法参数,不能用作返回类型(输入)。
第13章 其他OOP技术
alias 别名nest 嵌套;巢
subscribe 订阅
:: 运算符:当命名空间的别名与实际存在的命名空间重名时,编译器默认使用实际命名空间,此时可使用::符号迫使编译器使用由using语句定义的别名。
global关键字:实际是顶级根名称空间的别名。
定制异常:继承基类Exception,用try{…}catch{…}finally{…}捕获。
event关键字:定义事件
//Step0.定义参数类型(必要时),继承EventArgs public class MyEventArgs : EventArgs { private string message; public string Message { get; set; } public MyEventArgs(string msg) { message = msg; } } //Step1.定义委托,指定事件处理方法的参数和返回类型 //(标准事件委托:void返回类型+object事件源+继承EventArgs的事件参数) public delegate void MyEventHandler(object sender, MyEventArgs e); //Step2.定义事件,并指定要使用的委托类型。 public event MyEventHandler LastCardDrawn; //触发事件 public Card GetCard(int cardNum) { //当事件为null时说明该事件没有订阅者,不会引发事件 if (cardNum == 51 && LastCardDrawn != null) LastCardDrawn(this, new MyEventArgs("自定义参数"));//触发事件,传递事件参数 return cards[cardNum]; }
事件处理程序最好使用void返回类型;有返回值时(非void),访问的是最后一个订阅事件的处理程序返回值。
EventHandler、EventHandler:.NET定义的委托类型,使用标准的事件处理模式,其原型为:
public delegate void EventHandler(object sender, EventArgs e); public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
匿名方法:使用delegate关键字就地定义一个纯粹用作委托目的的处理程序,详见P335。
Attribute特性:对代码进行装饰,如[DebuggerStepThrough],通过反射读取特性值,详见P344。
第14章 C#语言的改进
COM(Component Object Model,组件对象模型)aggregate 聚合、聚集
accumulate 积累
对象初始化器、集合初始化器:合并实例化与初始化的简化方式。
List<Animal> farm = new List<Animal>//集合初始化器 { new Chicken(),//调用构造函数进行初始化 new Cow { Name="Norris" }//对象初始化器:不必显式调用构造函数,直接使用公开属性-值对进行赋值 };
var关键字:进行隐式类型化,依赖于编译器确定变量类型(类型推理)
//用var声明变量时需同时初始化,编译器才能确定变量类型 var myVar = new[] { 1, 2, 3 };//myVar被隐式设置为int[]
匿名类型:只读
var curry = new { Name = "name", Age = 5 };
dynamic关键字:动态类型,主要用于处理其他语言创建的对象,尽量避免使用。详见P362。
可选参数:为参数提供默认值,使其成为可选参数。避免使用。(可省去部分函数重载代码)
Optional特性也可定义可选参数,详见P366。
public List<char> GetChar( string str, bool capitalized = false //可选参数,必须位于参数列表末尾 ) { List<char> chars = new List<char>(); string newStr = capitalized ? str.ToUpper() : str; foreach (char c in newStr) chars.Add(c); return chars; } //使用 List<char> chars = GetChar("string");//等价于 List<char> chars = GetChar("string",false);
命名参数:当一个方法存在多个可选参数时,可使用<形参名>:<形参值>的形式使用指定参数。
List<char> chars = GetChar("string",capitalized : false);
扩展方法:给现有类型添加扩展功能,可提供实用方法库,详见P373。
Lambda表达式(用作委托):只用单一表达式即可完成任务时最佳,否则定义非匿名方法较好
(int a, int b) => a + b//编译器会提取Lambda表达式,创建一个匿名方法 (a, b) => a + b//隐式类型化,由编译器联系上下文确定参数类型,更加灵活 (a, b) => { b++; return a + b; }//含多条代码且返回类型不是void时,需用{}包含代码,用return指定返回值 a => a + b//只有1个隐式类型化参数,可省略括号() () => Math.PI//没有参数,用空号()表示
Lambda表达式表示为泛型类型:
泛型委托 | 类型参数 | 返回类型 | 举例 |
---|---|---|---|
Action | 0 | void | 泛型委托Action<>可表示表达式 () => Console.WriteLine("HelloWorld") |
Action<> | <=8 | void | 泛型委托Action<int,int>可表示表达式 (a, b) => Console.WriteLine((a + b).ToString()) |
Func<> | <=9 | 类型参数中的最后一个 | 泛型委托Func<string,string,int>可表示表达式 (a, b) => a.Length + b.Length(返回值为int) |
Lambda表达式结合System.Linq的使用见第23章LINQ简介。
(第一部分 C#语言 完)
相关文章推荐
- C#中 As 和强制转换的总结
- 语法高亮显示控件ICSharpCode.TextEditor
- 如何在.Net的C#中制作DLL文件
- C# 委托和事件 实现窗体间的通信
- C#_WinForm接收命令行参数
- C# 事件的简单理解
- 下载百度上的图片C#——输入名字就可以下载
- C# 调用Excel 出现服务器出现意外情况. (异常来自 HRESULT:0x80010105 (RPC_E_SERVERFAULT)
- C#委托的介绍(delegate、Action、Func、predicate)
- C# Action<T> 委托
- C# 发送邮件方法2
- c#主窗体向子窗体上的报表传参数
- C#高性能大容量SOCKET并发(一):IOCP完成端口例子介绍(转)
- Gmap.net百度地图开发
- C# 发送邮件方法
- 详解C#利用DataTable导出Excel
- 关于C#的Equals和Contains方法
- C# 去除字符串首尾字符或字符串
- C#中的强制类型转换与as转换的区别
- C#序列化及反序列化:类实例和string类型之间转换