(一)基本概念
.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组件!不需要使用注册表。有并行执行的特性。
(二)C#程序结构
(三)采用命令行方式,编译和运行C#
从VS2010的安装文件夹找到Visual Studo命令行。【直接cmd进入命令行不识别csc等命令】 csc /?获得更多帮助
要首先切换到项目文件所在路径
生成可执行文件!
(四)C#中类型
参数类型 | 修饰符 | 是否在 声明时使用 | 是否在 调用时使用 | 执行 |
值 | 没有 | 系统把实参的值复制到形参。在函数返回后,形参一同从栈中弹出 | ||
引用 | 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);
}
}
}