C#基础知识简单梳理
本文是一个菜鸟所写,本文面向的人群就是像我这样的小菜鸟,工作一年也辛辛苦苦学习了一年,一直没有机会梳理一下自己的知识,最近花了一些时间整理了一些C#基础知识,也算是对过去的一年做个回顾把~文章有点长,请自带瓜子和茶吧,请看下面C#基础知识简单架构图,不可能100%的全面,请见谅啊... http://pic002.cnblogs.com/images/2012/322864/2012070814470737.png1.值类型和引用类型 1.1堆和栈 简单的说值类型存放在堆栈上面,引用类型的数据存放在托管堆上面(它的引用地址却存放在堆栈上面)! 栈:它是一个内存数组,是一个先进后出的数据结构! 栈的特征:数据只能从栈顶进,从栈顶出! 堆:它是一个内存区域,可以分配大块区域存储某类型的数据,与栈不同的是它里面的数据可以任意排序和移除! 下面是园子的一张图,贴上来供大家参考啊!问 题值类型引 用 类 型
这个类型分配在哪里?分配在栈上分配在托管堆上
变量是怎么表示的?值类型变量是局部复制引用类型变量指向被分配得实例所占的内存
基类型是什么?必须继承自System.ValueType可以继承自除了System.ValueType以外的任何类型,只要那个类型不是sealed的
这个类型能作为其他类型的基类吗?不能。值类型是密封的,不能被继承是的。如果这个类型不是密封的,它可以作为其他类型的基类
默认的参数传递是什么?变量是按值传递的(也就是,一个变量的副本被传入被调用的函数)变量是按引用传递(例如,变量的地址传入被调用的函数)
这个类型能重写System.Object.Finalize()吗?不能。值类型不好放在堆上,因此不需要被终结。可以间接地重写
我可以为这个类型定义构造函数吗?是的,但是默认的构造函数被保留(也就是自定义构造函数必须全部带有参数)当然!
这个类型的变量什么时候消亡?当它们越出定义的作用域时。当托管堆被垃圾回收时。
1.2装箱和拆箱 关于装箱和拆箱是一个老生常谈的话题,也有很多文章来分析它,如:1. 6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱 2. 值类型的装箱与拆箱浅析 3. 深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别 http://pic002.cnblogs.com/images/2012/322864/2012070815055685.png 这类的文章真的多了,再总结就没多大的意义了,看的时候多写写代码,多想想,就会明白的!2.接口,抽象类,封装,继承,多态 接口和抽象类这两个概念还真不容易理解,有的时候理解一半,换一种方法考考你,你就会晕,到现在说实话我还没完全懂,一直没有把握它们的精髓,最近在看<<你必须知道的.NET>>,这是第二次看,收获很多...大家还是有时间多看看<<你必须知道的.NET>>,这本书可以说是很详细的讲解了OO思想,还有看看设计模式的书,多想多练,可以时间会长一点,不过总有一点我们会开窍的... 这种东西不是通过总结一下就能熟练运用的,不过你起码要有一点面向对象的思想,要想有这种思想必须学习前辈留下的知识总结,这种才能理论结合实践,才能深入的了解OO思想 推荐文章:细细品味C#——抽象、接口、委托、反射(感谢虾皮老师啊...)3.迭代器 主要是对foreach的深入理解,以及对两个接口的深入剖析(包括它们的泛型结构):IEnumerable(可枚举类型),IEnumertor(可枚举数),文章入口:使用IEnumerable和IEnumerator接口,从yield关键字看IEnumerable和Collection的区别4.泛型 泛型保证了类型安全,避免了装箱和拆箱的操作,提高了性能,可复用性也得到了很大的提高,下面就来说说基本的泛型语法吧! 项目中对于泛型和委托的结合运用也很多见,很多人不是为了语法而学习,而是泛型的扩展性让我们必须要知道它,把它实实在在的运用到项目中去,提高扩展性... 泛型语法不是很复杂,包括定义泛型类型,泛型方法,指定泛型约束,还有泛型约束包括只包括哪些类型等等,这些语法只要花些时间就能明白了,难的是一种思想,o(︶︿︶)o 我还很菜啊... 推荐文章:细细品味C#——泛型系列专题(虾皮帮我们已经整理关于泛型的精彩文章,看完之后会有很多的收获)5.集合 5.1一般集合 .NET Frameword中关于集合的类存储在System.Collections命名空间下,其实一开始学习的时候感觉集合这个东西很神秘,能动态增加,删除,选择数据(比数据好用多了),可是在学习之后,它的神秘感也随之消息,因为集合的底层代码跟数组有着密切联系的,请看:学习之路二:关于集合和数组内在联系的深入了解(里面也有个链接,可以点击学习)! 下面是非泛型集合类之间的关系图: http://pic002.cnblogs.com/images/2012/322864/2012071019374089.png 5.2泛型集合自从.NET Framework引用泛型概念之后,它在C#编程方面掀起了一个泛型热潮,泛型实在太好用了,不仅是类型安全,可扩展性,重要的是在性能方面有了显著提高,这让我们苦逼的程序猿看到了曙光,哈哈... 泛型集合类存储在System.Collections.Generic以及System.Collections.ObjectModel命名空间下,下面是集合类之间的关系图: http://pic002.cnblogs.com/images/2012/322864/2012071019380191.png 推荐文章:细细品味C#——泛型系列专题(有个pdf文件,下载下来回家慢慢看,同志们)6.反射 反射这东西两面性很极端,很多人说它的坏,也有很它在某些方面有着重大的作用,下图是关于类型反射所需要用到的类之间的关系图:http://pic002.cnblogs.com/images/2012/322864/2012071213334429.png 除了类型反射之外,还有一种是程序集的反射,功能比较强大,可是我对它的研究比较少,我就推荐几篇好文章把(下面几篇文章我也正在学习中)... 推荐文章 : 1..Net 中的反射(序章) - Part.1
2..Net 中的反射(查看基本类型信息) - Part.2
3..Net 中的反射(反射特性) - Part.3
4..Net中的反射(动态创建类型实例) - Part.47.特性(Attribute) 特性这个东西,在面向对象编程中有着非常重要的最用,在架构设计框架的时候,考虑使用特性的几率会非常的大! 特性结合反射技术就可以实现依赖注入,以前看到公司一个项目在写测试代码的时候,总是给每个方法加上的特性,当方法结束后,所有数据库的操作都将会回滚,我很费解,因为RollBack是自己定义的,怎么就一加上这个特性就自动完成回滚了! 下面就是完整的Rollback代码,可是我在使用它的时候遇到一个问题 ,就是它只可以用于单元测试,我尝试着把它用于一般的方法当中,可是一直没有实现回滚功能,我感到很费解,有兴趣的朋友可以帮我看看...http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifView Code
只能在单元测试里面进行调用: http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
1 2 public class ProgramTest : TestFixture//继承这个类 3 {48 49 //添加这个RollBack特性,就能实现回滚了50 public void MyTestTest()51 {52 SqlConnectionStringBuilder connectionString = new SqlConnectionStringBuilder53 {54 DataSource = @"LBDZ-20120514VC\SQLEXPRESS",55 InitialCatalog = "My",56 };57 connectionString.IntegratedSecurity = true;58 59 using (SqlConnection conn = new SqlConnection(connectionString.ToString()))60 {61 conn.Open();62 SqlCommand cmd = conn.CreateCommand();63 cmd.CommandText = "INSERT INTO dbo.MyTable ( id) VALUES ( 6666 )";64 cmd.ExecuteNonQuery();65 Console.WriteLine("OK");66 } 68 Assert.IsTrue(true);69 }70 }http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
Question:这个RollBack我至今还没有弄懂它怎么来实现的,如果那个园友能看懂的话,可以私信给我或留言给我,我会打心里感谢你的,可能会涉及到AOP和IOC的知识,希望大家帮帮我把,纠结了很长时间啦... 推荐文章: 1. 关于C# 中的Attribute 特性 2. C# 用Attribute实现AOP事务 3. Attribute在.net编程中的应用(一) 8.委托和事件 其实把理解事件跟字段和属性联系起来,虽然这样说可能会不严谨点,但是从一些大的方面讲事件就是对委托的封装,类似于属性对字段的封装,这种说法还是行得通的! 想要定义一个完整的委托和事件,需要经历一下步骤(需要注意一些命名规范): ① 定义事件 → 委托使用微软提供的EventHadler<TEventArgs>泛型委托,一般都会有两个参数:A) “object sender”定义的事件依附的对象,也就是事件定义在那个类中,那么这个参数就为这个类的实例化对象,一般都会用“This”!B) “EventArgs e”也就是用于传递一些参数信息的对象,也可以使用自己定制的参数了② 创建参数类 → 如果有必要定制的数据参数类(这个类似于创建自己的实体类用来传递信息),这个参数类应该继承于EventArgs这个类!③ 执行事件 → 其实在执行事件的时候还是有一定的规范的,比如方法名必须为“On+事件名”,还有在执行事件要判断下时候为null,,然后在调用!④ 注册事件 → 调用事件(在传递事件对象的时候最好用“this”关键字)⑤ 依附事件的方法 → 最后定义依附在这个事件中的方法,也就是执行这个事件的方法体,深入了解,其实依附事件中的方法其实都最终依附在事件衣服的委托中,这个委托会生成一个委托实例,以及一个委托链!委托和事件定义语法:委托: 访问修饰符 + delegate + 返回值类型 + 委托名(参数列表); 事件: 访问修饰符 + event + 委托名 + 事件名;委托和事件跟观察者模式联系比较密切,可是我还是没有理解它的精髓,可能是我还太菜了...总结:灵活运用事件和委托将会给你的程序带来更好的扩展性,这需要丰富经验的积累,好了推荐几篇我曾经学习过的文章把!推荐文章:1. 庖丁解牛——深入解析委托和事件 2. C# 中的委托和事件 3. C#中的委托和事件(续)9.线程 对于线程学习过,可是一直没有做过多线程的项目,一直没有领悟到它的精髓,也只能停留在表面的高度! 我就想说下Thread中的后台线程和前台线程(默认为“前台线程”),在这里总结下(其实我也是学习前辈们的知识)。 前台线程:当所有的前台的线程都执行完毕以后才会退出程序! 后台线程:对于后台线程,程序是不管你是否是执行完成的,不过当你程序一旦强制退出,后台线程也会终止的!http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
1 Thread thread = new Thread(delegate()2 {3 Console.WriteLine("线程开始工作");4 Thread.Sleep(2000); //暂停两秒钟5 Console.WriteLine("线程结束");6 });7 thread.IsBackground = true; //分别设置为true和false,看看控制台运行的情况,我相信你能很快明白的8 thread.Start();9 Console.WriteLine("主线程结束");http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
总结:设置为后台线程相当于我们说的异步,而前台线程就相当于同步,执行好线程在执行主程序! 能够熟练使用多线程,还是要在项目中不断的实践,可是项目是可遇而不可求的东西,现在我的项目是肯定要不到了,只能自己看看文章,熟悉熟悉知识啊... 推荐文章: 1. C# 温故而知新: 线程篇(一) 2. C# 温故而知新: 线程篇(二) 3. C#综合揭秘——细说多线程(上)10.六种异步方式 10.1 委托异步模型 使用的是委托的BeginInvoke和EndInvoke异步执行模式! 必须要有两个条件: ① 必须要有个委托作为寄宿体 ② 执行函数 ExecuteFunction ③ 回调函数 CallBackFunction ,所谓的回调函数就是获取执行函数的返回值! 有了上面三种条件之后,就可以直接调用Begin和End进行委托异步编程了,其中还有细节问题需要注意,下面我们就一一来看! 具体思路步骤: ① 选择一个适合的委托类型,如参数列表,返回值类型 ② 创建一个执行函数,必须跟委托的参数列表和返回值类型对应起来 ③ 创建一个回调函数,它只有一个参数没有返回值,参数类型为IAsyncResult类型,这是使用委托实现异步的规范写法,不可改变 代码实现:http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
1 //写一段简洁的代码 2 private void button1_Click(object sender, EventArgs e) 3 { 4 //定义委托,并指定异步的执行方法 5 Func<string, string> func = new Func<string, string>(ExecuteFunction); 6
14.4 关于注释(书中讲到的注释规则让我很有同感,因为现在项目中就有这样的现象) 请注意:注释也许真的不需要,学会使用代码就能完整表达设计和逻辑意图! 常见现象:代码在变动,在演化,彼此分离和重合,可是注释并不总是随着变动,上图: http://pic002.cnblogs.com/images/2012/322864/2012070718363882.png 所以只有代码才能真正的告诉你它在干什么,它有什么作用! http://pic002.cnblogs.com/images/2012/322864/2012070718382963.png Note:与其花时间编写解释你那糟糕代码的注释,还不如花时间清洁那糟糕的代码! 坏注释和多余注释的几点原则: ①有时候一段坏的注释不紧会影响代码的整洁,而且还会占用一定的时间,最终读注释的时间比阅读代码的时间还长,所以这种注释要删除它,影响我们阅读代码的时间 ②日志式注释:这种注释最有感触,在class开头写上每次修改的记录,这种方式也有好处,但是这种情况应该在没有源代码控制的情况下进行记录(其实我听赞同在class头上写上每次修改的版本的) ③关于废话性和误导性的注释坚决不能存在 ④能用函数和变量是就别用注释,所以变量和函数的命名真的很重要,可以让人一眼就能看出它的作用 请明白非常重要的一点:注释的作用就是解释未能自行解释的代码,如果注释本身还需要解释,就太遗憾了! 14.5 单元测试的重要性 一直觉得单元测试可有可无,那是因为我只是学习过从来没有真正的在项目中运用过,可是最近我下了狠心要在项目中构建一个单元测试框架,终于被我搞定了,我也感悟到单元测试对一个开发人员的重要性,想学习的话可以看看这篇文章:走进单元测试五:单元测试文章系列目录 建议大家看看<<代码整洁之道>>和<<.NET设计规范>>以及<<程序猿修炼之道之单元测试>>15.其它知识点 15.1 const和readonly本质区别 理解两者是在“编译时”还是“运行时”常量,以及两者的作用域,那么它们将不会这么神秘! 编译时OR运行时: const:编译时 readonly:运行时 作用域: const:①本身就是静态变量 ②只能定义基本类型,如int,string等等 ③局部变量和全局变量都可以定义 ④一旦定义就不能修改 readonly:①不是静态变量,如果需要需加上“static”关键字 ②可以定义一切类型,可以是自己自定义的对象 ③只能定义全局变量 ④一旦定义可以在构造函数里面进行初始化变量 总结:园子里面还有很多对于它们性能方面的文章,有兴趣的可以搜搜看,推荐使用“readonly”吧! 15.2 is和as操作符 16.2.1 As和强制转化最本质的区别 As:进行转换的时候永远不是出现异常,当转换失败时会返回一个“null”值,所以你只需要进行一个null值的判断就知道转换失败还是成功了! 强制转化:会出现转换失败并抛出异常,所以我们都需要使用“try/catch”来捕获转换出错的异常,也可以使用“is”来判断是否是你要转换的类型! 16.2.2 一些常见注意点 ① as不能用于值类型的转化 如:object number=100;int numberOne = number as int; 这是因为如果转换失败,那么就会返回一个“null”值,但是值类型是不允许为“null”的,所以在语法上是行不通的,就是你写成了“int?”也是不行的! ② 使用Is配合强制转换来进行类型转换 首先使用“Is”来判断是否是我需要转换的类型,然后在进行强制转换http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifView Code
③ 在没有泛型的foreach中,也是把“object”进行强制转化成所需要的类型,代码如下:http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifView Code
Note:或者使用GetType()方法来精确检测是否是你想要的转换类型! 15.3 运算符操作以及类型转化操作重载这两个知识点还是比较容易学习的,一个是操作符的重载,一个是用于自定义强制转换的方法(你也可以使用“as”进行强制转换),只要稍加注意一些语法就好了!
http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
1 public class MyPerson 2 { 3 public string Name { get; set; } 45 /* 6 *①必须为静态 7 *②关键字operator 8 *③需要定义重载的操作符 9 *④定义返回值类型10 */11 public static MyPerson operator +(MyPerson personFather, MyPerson personMother)12 {13 return new MyPerson() { Name = personFather.Name + personMother.Name };14 }15 16 /*17 ①必须为静态18 *②关键字“explict”和operator”19 *③需要转化的类型:MyPerson20 */21 public static explicit operator MyPerson(MyPeople myPeople)22 {23 return new MyPerson(){ Name="YCG" };24 }25 }26 public class MyPeople27 { }http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
具体的用法如下:http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
1 MyPerson personOne = new MyPerson() { Name = "AAAAAA" };2 MyPerson personTwo = new MyPerson() { Name = "BBBBB" };3 MyPerson personThree = personOne + personTwo;//操作符重载4 Console.WriteLine(personThree.Name);5 6 MyPeople people = new MyPeople() { Name = "wang wei" };7 MyPerson personFour = (MyPerson)people; //类型强制转换8 Console.WriteLine(personFour.Name);http://common.cnblogs.com/images/copycode.gif
http://common.cnblogs.com/images/copycode.gif
15.4 ToString方法 入口: c# 扩展方法奇思妙用高级篇五:ToString(string format) 扩展 15.5 数据实体模型(Tuple)以及匿名类型 16.5.1 Tuple实际上就是一个匿名的实体的模型,它的用处在于不要自己定义一个实实在在的Entity,使用它就能达到效果!http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifView Code
Note:在查看源代码的时候注意它的第八个参数: http://pic002.cnblogs.com/images/2012/322864/2012070813032290.png 16.5.2 匿名类型1 var data = new { number = 11111, str = "ssssss" };//不需要定义变量的类型,如果想知道匿名类型底层源码怎么写的,可以使用反编译查看源码,一目了然了!2 Console.WriteLine(data.number + data.str);
15.6 String和StringBuilder详解 这个技术大妞们已经讨论的很多,我也没这个能力说的一清二楚,推荐几篇文章吧:1. 字符串的驻留(String Interning) 2. 深入理解string和如何高效地使用string 等等,实在很多啦...17.Remoting 传送门:.NET Remoting技术文章汇总,看过那些文章,对于Remoting的理解会有一个质的上升...
页:
[1]