C#入门经典(v6) 读书笔记 (第一部分 C#语言)

前言

我说会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运算符:用于把一种类型转换为指定的引用类型。以下两句代码等价,但有不同,详见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#语言的改进

还没看,待续…

时间: 2024-10-14 16:09:54

C#入门经典(v6) 读书笔记 (第一部分 C#语言)的相关文章

C#入门经典(读书笔记&lt;二&gt;)

一.抽象类与接口 (1)抽象类: 1.类中的方法不提供具体实现,但该类的派生类必须实现这些方法,这些方法在C#中称为抽象方法.  2. 抽象方法必须是一个没有被实现的空方法.包含抽象方法的类称为抽象类,抽象类中也可以包含非抽象方法. 因为抽象类是用来作为基类的,所以不能直接被外部程序实例化,而且也不能被密封.  3.通过关键字abstract进行标记将类声明为抽象. 不能创建抽象类的对象,但可以创建抽象类的引用. 一个abstract类可以不包含抽象方法,可以包含非抽象方法和变量. 抽象方法是虚

《R语言实战》读书笔记--第一章 R语言介绍

1.典型的数据分析过程可以总结为一下图形: 注意,在模型建立和验证的过程中,可能需要重新进行数据清理和模型建立. 2.R语言一般用 <- 作为赋值运算符,一般不用 = ,原因待考证.用->也可以. 3. age <- c(1,3,5,2,11,9,3,9,12,3) weight <- c(4.4,5.3,7.2,5.2,8.5,7.3,6.0,10.4,10.2,6.1) mean(weight) sd(weight) cor(age,weight) plot(age,weigh

iOS 读书笔记 第一章

1.确定某个实例或类方法是否可用. 1)使用NSObject的类方法instancesRespondToSelector:来确定是否在该类的一个实例中存在一个特定的选择器. NSArray *array = @[@"1",@"2"]; if ([NSArray instancesRespondToSelector:@selector(sortUsingComparator:)]) { //do something use sortUsingComparator: }

《javascript权威指南》读书笔记——第一篇

<javascript权威指南>读书笔记--第一篇 金刚 javascript js javascript权威指南 由于最近想系统学习下javascript,所以开始在kindle上看这本书来补充下. 今天是今年的196天,由于我之前承诺过,每天分享读书笔记,只是之前分享的是大众读物,所以随手分享到kindle阅读群里了.但是现在读的是技术类书籍,分享到kindle读书群不太合适,所以还是以博客的形式分享.这样子,一个链接,大家感兴趣了就点开看看,不感兴趣了,就不点开. 其实这篇文章应该是昨天

《Java web 开发实战经典》读书笔记

去年年末,也就是大四上学期快要结束的时候,当时保研的事情确定了下来,终于有了一些空闲的时间可以学点实用的技术. 之前做数据库课程设计的时候,也接触过java web的知识,当时做了一个卖二手书籍的网站,但是由于掌握的技术不够,最后做出来的东西勉强能应付答辩.所以,想抽出时间继续昨晚这个项目.当时,我有些找工作的同学,已经在北京经历了找工作的艰辛,所以他们时常会举办一些小讲座,给学弟学妹传授找工作的经验,我也从这上面学到不少东西.<Java web 开发实战经典>这本书便是以为找工作的同学浩哥给

《Java并发变成实践》读书笔记---第一章 简介

<Java并发编程实战>深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册.书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险.构造线程安全的类及验证线程安全的规则,如何将小的线程安全类组合成更大的线程安全类,如何利用线程来提高并发应用程序的吞吐量,如何识别可并行执行的任务,如何提高单线程子系统的响应性,如何确保并发程序执行预期任务,如何提高并发代码的性能和可伸缩性等内容,最后介绍了一些高级主题,如显式锁.原子变量.非阻塞算法以及

《深入理解Java虚拟机》读书笔记---第一章 走进Java

一.为什么要读此书 <深入理解Java虚拟机>这本书读了很多次,每次读都会有不一样的感受.首先说一下为什么要读这本书,如果把Java比喻成乾坤大挪移,那了解虚拟机的工作原理就是练习九阳神功,java语言是招式,对虚拟机的认识是内功心法,只有内功心法强大,所使的招式才强大,这就是为什么阳顶天只能把乾坤大挪移练到第四层,而张无忌能练到第七层.由于java虚拟机的强大,把很多功能都隐藏了,例如内容管理,垃圾回收机制等,使得很多java程序猿对这一块的知识所有缺失,编码的时候也是似懂非懂的,以至于遇到

Apache Tomcat 7 读书笔记 - 第一章

Apache Tomcat 简介: 开源框架,下载地址:http://tomcat.apache.org/.可以嵌入独立的web应用,也可作为多个web应用的服务器. 基于Java的web应用服务器容器,能托管Servlet和Java Server Pages(JSP)的web应用.我们常用的J2EE框架,Spring MVC, Structs等,部署到Tomcat上去后,Tomcat会将其自动解析成Serlvet与JSP.在前后端开发完全分离的情况下(后台只提供接口,前端调用),不推荐使用原有

读书笔记之:C语言深度剖析

读书笔记之:C语言深度剖析 <C 语言深度解剖>这本书是一本“解开程序员面试笔试的秘密”的好书.作者陈正冲老师提出“以含金量勇敢挑战国内外同类书籍”,确实,这本书中的知识点都是一些在面试中常见的考点,并且很多都是我们平常不注意的点,对于我们深入理解C语言确实很有帮助. 第1章关键字 1.register虽然寄存器的速度非常快,但是使用register修饰符也有些限制的:register变量必须是能被CPU寄存器所接受的类型.意味着register变量必须是一个单个的值,并且其长度应小于或等于整

《30天自制操作系统》读书笔记(3) 引入C语言

这一次的学习相当曲折, 主要是因为粗心, Makefile里面的错误导致了文件生成出现各种奇奇怪怪的问题, 弄得心力交瘁, 因此制作过程还是尽量按着作者的路子来吧. 作者提供的源码的注释在中文系统下是乱码, 而且代码的分隔用了两个Tab, 在这里要处理一下: :%s/;.*//g 删除所有的注释; :%s/\t\t/\t 把两个Tab替换为一个Tab; 要让作者的nas文件和asm文件拥有相同的语法规则, 在_vimrc文件的最后一行添加 au BufNewFile,BufRead *.nas