.NET框架,CLR和C#之间的关系。
.NET是一个独立发布的软件包,包括CLR,类库 和相关语言编译器
C#代码 经编译后 在CLR环境运行
不同.NET版本的比较:
.NET3/3.5只是扩展了WF、WPF、WCF、WCS组件,没有更新C#编译器,CLR版本是2.0。
C、C++程序员在上世纪90年代,使用win32 API ,多数使用MFC(微软基础类库),一些人转向COM(组件对象模型)。
但是都有一些缺点:Win32 API不是面向对象的,使用比MFC复杂。
MFC虽然是面向对象的,但不一致
COM概念简单,但代码复杂
当时,windows开发主要针对桌面应用。
2002年微软发布.NET框架,比MFC和COM更一致,更面向对象。
.NET的特点:
多平台:可用于开发 服务器程序,桌面程序,PDA,移动电话程序。
行业标准:支持多种通信协议,XML,HTTP,SOAP,WSDL
安全: 相对安全了些
C#/VB代码==(编译)==>CIL (中间语言)===>机器语言==>CLR执行环境
.NET框架有自动回收垃圾功能,像java。C#的程序可以调用VB的类,前提要遵循一定的规则。.NET框架下的代码页可以调用Win32 DLL导出的纯C函数的代码,如Windows API(非NET)。不需要用COM组件!不需要使用注册表。有并行执行的特性。
从VS2010的安装文件夹找到Visual Studo命令行。【直接cmd进入命令行不识别csc等命令】 csc /?获得更多帮助
要首先切换到项目文件所在路径
生成可执行文件!
参数类型 |
修饰符 |
是否在 声明时使用 |
是否在 调用时使用 |
执行 |
值 |
没有 |
系统把实参的值复制到形参。在函数返回后,形参一同从栈中弹出 |
||
引用 |
ref |
是 |
是 |
形参是实参的别名 |
输出 |
out |
是 |
是 |
形参是实参的别名 |
数组 |
params |
是 |
否 |
允许传递可变目录的实参列表,编译器需要在堆中重新构建数组;也可以传递一个数组,不需要重建数组 |
数据成员 |
函数成员(执行代码) |
字段 常量 |
方法 属性 构造函数 Finalizer方法 运算符 索引 事件 |
类成员修饰符顺序: [ 特性 ] [ 修饰符 ] 核心声明
修饰符有:pulic private static const(针对字段声明) 核心声明如: int x, void fun(int x) |
|
类成员又可分为: 实例类成员:每个实例拥有各个类成员的copy 静态类成员:可被类的所有实例共享,即使没有实例也存在可以访问
其中可以声明为静态的类成员有:字段、方法、属性、构造函数、运算符、事件 注意:其他,常量、Finalizer方法、索引不可声明为静态 |
有关调用参数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CSharp_Call
{
class MyClass1
{
public int add(int x, int y)
{
return x + y;
}
//static属性的方法只能被本类的对象调用
static int minus(int x, int y)
{
return x - y;
}
public void fun1(ref MyClass2 a, ref int b)
{
a.val = 24;
b = 29;
}
public void fun2(out MyClass2 a, out int b)
{
//输出类型 参数,必须在函数调用之前初始化(与ref引用类型参数不同的地方),否则报错
a = new MyClass2();
a.val = 99;
b = 100;
}
//数组参数作为形参:定义用用关键字params,调用时不用关键字。在一个参数列表最多只有一个数组参数,且放在其他参数的后面,数值类型后面要有[]
public void displaylist(params int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine("{0} ", arr[i]);
}
//也可以采用如下方式循环输出
/*
foreach (int elem in arr)
{
Console.WriteLine("{0} ", elem);
}
* */
}
}
class MyClass2
{
public int val = 20;
}
class MyClass3
{
}
class Program
{
static void Main(string[] args)
{
MyClass1 myobject = new MyClass1();
int x = 3, y = 4;
//值 参数的传递,复制一份实参到形参
Console.WriteLine("{0}+{1}={2}", x, y, myobject.add(x, y)); //在Program类中调用MyClass类的函数时,必须声明MyClass的对象来调用
MyClass2 myobj2 = new MyClass2();
//直接调用另一个的属性,由于是复杂数据类型,栈中存放只是对象在堆中的引用
Console.WriteLine("{0}", myobj2.val);
//引用类型参数,函数定义和调用时都加上关键字ref,形参是实参的别名,指向相同内存单元
myobject.fun1(ref myobj2, ref x);
Console.WriteLine("{0},{1}", myobj2.val, x);
//输出类型参数,函数定义和调用时都加上关键字out,形参是实参的别名,指向相同内存单元
myobject.fun2(out myobj2, out x);
Console.WriteLine("{0},{1}", myobj2.val, x);
//注意数组的定义
int[] myarr = new int[] { 1, 1, 2, 3, 5, 8, 11 };
//直接传递一个数组参数,不需要编译器在堆中重新构造数组,直接存放在栈中
myobject.displaylist(myarr);
//传递一个实参列表,需要编译器在堆中重新构造数组
myobject.displaylist(2, 4, 6, 8, 10);
myobject.displaylist(1, 3, 5, 7);
}
}
}
有关类成员的
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ClassMember { class MyClass1 { int elem1; //实例类成员——实例字段 static int elem2=24; //静态类成员 - -静态字段 public void SetVars(int x, int y) { elem1 = x; elem2 = y; //像访问实例字段一样访问静态字段 } public void Display(string str) { Console.WriteLine("{0}: elem1= {1},elem2={2}", str, elem1, elem2); //像访问实例字段一样访问静态字段 } } class MyClass2 { static public int A; //静态字段 static public void PrintA() //静态方法 { Console.WriteLine("A: {0}", A); } } class MyClass3 { const int val1 = 100; //不能再其他类调用! //注意 常量成员的声明和定义必须在一起,不能分开写出 const int val1; val1=100; public const int val2 = 200;//用public修饰const,可被其他空间的类调用 不能用static修饰 } class MyClass4 { public int val0; //区别字段和属性,不能重名 private int val; //字段,分配内存 public int myval //属性:不分配内存,至少有一个set或get访问器,不允许有其他方法 { set //set访问器 { val = myval; } get //get访问器 { return val; } } public int max { set { //方法也可以不与属性相对应,属性也可以与数据库关联 } get { return 10; } } public int readonlyPerporty //只有get方法的属性称为 只读属性,安全 { get { return val; } } public int writeonlyPerporty //只有set方法的属性 称为 只写属性 { set { val = 4; //在只有set方法是,不能用val=writeonlyPerporty赋值 } } } class MyClass5 { //自动实现属性,只声明属性而不声明后备字段,不提供访问器的方法体;除非通过访问器,否则不能访问后备字段 public int myval { set; get; } static int val; public static int myval2 //静态属性,可在类内访问,也可从类外不用实例化访问 { set { myval2 = val; } get { return val; } } public void PrintVal() { Console.WriteLine("val={0}", myval2); } } class MyClass6 { public string LastName; public string FisrtName; public string BirthPlace; public string this[int index] //索引没有名称,名称位置使用关键字this,索引参数列表在方括号中间,至少有一个参数 {//和属性一样,索引不分配内存,不同的是索引通常访问多个数据成员 set { switch (index) //set被调用时,接受2个数据:隐式参数value(要保存的数据)+索引参数 { case 0: LastName = value; break; case 1: FisrtName = value; break; case 2: BirthPlace = value; break; default: throw new ArgumentOutOfRangeException("index"); break; } } get { switch (index) { case 0: return LastName; case 1: return FisrtName; case 2: return BirthPlace; default: throw new ArgumentOutOfRangeException("index"); break; } } } } partial class MyClass7 //使用关键字 partial 一个类类型可以在两部分中,可以放在多个文件中。 { public void Out1(int val){ Console.WriteLine("out1:{0}",val); } } partial class MyClass7 { public void Out2(int val) { Console.WriteLine("out2:{0}",val); } } class Program { static void Main(string[] args) { // Console.WriteLine("静态字段mem2={0}", new MyClass1().elem2); MyClass1 obj1 = new MyClass1(); MyClass1 obj2 = new MyClass1(); // MyClass1.elem2 = 2012; // Console.WriteLine("静态字段mem2={0}",MyClass1.elem2); obj1.SetVars(2, 4); obj1.Display("obj1 ");//输出2,4 obj2.SetVars(20, 40); obj2.Display("obj2");//输出20,40 obj1.Display("obj1");//输出2,40 //由于2个实例obj1,obj2公用1个静态字段elem,任何一个实例对elem2的改变都会影响到实例的对elem2的访问 MyClass2.A = 10; //使用.运算,不用实例化对象,直接访问静态字段 MyClass2.PrintA(); //使用.运算,不用实例化对象,直接调用静态方法 Console.WriteLine("常量 val2 :{0}", MyClass3.val2);//常量 像 静态字段一样,对每个实例都可见,不用实例化就可以访问 //常量与 静态量不同的时,常量没有自己的存储位置,编译时被编译器替换,类似#define (常量不可用static修饰) MyClass4 obj4 = new MyClass4(); //仅从使用上不能区分属性和字段 obj4.val0 = 5; //给public的字段赋值 obj4.myval = 10; //给属性赋值,set访问器被隐式调用 //obj4.myval.set(3);//注意:不能显示调用set访问器,否则报错 Console.WriteLine("{0},{1}", obj4.val0, obj4.myval);//读取字段和属性,get访问器被隐式调用 MyClass5 obj5 = new MyClass5(); obj5.myval = 2012; Console.WriteLine("自动属性: {0}", obj5.myval); Console.WriteLine("静态属性:{0}", MyClass5.myval2); MyClass6 obj6 = new MyClass6(); obj6[0]="Merry"; obj6[1]="Shibe"; obj6[2] = "Beijing"; //隐式调用索引的set访问器 Console.WriteLine("Name: {0} {1}", obj6[1],obj6[0]); //调用索引的get访问器 //注意:属性和索引都有get/set访问器,默认访问器的访问级别同成员本身。可以也可以单独设置访问器的访问级别,但要保证访问器的安全级别更高 //public< protected( internal) < (protected/ internal) < private MyClass7 obj7 = new MyClass7(); obj7.Out1(5); obj7.Out2(55); } } }