C#基础笔记

来源:互联网 发布:网络最牛的对联 编辑:程序博客网 时间:2024/06/09 23:46
动态链接库DLL,Dynamic Link Library)和程序都属于程序集Assembly)。

C#编译器只是将C#代码转换成公共中间语言Common Intermediate Language, CIL),VESVirtual Execution System 虚拟执行系统,也称运行时)将CIL编译成机器码,这个过程称为即时编译JT编译,Just-in-Time)。这些代码称为托管代码Managed Code)。

在数值范围内,decimal数字表示的十进制数都是完全准确的,因为其基数是十进制的。浮点数是基于二进制的,所以有误差。可以在数值最后加上m,表示decimal类型,加f,d分别表示float, double.

直接将一个值放到源代码中的行为称为硬编码hardcoding)。若是修改数值,必须重新编译代码。为了避免这种情况,可以考虑从外部来源获取数值,如配置文件(如公司系统的config.xml)。

round-trip格式说明符返回的是一个完整的字符串,假如将该字符串转换回数值,那么将肯定得到原始值。

不能将换行符直接插入到一个不以@开头的字符串中(想想在C#里取数SQL基本都是以@开头)。

string类型的关键特征在于它是不可变的(immutable),没有机制(自带方法)可供修改一个字符串的内容。可以将方法将其处理后的返回值重新赋值给它。

string.System.Text.StringBuilder同样不可变,但System.Text.StringBuilder类型则可通过Append(),Insert(),Remove(),Replace()等进行修改。

所有类型都可以划分为两类:值类型和引用类型。值类型储存的是数值,在栈上。引用类型储存的是内存地址,同样在栈上。但通过内存地址在堆上找到数值。所以,修改值类型,只会对该变量影响。修改引用类型,所有指到该内存地址的值都会被修改。

在checked块内,如果在运行时发生一次溢出的赋值,就会引发一个异常。在unchecked块内,它会将数据截断,不引发异常。C#默认是后者。

在C#2.0开始,所有的基本数值类型都包含一个静态TryParse()方法。该方法与Parse类似,只是其需要两个参数,返回布尔值。在转换失败情况下,不会报错,只是返回false。

多维数组结构必须一致,交错数组则要求对数组中的数组进行实例化。两者声明不同,多维数组是int[,] ,交错数组是int[][] 。

属性Length返回数组中元素的总数。如果是多维数组,则返回所有子元素的个数,如二维数组,2行3列,则6个。如果是交错数组,由于Length返回的是外部数组的元素数,所以Length只作用于外部数组,只统计有多少个数组,不管各自内部有多少个元素。

System.Array.BinarySearch()传入数组必须升序,否则出错(注意不仅是排序,是升序)。如果以降序,或者搜索元素不存在,那么返回值为负值。使用取反运算符~可以返回大于搜索值的第一个索引(暂时不知有鬼用)。

System.Array.Reverse()反转数组

System.Array.Clear()不删除数组元素,而且不将长度设为零,因为数组大小是固定的,不能修改。所以Clear只是将每个元素设为默认值,引用类型Null,数值0,bool false, char '\0'。

string类型的ToCharArray()方法,返回一个char数组。

 

DOS/Windows系统采用CRLF(即回车+换行)表示下一行
Linux/UNIX系统采用LF表示下一行
MAC系统采用CR表示下一行
注:CR的ASCII是十进制数的13,十六进制的0x0D,LF为10和0x0A

 多数的计算机语言中,CR表示为字符或者字符串就是"\r",LF为"\n"


为了在多个平台都可运行,可用System.Environment.NewLine属性来输出当前环境的换行符。

2013.1.11


从C#2.0开始,所有异常都派生自System.Exception类,所以所有的异常都可以用catch(System.Exception exception)块进行处理。然而,一个更好的做法是编写专门的catch块来处理更具体的派生类型(如System.FormatException),从而获取有关异常的具体信息,有的放矢地进行处理,并避免使用大量条件逻辑来判断具体发生了什么类型的异常。

这也是C#规定catch块必须从“最具体”到“最不具体”排列的原因,例如用于捕捉System.FormatException的catch语句不能出现在System.Exception之后,因为System.FormatException 较 System.Exception更具体。

命名空间可以是嵌套的,这意味着假如一个方法在一个更具体的命名空间中,那么即使存在using System这样的指令,也不能在使用更具体的命名空间时省略System字样,比如要使用System.Text中的方法,则必须指定using System.Text命名空间。换句话说,就是必须准确指明命名空间。

C#中的二元运算符要求进行一次赋值或者调用,它们总是返回一个新的结果,而且两个操作数都不能修改。在C++中像1+1;这样不进行赋值的语句通过编译,但在C#中,只有赋值,调用,递增,递减和new对象表达式才允许作为仅有运算符的语句使用。

 2013.1.14

 


作为一个良好的编程习惯,我们应该只在属性实现的内部,访问为属性提供支持的字段。换言之,我们使用的应该一直是属性,而不要直接调用字段。许多时候,即使是在包容属性的那个类中,也不应该从属性实现的外部,访问它所支持的字段。这样一来,在为属性添加了验证逻辑或者其他额外的逻辑之后,整个类就可以马上利用这些逻辑。

C#允许属性像字段一样使用,只是不允许将它们作为ref或者out参数值来传递,因为ref和out参数值在内部实现时,需要将内存地址传给目标方法,但属性可能是没有支持字段的虚字段。

一旦为一个类显式添加了构造器,C#编译器就不再自动提供默认构造器。没有必要依赖由编译器定义的默认构造器,程序员可以显式地定义一个默认构造器,这也许是一种能将某些字段初始化成特定值的构造器。、

对象初始化器。在创建对象的构造器调用之后,现在增加一对大括号,并在其中添加一个成员初始化列表,赋值等号左边是字段属性,右边是值。如:

public Student (string id, string firstname, string lastname){ Sex = '1', Score = 60}

使用this在一个构造器中调用另一个构造器,可以避免输入重复的代码。这称为构造器链(constructor chaining),它是用对象初始化器来实现的。如:

public Employee(int id, string firstName, string lastName):this(firstName, lastName)此处this表示构造器

静态构造器。不是显式调用的,运行时会在首次访问类时自动调用静态构造器。

【关于const和readonly】

 首先先解释下什么是静态常量以及什么是动态常量。静态常量是指编译器在编译时候会对常量进行解析,并将常量的值替换成初始化的那个值。而动态常量的值则是在运行的那一刻才获得的,编译器编译期间将其标示为只读常量,而不用常量的值代替,这样动态常量不必在声明的时候就初始化,而可以延迟到构造函数中初始化。

      当你大致了解上面的两个概念的时候,那么就可以来说明const与readonly了。const修饰的常量是上述中的第一种,即静态常量;而readonly则是第二种,即动态常量。那么区别可以通过静态常量与动态常量的特性来说明:

      1)const修饰的常量在声明的时候必须初始化;readonly修饰的常量则可以延迟到构造函数初始化 

      2)const修饰的常量在编译期间就被解析,即常量值被替换成初始化的值;readonly修饰的常量则延迟到运行的时候

      此外const常量既可以声明在类中也可以在函数体内,但是static readonly常量只能声明在类中。

http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.html

2013.1.22


 

解决单一继承的问题,可以用聚合来解决,即在一个类中聚合另一个类,使后者成为前者的一个成员。

重写一个成员,会造成运行时调用最底层或者说派生得最远的实现。

假如有如下继承链:a<-b<-c<-d,在a中有虚方法public virtual do();且b,c,d均重写了do方法。

那么a A = new c(); A.do(); 从a开始往下寻找,将调用c的do方法,因为从a到c,c派生到最远。同理如果a A = new d(); A.do();将调用d的do方法。b亦同理。

如果重写一个方法没有使用override关键字,编译器会报告一条警告消息。

new修饰符在基类面前隐藏了派生类重新声明的成员。在这种情况下,不是调用派生得最远的成员,相反,基类的成员会搜索继承链,找到使用了new修饰符的那个成员之前的成员,然后调用该成员。

假如有如下继承链:a<-b<-c<-d,在a中有非虚方法public do(); 在b中有虚方法public virtual do(); c继承并重写了do(),d用new声明了一个do()方法。

那么分别实现A,B,C,D四个实例,分别对应a,b,c,d四个类。将D赋值给A,B,C。下面分析四者调用do方法时不同的结果:

D.do();调用d的方法,这个没什么好解析的。

C.do();从c到d,虽然构成一个继承链,但do方法在d是new修饰的,不在重写范围,所以调用的是c的方法。

B.do();从b到d,同样构成一个继承链,但到c是do方法重写的最后一站,所以与C.do();一样,调用的是c方法。

A.do();从a到d,a的do方法没有重新声明任何基类成员,而且是非virtual的,所以,它会被直接调用,调用a方法。

接口。一旦某个类声明自己要实现一个接口,则该接口的所有成员都必须实现。

接口的一个重要特征在于,它们永远不能被实例化,不能使用new来创建一个接口。也正是这个原因,接口不能有构造器或终结器。接口也不能包含static成员,因为接口的一个重要目的就是实现多态性,而假如没有实现它的一个类型的实例,多态性是没有什么价值的。

显式实现接口成员,只有通过接口本身来调用它,而隐式实现则可以直接调用。

比如a显式实现接口iCompare,那么a的实现A调用Compare()方法,必须先将其转为iCompare类型,再调用,否则出错。即必须这样调用:((iCompare)A).Compare();而隐式实现的话,直接调用A.Compare();但同时a中的Compare()方法必须是public的(默认是private)。

更改或者删除一个特定接口成员的签名,明显会造成现有代码的中断,因为除非进行修改,否则对那个成员的任何调用都不再能够编译。更改一个类的public或者protected成员也同样如此。然而跟类不同的是,增加一个接口成员,同样也不能编译。因为要实现接口的所有成员,因此要进行修改才可以。

在开发阶段更改接口显然是可以接受的,虽然开发者可能要为此付出相当多的劳动,然而一旦接口对外发布,就不应该更改它,相反,你应该创建第二个接口,该接口可以从原始接口派生。

2013.1.27

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小斗鱼出生后喂年丰虾在缸底怎么办 脸上痘痘红肿痒怎么办 签证一定要写酒店地址怎么办 重庆的狗狗死了怎么办 村霸霸占土地该怎么办 母狗生不出来了怎么办 电视锁屏失败了怎么办? 海尔户户通位置信息改变怎么办 户户通e02智能卡通信失败怎么办 户户通e04未授权怎么办 查环保没生意做怎么办 怎么办扬大牛奶直销点 军人在退伍的时候带病怎么办 个税密码忘记了怎么办 地税网上申报密码忘记了怎么办 国税银行缴款凭证丢失了怎么办 税务局让法人缴税法人不缴会怎么办 税盘忘记清卡怎么办 7年没申报地税怎么办 已报税忘了清卡怎么办 国税报税密码忘了怎么办 有一个月忘报税了怎么办 地税报税密码忘了怎么办 电子税务账号忘记了怎么办 国税ukey密码忘了怎么办 电子税务局显示版本低怎么办 电子税务局2.0不显示打印怎么办 青海建筑三级资质初申是怎么办 欠钱败诉没钱还怎么办 学校退款卡丢了怎么办 学校发的卡掉了怎么办 汇款回执单丢了怎么办 大学交学费的卡丢了怎么办 交学费的银行卡丢了怎么办 学校补助卡丢了怎么办 学校交学费的卡丢了怎么办 采购零星材料无发票怎么办 租房合同弄丢了怎么办 买房的合同丢了怎么办 押金的收据丢了怎么办 房东的合同掉了怎么办