C# Primer 小记

章二:C#基础

1、还可以单独使用if语句,不加else语句。也可以合并else if子句,测试多个条件

 

2case无内容贯穿不需要goto

 

3default:后也需要break

 

4goto语句有两个限制,不能跳转到像for循环这样的代码块中,也不能跳出类的范围,不能退出try...catch块后面的finally

 

5、可以获取枚举的字符串表示(从字符串获取枚举值)

 

6、数组:

             int[] intArry1, intArry2;

         intArry1 = new int[32];

         intArry1[0] = 10;

         intArry2 = intArry1;

         intArry1[0] = 11;

         Console.WriteLine("{0} {1}", intArry2[0], intArry2[1], intArry2.length);

         Console.ReadLine();

        //intArry2[0]的值为11String的特性只针对String

        //对于intArry2[1]的引用不会引起编译器错误,intArry2[1]的值被初始化为0

 

7using语句的另一用途是定义命名空间的别名

 

8、必须把#define#undef命令放在C#源代码的开头,在声明要编译的任何对象的代码之前

 

9#if#elif还支持一组逻辑运算符!==!=||。如果符号存在就被认为是true,否则为false

 

10、标识符支持Unicode字符

 

章三:对象和类型

 

1、构造函数必须与所属的类同名,且不能有返回类型

 

2、两个方法不能仅根据参数是声明为ref还是out来及返回值类型来区分签名

 

3、如果提供了带参数的构造函数,编译器就不会自动提供默认的构造函数,只有在没有定义任何构造函数时,编译器才会自动提供默认的构造函数

 

4、编写静态构造函数的一个原因是,类有一些静态字段或属性,需要在第一次使用类之前,从外部源中初始化这些静态字段和属性;

   .NET运行库没有确保静态构造函数什么时候执行,所以不要求在某个特定时刻(例如,加载程序集时)执行的代码放在静态构造函数中,也不能预计不同类的静态构造函数按什么顺序执行。但是可以确保静态构造函数至多执行一次,即在代码引用类之前执行。在C#中静态构造函数通常在第一次调用类的成员之前执行;

   注意静态构造函数没有访问修饰符,其它C#代码从不调用它,但在加载类时,总是由.NET运行库调用它,所以像publicprivate这样的访问修饰符号就没有意义了。同样静态构造函数不能带任何参数,一个类也只能有一个静态构造函数,很显然,静态构造函数只能访问类的静态成员,不能访问实例成员;

   注意,无参数的实例构造函数可以在类中与静态构造函数安全共存,尽管参数列表是相同的,但这并不矛盾,因为静态构造函数是在加载类时执行,而实例构造函数是在创建实例时执行,所以构造函数的执行不会有冲突;

   如果多个类都有静态构造函数,先执行哪个静态构造函数是不确定的。此时静态构造函数中的代码不应该依赖其他静态构造函数的执行情况。另一方面,如果静态字段有默认值,它们在调用静态构造函数之前指定;

 

5、构造初始化器(符)

 

6readonly关键字比const灵活得多,允许把一个字段设置为常量,但可以执行一些运算,以确定它的初始值。其规则是可以在构造函数中给只读字段赋值,但不能在其它地方赋值。只读字段还可以是一个实例字段,而不是静态字段,类的每个实例可以有不同的值。与const字段不同,如果要把只读字段设为静态,就必须显式声明;

 

7、结构有默认的初始化构造函数,但要通过new触发;结构不能包含显示的无参数构造函数,编译器总是提供一个无参数的默认构造函数,这是不允许被替换的

 

8、静态类,如果一个类只包含静态方法和属性,该类就是静态的,此外还可以为类定义加上static关键字,这样编译器可以检查以后是否给该类添加了实例成员,如果是,就生成一个编译错误,这可以确保不创建静态类的实例

 

章四:继承

 

1、继承有两种:实现继承和接口继承,C++支持实现继承,VB6支持接口继承,而C#两种都支持,在实现继承方面,C#没有C++中的多重继承和公有私有继承机制

 

2、在类定义中没有指定基类,C#编译器就假定System.Object是基类

 

3、属性也可以声明为Virtual的,构造函数、成员字段、静态函数不能声明为Virtual的,虚拟的概念只对类中的实例函数成员有意义

 

4、如果签名相同的方法在基类和派生类中都进行了声明,但该方法没有声明为VirtualOverride,派生类方法就会隐藏其基类方法,在这种情况下编译器会给出一个警告,这种警告可以在派生类的同名函数前使用new关键消除

 

5、方法也可以声明为sealed的,sealed关键定为方法提供了一种方式,可以确保为方法提供的重写代码是最终代码,其他人不能再重写它

 

6、构造函数的调用顺序是先调用System.Object,再按层次由上向下进行,直到到达编译器要实例化的类为止,还要注意在这个过程中,每个构造函数都初始化它自已的类中的字段,这是它的一般工作方式,在开始添加自已的构造函数时,也应尽可能遵循这个规则。实际上如果派生类的构造函数没有使用“:base(...)”关键字指定了某个基类构造的显示调用语法,则编译器自动为派生类构造加上调用基类默认构造的隐式语法“:base()”。即如果编译器没有在派生类构造的起始花括号前找到对(如果有this(...)则仍按从上向下顺序,相当于“:this(...)base(...)”基类构造函数的引用,它就会假定我们要调用基类构造函数--这符合默认构造函数的工作方式。

 

7、在继承的层次结构中,要注意,在某些情况下如果父类用带private关键字的无参构造函数来代替默认的构造函数,将得到一个编译错误,提示构造不可访问,即使你没有实例化子类

 

8C#中有五种可见性修饰符:publicprotectedprivateinternalprotected internal。其中,internalprotected internalC#.NET Framework新增的。internalpublic类似,但访问仅限于同一个程序集中的其他代码,换言之,在同一个程序中同时编译的代码。使用internal可以确保编写的其他类都能访问某一成员,但同时其他公司编写的其他代码不能访问它们。protected internal合并了protectedinternal,这是一同OR合并,即protected internal成员在同一个程序集的任何代码中都可见,在派生类中也可见,甚至在其他程序集中也可见。不能把类定义为protectedprivateprotected internal,否则将出现编译错误,因为这些修饰符对于包含在名字空间中的类型来说是没有意义的。因为这些修饰符号只能应用于成员。但是,可以用这些修饰符定义嵌套类型,因为在这种情况下,类型也具有成员的状态。

 

9、一般情况下,接口中只能包含方法、属性、索引器和事件的声明。不能实例化接口(但可以new出新口数组:ISaveAccount[] isarray = new ISaveAccount[2]),它只能包含其成员的签名。接口不能有构造函数或字段。接口定义也不允许包含运算符重载。在接口定义中还不允许声明成员上的修饰符。接口成员总是public的,不能声明为virtualstatic

 

章五:数组

 

1int[] iArray = new int[3]{2, 3, 4} 花括号被称为数组初始化器,数组初始化器只能在声明数组变量时使用,不能在声明数组之后使用,哪果用花括号初始化数组,还可以不指定数组的大小 int[] iArray = new int[]{2, 3, 4} 编译器会自动计算,使用C#编译器还有一种更简化的形式 int[] iArray = {2, 3, 4}

 

2、分清数组维数和每一维长度(上下界)的区别;

 

3、用括号声明数组是C#中使用Array类的记号,在后台使用C#语法,会创建一个派生于基础Array的新类。这样,就可以使用Array类为每个C#数组定义的方法和属性了。例如Length属性,还可以使用foreach语句迭代数组,其实这是使用了Array类中的GetEnumerator()方法,或者说在Array类中实现了枚举器。

 

4Array类是一个抽象类,不能使用构造函数来创建数组,但除了可以使用C#语法创建数组实例外,还可以使用它的CreateInstance()静态方法创建数组,如果事先不知道元素类型,或者想创建索引不基于0的数组,就可以使用改静态方法。

 

5、数组是引用类型,所以将一个数组赋予另一个数组变量,就会得到两个指向同一个数组的变量。而复制数组实现ICloneable接口。这个接口定义的Clone()方法会创建(无需创建新数组则使用CopyTo方法或Array.Copy())一个数组的浅副本,也就是说,如果数组元素是值类型,就会复制所有的值,如果数组包含的是引用类型,则不复制元素本身,而只是复制引用。如果需要包含引用类型的数组的深副本,就必须迭代数组,创建新对象。

 

6Array类实现了对数组中元素的冒泡排序。Sort()方法需要数组中的元素实现IComparable接口。简单类型,如StringInt32实现了IComparable接口(升序)。调用语法为Array.Sort(...)

 

7、类对象如果需要在数组或集合中能够被排序,就必须实现ICompable接口,这个接口定义了一个方法CompareTo();但如果排序的方式比较复杂,如需要对哪个字段进行排序,是升序还是降序,或者不能修改类的定义,则可以针对该类定义一个IComparer接口,在调用数组或集合的Sort()方法时执行它,IComparer接口定义了Compare()方法。

 

8Array类实现了IEumerableICollectionIList接口,ICollection接口派生于IEnumerableIList派生于ICollection

 

9、搞不太懂的yield

 

章七:内存管理和指针

 

1、堆栈:从高往低分配,从低向高存储;堆:从低往高分配,从低向高存储

 

2、垃圾收集器不知道如何释放非托管资源(例如文件句柄、网络连接和数据库连接)。托管类在封装对未托管资源的直接或间接引用时,需要制定专门的规则,确保未托管的资源在回收类的一个实例时释放。有两种机制处理未托管资源的释放:实现System.IDisposable接口,和为类定义一个析构函数,两者的区别在于:

 

1、调用方式不同:Dispose()由用户调用,为确定调用,而析构函数由垃圾收集器调用,为不确定调用

 

       //2Dispose()中可以处理托管和非托管资源的释放,析构中只能处理非托管资源(在调       析之前,垃圾收集器可以已经释放了托管资       源)的释放

 

章七:委托和事件

 

1、实际上,“定义一个委托”是指“定义一个新类”。委托实现为派生于基类System.MulticastDelegate的类,System.MulticastDelegate又派生于基类System.DelegateC#编译器知识这个类,会使用其委托语法。因为委托基本上是定义一个新类,所以可以在定义类的任何地方定义委托,既可以在另一个类的内部定义,也可以在任何类的外部定义,还可以在命名空间中把委托定义为顶层对象。根据定义的可见性,可以在委托定义上添加一般性的访问修饰符:publicprivate、和protected

 

2、在术语方面,类有两个不同的术语:“类”表示较为广义的定义,“对象”表示类的实例。但委托只是一个术语。在创建委托的实例时,所创建的委托的仍称为委托。必须从上下文中确定委托的确切含义。

 

3、给定委托的实例可以表示任何类型对象上的实例方法或静态方法-只要方法的签名匹配于委托的签名即可

 

4、委托推断:GetAString firMethod = new GetAString(i.ToString) 等效于 GetAString firMethod = i.ToString

 

5、使用匿名方法定义委托

 

6、多播委托:

1、可以使用+=为一个委托实例添加多个方法,或者说一个委托实例可以存储多个方法的引用,因为System.MulicastDelegate的实例成员允许把多个方法调用链接在一起,成为一个列表;

 

2、如果调用多播委托实例,就会自动连续调用其存储的多个方法,为此,这些方法的返回值应为void,否则就只能    得到委托调用的最后一个方法的返回值;

 

3、应注意对同一个委托调用方法链的顺序并未正式定义,因此应避免编写依赖于以特定顺序调用方法的代码;

 

4、多播委托实例包含了一个逐个调用的委托实合,如果通过委托调用的一个方法抛出了异常,整个迭代就会停止,解决办法就通过Delegate类定义的GetInvocationList()方法返回一个Delegate对象数组,来逐一手工迭代;

 

7事件(略)

 

 

章八:字符串和正则表达式

 

1、如果多次修改一个字符串,例如,在显示字符串或将其传递给其他方法或应用程序前,创建一个较长的字符串,String类就会变得效率低下。对于这种情况,应使用另一个类System.Text.StringBuilder,因为它是专门为这种情况设计的。

 

2、哪果要使类的友好性比较高,就需要使用某些工具以用户希望的方法显示它们的字符串表示。.NET运行库定义了一种标准方法:使用接口IFormattableIFormattable只定义了一个方法,该方法也叫作ToString(),它带有两个参数,这与System.Object版本的ToString不同,它不带参数,下面是IFormattable的定义

 

       interface IFormattable

       {

              string ToString(string format, IFormatProvider formatProvider);

       }

 

3、正则表达式Regex

 

章十三:错误和异常

 

1

try块包含的代码组成了程序的正常操作部分,但这部分的程序可能遇到某些严重的错误。

 

catch块包含的代码处理各种错误,这些错误是try块中的代码执行时遇到的。这个块还可以用于记录错误。

      

finally块包含的代码清理资源或执行在try块或catch块末尾执行的其他操作。无论是否产生异常,都会执行

finally块,理解这一点是非常重要的。因为finally块包含了应总是执行的清理代码,如果在finally块中放置return语句,编译器就会标记一个错误(catch中可以放置return语句,需要注意的是即使catch中放置了return语句,finally中的代码仍然会被执行)。例如,可以在finally块中关闭try块中打开的连接。finally块是可选的。如果不需要清理代码(例如删除对象或关闭已打开的对象),就不需要包含此块。

 

2、一般catch块与catch(Exception)是不太一样的,通常一般catch块处理的是其他没有用C#编写的代码(甚至根本不是托管代码)抛出的异常。在C#语言中,只有派生于System.Exception的类的实例,才能作为异常来抛出。但其他语言没有这个限制,例如C++允许把变量作为异常来抛出。如果代码调用了其他语言编写的库或程序集,抛出的异常就可能不是派生于System.Exception。但在许多情况下,.NET PInvoke机制会捕获这些异常,把它们转换为.NET Exception对象。

 

章十九:.NET数据访问

 

ADO.NET附带了四个数据库客户命名空间,一个用于SQL Server,另一个用于Oracle,第3个用于ODBC数据源,第四个用于OLEBC实现的数据库。如果数据库不是SQL ServerOracle,就应使用OLE DB,除非还能使用ODBCADO.NET类最重要的特性是:它们是以断开连接的方式工作,这在目前以Web为中心的环境中是非常重要的。我们常常把服务(例如在线书店)构建为连接一个服务器,检索一些数据,再在客户机上处理这些数据,之后重新连接服务器,把数据传送回去,进行处理。ADO.NET的断开连接的本质就可以实现这种操作。

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值