首页 > Python基础教程 >
-
C#教程之C#图解教程
* 基础
1、virtual和new
- Virtual 关键字允许在派生类中重写这些对象,默认情况下,方法是非虚拟的,不可以重写非虚方法;
- virtual关键字不可以与static、abstract、private、override一起使用。
- Virtual关键字又是和override紧密不可分的,如果要实现Virtual方法就必须要使用override或new关键字(new和override产生的机理不同)。New和Override这两个关键字是互斥的。不可以同时使用;
- new : new关键字可以在派生类中隐藏基类的方法
- virtual: Override关键字主要是提供派生类对基类方法的新实现,重写的基类方法必须和Override的方法具有相同的签名,相同的访问修饰符
总结:New关键字主要用来区别派生类和基类同名方法的选择问题,通过隐藏基类方法,达到使编译器调用正确的方法的目的。Override主要用来对基类的方法和虚方法进行重写。
2、不用vs软件写代码
- 在notepad++ 中写代码,命名为.cs结尾的文件:My.cs
- 对源文件运行C#命令行编译器csc.exe ,编译(csc My.cs)→ 运行(My.exe)
- 打开命令行的方法:1、cmd中运行批处理文件【C:\Program Files (x86)\Microsoft Visual Studio\Preview\Enterprise\Common7\Tools\VsDevCmd.bat】,然后再转到d: 盘 csc My.cs ;
2、在windows→ 菜单→ 开始→ 程序→ VS菜单→ 命令提示符窗口
注: cmd中,d:转到d盘目录下, cd MyNote转到d盘的MyNote目录下
using System; namespace Wrox { public class My { static void Main() { Console.WriteLine("Hello form Wrox"); Console.ReadLine(); } } }
* net框架
- .NET框架由三部分组成。
1.CLR
* 内存管理和垃圾收集。
* 代码安全验证。
* 代码执行、线程管理及异常处理。
- .NET Framework的核心是运行库执行环境,称为(公共语言运行库CLR或.NET运行库),通过CLR控制下运行的代码称为托管代码
1.1 编译:
1. 将源代码编译为Microsoft中间语言(IL)【低级语言,数字代码,可快速转换为本地机器码】
2. CLR把IL编译为平台专用的代码
- 优点:
平台无关性:编译为中间语言可以获得.NET平台无关性。
提高性能:IL总是即时编译(称为JIT编译),只编译调用的那部分,代码编译过一次后,得到的本地可执行程序就存储起来,直到退出程序为止,下次运行着代码就不需要重新编译了。
托管IL代码几乎和本地机器代码的执行速度一样快,JIT编译器确切知道程序运行在什么类型的处理器上,可以利用该处理器提供的任何特性或特定的机器代码指令来优化最后
的可执行代码。
语言的互操作性:能将VB C# C++编译为中间语言,编译为中间语言的代码可以与其他语言编译过来的代码进行交互操作。
1.2 编译工具涵盖了编码和调试所需的一切,包括:
* Visual Studio集成开发环境IDE.
* .NET兼容的编译器(如:C#\ VB...).
* 调试器.
* 网站开发服务器技术,如ASP.NET 或WCF
BCL(base class library基类库),是.NET框架的一个大类库
C#编写的代码靠.NET Framework运行,结论:1.c#的体系结构和方法反映了.net基础方法论 2.多数情况下,c#特定语言功能取决于.NET的功能,或依赖于.NET基类。
2. 中间语言
2.1 特征
1. 面向对象和使用接口:带有类的单一继承性,
2. 不同的值类型和引用类型:值类型变量之间存储数据,引用类型变量仅存储地址,对应的数据在该地址中找
3. 强数据类型化
4. 使用异常来处理错误
5. 使用特性(attribute)
3.垃圾回收
- 内存泄漏:请求内存的代码必须显式通知系统它什么时候不再需要该内存,很容易被遗漏,从而导致内存泄漏;
- .NET垃圾回收期是一个程序,用来清理内存。所有动态请求的内存都分配到堆上,隔一段时间.NET检测到给定进程的托管堆已满,需要清理时,就调用垃圾回收器。垃圾回收器处理目前代码
中所有变量,检查对存储在托管堆上的对象的引用,没有引用的对象被删除。因此:不能保证什么时候会调用垃圾回收器:CLR决定需要它时就可以调用它
4. 应用程序域
- 减少运行应用程序的系统开销,同时需要与其他程序分离开来,但仍需要彼此通信。
- windows通过地址空间把进程分隔开来,每个进程有4GB的虚拟内存来存储其数据和可执行代码(4GB对应32位系统),每个进程都会有不同的映射,虚拟地址空间块映射的物理内存之间不重叠。
- 任何进程都只能通过制定虚拟内存中的一个地址来访问内存,即进程不能直接访问物理内存。
- 虚拟路径:相对路径, 物理路径:硬盘的绝对路径
5. 程序集
- 程序集assembly是包含编译好的、面向.NET Framework的代码的逻辑单元,可以存储在多个文件中(动态程序集存储在内存中);如果一个assembly存储在多个文件中,其中就会有一个包含入口点的
主文件,该文件描述了程序集中的其他文件。
- 可执行代码和库代码使用相同的程序集结果。但是可执行的程序集包含一个主程序的入口点;而库程序集不包含。
- 程序集的重要特征:包含的元数据描述了兑银代码中定义的类型和方法,程序集也包含描述程序集本身的元数据。
* C#概述
- 块:{语句1 ; 语句2;} 注意:{}后面没有分号
- Console.Write(" ");
* Console.WriteLine(" Two sample integers are {0} and {1} .", 3, 6); 从0开始替代标记、替代值
* Console.WriteLine("Three integers are {1} , {0}, {1}", 3, 6); 输出6, 3, 6 。注意标记位和标记值一一对应,标记位从0开始。
- 格式化字符串:
* Console.WriteLine(" The value: {0:C}.", 500); 格式化为货币,$500.00
* Console.WriteLine(" {0, 10} ", 500); 正数右对齐,左边补...
- 注释:
* 单行//, 多行 /**/, 文档注释 ///
1.数据类型
- 预定义类型16种:
- 自定义类型6种:
类(class)、结构(struct)、数组(array)、枚举(enum)、接口(interface)
2. 栈和堆:
* 栈:是一个内存数组(桶,LIFO先进后出,后进先出)
# 存储类型:某些类型变量的值、程序当前的执行环境、传递给方法的参数
# 栈的特征:只能从栈顶插入(push入栈),删除(pop出栈)
* 堆:是一块内存区域,可以分配大块的内存用来存储某类型的数据对象,可以随意插入和移除;当对象不再被使用时,CLR的GC会自动回收
- 值类型和引用类型
* 值类型:需要一段单独的内存,存储实际的数据,放在栈中
* 引用类型:需要两段内存。第一段存储实际的数据,放在堆中;第二段是一个引用,指向数据在堆中的存放的位置,放在栈中
* 总结:
简单情形:值类型数据放在栈中;引用类型,实际数据始终放在堆中,引用放在栈中
复杂情形:引用类型的数据始终放在堆中;值类型对象或引用类型的引用部分可以放在堆中,也可以放在栈中,依赖于实际环境。
在赋值的时候,值类型是复制一份,新的和旧的在以后的操作中互不影响,而引用类型复制的只是地址,在以后的修改中,修改新的旧的也会受到影响。
* 为数据分配内存:
ClassA a = new ClassA(); a只是用来保存引用分配在栈中,使用new才是给实际数据分配内存【new运算符为任意指定类型的实例分配内存并初始化内存】
3. 变量常量
变量类型 | 用途 | 存储位置 | 自动初始化 |
本地变量 | 在方法的作用域保存临时数据,不是类型成员 | 栈或堆和栈 | 否 |
字段 | 保存和类型或类型实例相关的数据,是类型成员 | 堆 | 是 |
参数 | 从一个方法到另一个方法传递数据的临时变量,不是类型的成员 | 栈 | 否 |
数组元素 | 同类数据项构成的有序集合的一个成员,可以为本地变量,也可以类型的成员 | 堆 | 类成员是,本地变量否 |
* 静态类型:变量的类型在编译的时候确定并且不能再运行时修改。
* dynamic:在编译时对dynamic类型的所有信息打包,在运行时,对这些信息进行检查,会抛出异常。
- var关键字(从等号右边推断出的实际类型的速记,并不改变C#的强类型性质)
* 只能用于本地变量,不能用于字段。
* 只能在变量声明中包含初始化时使用(即var n = 10;)
* 一旦编译器推断出变量的类型,它就是固定且不能更改。
- 常量: const double PI = 3.1415; 声明时初始化,在编译时确定类型,不能再赋值
- DateTime dt = DateTime.Now;
- 委托
namespace EventTest { /// <summary> /// 委托总结:委托是一种类型,和类是平级,因此不存在重载一说 /// 系统提供的委托: /// 无返回值:Action无参数无返回值,Action<string, int>有参数无返回值 /// 有返回值:Func<int, int>最后一个都是返回值 public class SmarizeDelegate { public void Test() { MyDel del = (x, y) => { return x + y; }; //lamda表达式 del(10, 20); MyDel2<int> del2 = (x, y) => x + y; //lamada表达式带return就要带{},不带return就可以不带{} del(10, 20); M1((x, y) => (x + y).ToString()); //Func有返回值委托,传入两个int,返回一个string Func<string, string, string> fn = M2(); //调用委托作为返回值的 fn("你好", "徐攀"); } static void M1(Func<int, int, string> fn) //委托作为方法参数类型 { Console.WriteLine(fn(10, 20)); } static Func<string, string, string> M2() //委托作为方法返回值 { return new Func<string, string, string>((x,y) => x+y); } } public delegate int MyDel(int x, int y); //基本委托 public delegate T MyDel2<T>(T t1, T t2); //泛型委托 }