C#速成

None.gif 原文出处:http: // www.codeguru.com/cs_syntax/CSharp.html
None.gif
原作者:Aisha Ikram
None.gif在一些术语上我尽量做到与MSDN的中文资料所述术语保持一致
None.gif
None.gif使用环境: .NET, C#, Win XP, Win 
2000  
None.gif
None.gif绪论
None.gifC#是这样的一种语言,具有C
++ 的特点,象Java一样的编程风格, 并且象Basic一样的快速开发模型。如果你已经知道了C ++ ,本文会在不到一个小时的时间内让你迅速掌握C#的语法。熟悉Java的括会更好,因为Java的程序结构、打包(Packages)和垃圾收集的概念有助于你更快的了解C#。因此在讨论C#的构造时,我会假定你了解C ++
None.gif
None.gif本文会讨论C#语言的构造与特点,同时会采取简洁的和你能理解的方式使用些代码示例,我们会尽量让你能稍微看看这些代码就能理解这些概念。
None.gif
None.gif注意:本文不是为C#高手(C# gurus)所写. 这是针对在C#学习上还是初学者的文章。
None.gif
None.gif下面是将要讨论的C#问题的目录:
None.gif
None.gif程序结构 
None.gif命名空间
None.gif数据类型
None.gif变量
None.gif运算符和表达式
None.gif枚举
None.gif语句(Statements )
None.gif类(Classes)和结构(Structs)
None.gif修饰符(Modifiers)
None.gif属性(Properties)
None.gif接口(Interfaces)
None.gif方法参数(Function Parameters)
None.gif数组(Arrays)
None.gif索引器(Indexers)
None.gif装箱及拆箱操作
None.gif委托(Delegates)
None.gif继承和多态
None.gif
None.gif下面的内容将不会在被讨论之列:
None.gif
None.gifC
++ 与C#谁更通用
None.gif诸如垃圾回收、线程以及文件处理等概念
None.gif数据的类型转换
None.gif异常处理
None.gif.NET库
None.gif
None.gif
-------------------
None.gif程序结构
None.gif
-------------------
None.gif这一点象C
++ ,C#是一种对大小写字母敏感的语言,分号“;”是语句间的分隔符。与C ++ 不同的是,C#当中声明代码文件(头文件)与实现代码文件(cpp文件)不是独立存在的,所有代码(类声明和类实现)都位于一个扩展名为cs的文件内。
None.gif
None.gif让我们瞧瞧C#当中的 Hello world 程序是怎样的。
None.gif
None.gif
using  System;
None.gif
None.gif
namespace  MyNameSpace
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
class HelloWorld
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine (
"Hello World");
ExpandedSubBlockEnd.gif     }

ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gif在C#当中的每样东西都被封装到一个类中,C#的类又被封装到一个命名空间当中(就象一个文件夹中的文件)。类似于 C
++ ,main方法是你的程序的入口点。C ++ 的main函数调用名称是 " main " ,而C#的main函数是以大写字母M为起点的名称是 " Main "
None.gif
None.gif没有必要把分号分隔符放在类语句块或者结构定义语句块后。这在C
++ 当中被要求,但在C#当中却不是。
None.gif
None.gif
-------------------
None.gif命名空间
None.gif
-------------------
None.gif每一个类都被包装进一个命名空间。命名空间的概念与C
++ 的完全相同,但在C#当中使用命名空间的频率较C ++ 还高。你可以使用点限定符(dot qulifier)访问一个类。在上面的hello world程序当中MyNameSpace就是一个命名空间。
None.gif
None.gif现在思考这样的一个问题,你想从某些别的类的命名空间当中来访问HelloWorld这个类该如何操作。
None.gif这有一个例子:
None.gif
None.gif
using  System;
None.gif
namespace  AnotherNameSpace
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
class AnotherClass
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public void Func()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine (
"Hello World");
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif现在,从你的HelloWorld类里你能象这样去访问上面的这个AnotherNameSpace的命名空间:
None.gif
None.gif
using  System;
None.gif
using  AnotherNameSpace;     //  you will add this using statement
None.gif
namespace  MyNameSpace
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
class HelloWorld
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        AnotherClass obj 
= new AnotherClass();
InBlock.gif        obj.Func();
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gif在.NET库当中,System是位于顶层的命名空间,别的命名空间都存在这个命名空间之下。默认状态下,存在一个全局的命名空间,因此一个在命名空间外定义的类将直接在这个全局命名空间之下;因此,你能在没有任何点限定符的情况下访问这个类。
None.gif
None.gif你也可以象下面这样定义嵌套的命名空间。
None.gif
None.gifUsing
None.gifC
++ 当中的 " #include " 指示被C#的 " using " 关键字取代,它后面跟着一个命名空间的名字。正如上面的 " using System " " System " 是别的所有被封装的命名空间和类中最底层的命名空间。所有对象的基类都是System命名空间内的Object类派生的。
None.gif
None.gif
-------------------
None.gif变量
None.gif
-------------------
None.gif除以下并别外,C#当中的变量几乎与C
++ 同:
None.gif
None.gif与C
++ 不同,C#变量被访问之前必须被初始化;否则编译时会报错。因此,访问一个未初始化变量是不可能的事。
None.gifC#中你不会访问到一个不确定的指针。(译者注:严格说起来C#已经把指针概念异化,限制更严格。所以有些资料上会说C#取消了指针概念)
None.gif一个超出数组边界的表达式是不可访问的。
None.gifC#中没有全局的的变量或全局函数,全局方式的操作是通过静态函数和静态变量来实现的。
None.gif
None.gif
None.gif
-------------------
None.gif数据类型
None.gif
-------------------
None.gif所有C#数据类型都派生自基类Object。这里有两类数据类型:
None.gif
None.gif基本型
/ 内置型 用户自定义型
None.gif
None.gif下面一个C#内置类型列表:
None.gif
None.gif类型 字节数 解释
None.gif
byte   1  无符号字节型
None.gif
sbyte   1  有符号字节型
None.gif
short   2  有符号短字节型
None.gif
ushort   2  无符号短字节型
None.gif
int   4  有符号整型
None.gif
uint   4  无符号整型
None.gif
long   8  有符号长整型
None.gif
ulong   8  无符号长整型
None.gif
float   4  浮点数
None.gif
double   8  双精度数
None.gif
decimal   8  固定精度数
None.gif
string  unicode字串型
None.gif
char  unicode字符型
None.gif
bool  真假布尔型
None.gif
None.gif注意:C#当中的类型范围与C
++ 有所不同;例如,C ++ 的long型是4个字节,而在C#当中是8个字节。同样地,bool型和string型都不同于C ++ 。bool型只接受true和false两种值。不接受任何整数类型。
None.gif
None.gif用户定义类型包括:
None.gif
None.gif类类型(
class )
None.gif结构类型(
struct )
None.gif接口类型(
interface )
None.gif
None.gif数据类型的内存分配形式的不同又把它们分成了两种类型:
None.gif
None.gif值类型(value Types)
None.gif引用类型(Reference Types)
None.gif
None.gif值类型:
None.gif值类型数据在栈中分配。他们包括:所有基本或内置类型(不包括string类型)、结构类型、枚举类型(
enum  type)
None.gif
None.gif引用类型:
None.gif引用类型在堆中分配,当它们不再被使用时将被垃圾收集。它们使用new运算符来创建,对这些类型而言,不存在C
++ 当中的delete操作符,根本不同于C ++ 会显式使用delete这个运算符去释放创建的这个类型。C#中,通过垃圾收集器,这些类型会自动被收集处理。
None.gif
None.gif引用类型包括:类类型、接口类型、象数组这样的集合类型类型、字串类型、枚举类型
None.gif
None.gif枚举类型与C
++ 当中的概念非常相似。它们都通过一个enum关键字来定义。
None.gif
None.gif示例:
None.gif
None.gif
enum  Weekdays
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday
ExpandedBlockEnd.gif}

None.gif
None.gif类类型与结构类型的比较
None.gif除了在内存分配形式上外,类与结构的概念完全与C
++ 相同。类的对象被分配在堆中,并且通过new来创建,结构也是被new创建但却被分配在栈当中。C#当中,结构型适于快速访问和拥有少量成员的数据类型。如果涉及量较多,你应该创建一个类来实现他。
None.gif(译者注:这与堆和栈内存分配结构的特点有关。简而言之,栈是一种顺序分配的内存;堆是不一定是连续的内存空间。具体内容需要大家参阅相关资料)
None.gif
None.gif示例:
None.gif
None.gif
struct  Date
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int day;
InBlock.gif    
int month;
InBlock.gif    
int year;
ExpandedBlockEnd.gif}

None.gif
None.gif
class  Date
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int day;
InBlock.gif    
int month;
InBlock.gif    
int year;
InBlock.gif    
string weekday;
InBlock.gif    
string monthName;
InBlock.gif    
public int GetDay()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return day;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public int GetMonth()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return month;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public int GetYear()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return year;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetDay(int Day)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        day 
= Day ;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetMonth(int Month)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        month 
= Month;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetYear(int Year)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        year 
= Year;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public bool IsLeapYear()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return (year/4 == 0);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetDate (int day, int month, int year)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockEnd.gif    }

InBlock.gif    dot.gif
ExpandedBlockEnd.gif}

None.gif
None.gif
None.gif
None.gif
-------------------
None.gif属性
None.gif
-------------------
None.gif如果你熟悉C
++ 面象对象的方式,你就一定有一个属性的概念。在上面示例当中,以C ++ 的观点来看,Data类的属性就是day、month和year。用C#方式,你可以把它们写成Get和Set方法。C#提供了一个更方便、简单、直接的方式来访问属性。
None.gif
None.gif因此上面的类可以被写成:
None.gif
None.gif
using  System;
None.gif
class  Date
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int Daydot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gif{
InBlock.gif            
return day;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{
InBlock.gif            day 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
int day;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int Monthdot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gif{
InBlock.gif            
return month;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{
InBlock.gif            month 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
int month;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int Yeardot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gif{
InBlock.gif            
return year;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{
InBlock.gif            year 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
int year;
InBlock.gif
InBlock.gif    
public bool IsLeapYear(int year)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return year%4== 0 ? truefalse;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetDate (int day, int month, int year)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.day   = day;
InBlock.gif        
this.month = month;
InBlock.gif        
this.year  = year;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif你可在这里得到并设置这些属性:
None.gif
None.gif
class  User
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif   
public static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif   
dot.gif{
InBlock.gif        Date date 
= new Date();
InBlock.gif        date.Day 
= 27;
InBlock.gif        date.Month 
= 6;
InBlock.gif        date.Year 
= 2003;
InBlock.gif        Console.WriteLine(
"Date: {0}/{1}/{2}", date.Day,
InBlock.gif                                               date.Month,
InBlock.gif                                               date.Year);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
None.gif
None.gif
None.gif
-------------------
None.gif修饰符
None.gif
-------------------
None.gif你必须已经知道public、
private 、protected这些常在C ++ 当中使用的修饰符。这里我会讨论一些C#引入的新的修饰符。
None.gif
None.gif
readonly (只读)
None.gifreadonly修饰符仅在类的数据成员中使用。正如这名字所提示的,
readonly  数据成员仅能只读,它们只能在构造函数或是直接初始化操作下赋值一次。readonly与const数据成员不同, const  要求你在声明中初始化,这是直接进行的。看下面的示例代码:
None.gif
None.gif
class  MyClass
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
const int constInt = 100;    //直接初始化
InBlock.gif
    readonly int myInt = 5;      //直接初始化
InBlock.gif
    readonly int myInt2;     //译者注:仅做声明,未做初始化
InBlock.gif
    
InBlock.gif    
public MyClass()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        myInt2 
= 8;              //间接的
ExpandedSubBlockEnd.gif
    }

InBlock.gif    
public Func()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        myInt 
= 7;               //非法操作(译者注:不得赋值两次)
InBlock.gif
        Console.WriteLine(myInt2.ToString());
ExpandedSubBlockEnd.gif    }

InBlock.gif    
ExpandedBlockEnd.gif}

None.gif
None.gif
sealed (密封)
None.gif密封类不允许任何类继承,它没有派生类。因此,你可以对你不想被继承的类使用sealed关键字。
None.gif
None.gif
sealed   class  CanNotbeTheParent
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int a = 5;
ExpandedBlockEnd.gif}

None.gif
None.gif
unsafe (不安全)
None.gif你可使用unsafe修饰符来定义一个不安全的上下文。在不安全的上下文里,你能写些如C
++ 指针这样的不安全的代码。看下面的示例代码:
None.gif
None.gif
public   unsafe  MyFunction(  int   *  pInt,  double *  pDouble)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int* pAnotherInt = new int;
InBlock.gif    
*pAnotherInt  = 10;
InBlock.gif    pInt 
= pAnotherInt;
InBlock.gif    dot.gif
InBlock.gif    
*pDouble = 8.9;
ExpandedBlockEnd.gif}

None.gif
None.gif
None.gif
None.gif
None.gif
-------------------
None.gif
interface (接口)
None.gif
-------------------
None.gif
None.gif如果你有COM方面的概念,你会立亥明白我要谈论的内容。一个接口就是一个抽象的基类,这个基类仅仅包含功能描述,而这些功能的实现则由子类来完成。C#中你要用interface关键字来定义象接口这样的类。.NET就是基于这样的接口上的。C#中你不支持C
++ 所允许的类多继承(译者注:即一个派生类可以从两个或两个以上的父类中派生)。但是多继承方式可以通过接口获得。也就是说你的一个子类可以从多个接口中派生实现。
None.gif
None.gif
using  System;
None.gif
interface  myDrawing
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int originx
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
get;
InBlock.gif        
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
int originy
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
get;
InBlock.gif        
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
void Draw(object shape);
ExpandedBlockEnd.gif}

None.gif
None.gif
class  Shape: myDrawing
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int OriX;
InBlock.gif    
int OriY;
InBlock.gif
InBlock.gif    
public int originx
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
getdot.gif{
InBlock.gif            
return OriX;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
setdot.gif{
InBlock.gif            OriX 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
public int originy
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
getdot.gif{
InBlock.gif            
return OriY;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
setdot.gif{
InBlock.gif            OriY 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void Draw(object shape)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        dot.gif    
// do something
ExpandedSubBlockEnd.gif
    }

InBlock.gif    
InBlock.gif    
// class's own method
InBlock.gif
    public void MoveShape(int newX, int newY)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif    dot.gif..
ExpandedSubBlockEnd.gif    }

InBlock.gif    
ExpandedBlockEnd.gif}

None.gif
None.gif
None.gif
None.gif
None.gif
-------------------
None.gifArrays(数组)
None.gif
-------------------
None.gif
None.gifC#中的数组比C
++ 的表现更好。数组被分配在堆中,因此是引用类型。你不可能访问超出一个数组边界的元素。因此,C#会防止这样类型的bug。一些辅助方式可以循环依次访问数组元素的功能也被提供了,foreach就是这样的一个语句。与C ++ 相比,C#在数组语法上的特点如下:
None.gif
None.gif方括号被置于数据类型之后而不是在变量名之后。
None.gif创建数组元素要使用new操作符。
None.gifC#支持一维、多维以及交错数组(数组中的数组)。
None.gif
None.gif示例:
None.gif
None.gif    
int [] array  =   new   int [ 10 ];               //  整型一维数组
None.gif
     for  ( int  i  =   0 ; i  <  array.Length; i ++ )
None.gif        array[i] 
=  i; 
None.gif
None.gif    
int [,] array2  =   new   int [ 5 , 10 ];           //  整型二维数组
None.gif
    array2[ 1 , 2 =   5 ;
None.gif
None.gif    
int [,,] array3  =   new   int [ 5 , 10 , 5 ];        //  整型的三维数组
None.gif
    array3[ 0 , 2 , 4 =   9 ;
None.gif
None.gif    
int [][] arrayOfarray  =   =   new   int [ 2 ];     //  整型交错数组(数组中的数组)
None.gif
    arrayOfarray[ 0 =   new   int [ 4 ]; 
ExpandedBlockStart.gifContractedBlock.gif    arrayOfarray[
0 =   new   int []  dot.gif {1,2,15} ;
None.gif
None.gif
None.gif
None.gif
None.gif
-------------------
None.gif索引器
None.gif
-------------------
None.gif
None.gif索引器被用于写一个访问集合元素的方法,集合使用
" [] " 这样的直接方式,类似于数组。你所要做的就是列出访问实例或元素的索引清单。类的属性带的是输入参数,而索引器带的是元素的索引表,除此而外,他们二者的语法相同。
None.gif
None.gif示例:
None.gif
None.gif注意:CollectionBase是一个制作集合的库类。List是一个protected型的CollectionBase成员,储存着集合清单列表。
None.gif
class  Shapes: CollectionBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public void add(Shape shp)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        List.Add(shp);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
//indexer
InBlock.gif
    public Shape this[int index]
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gif{
InBlock.gif            
return (Shape) List[index];
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{
InBlock.gif            List[index] 
= value ;
ExpandedSubBlockEnd.gif         }

ExpandedSubBlockEnd.gif     }

ExpandedBlockEnd.gif}

None.gif
None.gif
None.gif
None.gif
None.gif
-------------------
None.gif装箱和拆箱操作(Boxing
/ Unboxing)
None.gif
-------------------
None.gif
None.gifC#的装箱思想是全新的。上面提到过所有的数据类型,不论内置或用户自定义,全都从命名空间System的一个基类object派生出来。因此把基本的或者原始类型转换成object类型被称做装箱,反之,这种方式的逆操作被称为拆箱。
None.gif
None.gif示例:
None.gif
None.gif
class  Test
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif   
static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif   
dot.gif{
InBlock.gif      
int myInt = 12;
InBlock.gif      
object obj = myInt ;       // 装箱
InBlock.gif
      int myInt2 = (int) obj;    // 拆箱
ExpandedSubBlockEnd.gif
   }

ExpandedBlockEnd.gif}

None.gif
None.gif示例展示了装箱和拆箱操作。一个整型值转换成object类型,然后又转换回整型。当一个值类型的变量需要转换成引用类型时,一个object的箱子会被分配容纳这个值的空间,这个值会被复制进这个箱子。拆箱与此相反,一个object箱子中的数据被转换成它的原始值类型时,这个值将被从箱中复制到适当的存储位置。
英文原版:
None.gif
None.gifEnvironment: .NET, C#, Win XP, Win 
2000  
None.gif
None.gifIntroduction
None.gifC# 
is  a language with the features of C ++ , programming style like Java, and the rapid application model of Basic. If you already know the C ++  language, it will take you less than an hour to quickly go through the syntax of C#. Familiarity with Java will be a plus because the Java program structure, the concept of packages, and garbage collection will definitely help you learn C# more quickly. So  while  discussing C# language constructs, I will assume that you know C ++ .
None.gifNone.gif
None.gif(continued)
None.gif
None.gif
None.gifThis article dicusses the C# language constructs and features, 
using  code examples  in  a brief and comrehensive way so that you can, just by having a glance at the code, understand the concepts.
None.gif
None.gifNote: This article 
is  not  for  C# gurus. There must be some other beginner ' s articles on C#, but this is yet another one.
None.gif

None.gifThe following topics of the C# langauge are discussed:
None.gif
None.gifProgram Structure 
None.gifNamespaces 
None.gifData Types 
None.gifVariables 
None.gifOperators and Expressions 
None.gifEnumerations 
None.gifStatements 
None.gifClasses and Structs 
None.gifModifiers 
None.gifProperties 
None.gifInterfaces 
None.gifFunction Parameters 
None.gifArrays 
None.gifIndexers 
None.gifBoxing and Unboxing 
None.gifDelegates 
None.gifInheritance and Polymorphism 
None.gifThe following topics are not discussed:
None.gif
None.gifThings that are common 
in  C ++  and C# 
None.gifConcepts such 
as  garbage collection, threading, file processing, and so forth 
None.gifData type conversions 
None.gifException handling 
None.gif.NET library 
None.gifProgram Structure
None.gifLike C
++ , C#  is   case - sensitive. The semicolon, ;,  is  the statement separator. Unlike C ++ , there are no separate declaration (header) and implementation(cpp) files  in  C#. All code ( class  declaration and implementation)  is  placed  in  one file with a cs extention.
None.gif
None.gifHave a look at 
this  Hello world program  in  C#.
None.gif
None.gif
using  System;
None.gif
None.gif
namespace  MyNameSpace
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
class HelloWorld
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine (
"Hello World");
ExpandedSubBlockEnd.gif     }

ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gifEverything 
in  C#  is  packed into a  class  and classes  in  C# are packed into namespaces (just like files  in  a folder). Like C ++ , a main method  is  the entry point of your program. C ++ ' s main function is called "main", whereas C# ' s main function starts with a capital M and  is  named  " Main " .
None.gif
None.gifThere 
is  no need to put a semicolon after a  class  block or  struct  definition. It was required  in  C ++ , but not  in  C#.
None.gif
None.gifNamespace
None.gifEvery 
class   is  packaged into a  namespace . Namespaces are exactly the same concept  as   in  C ++ , but  in  C# we use namespaces more frequently than  in  C ++ . You can access a  class   in  a  namespace   using  dot . qualifier. MyNameSpace  is  the  namespace   in  the hello world program above.
None.gif
None.gifNow, consider that you want to access the HelloWorld 
class  from some other  class   in  some other  namespace .
None.gif
None.gif
using  System;
None.gif
namespace  AnotherNameSpace
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
class AnotherClass
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public void Func()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine (
"Hello World");
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gifNow, from your HelloWorld 
class , you can access it  as :
None.gif
None.gif
using  System;
None.gif
using  AnotherNameSpace;     //  you will add this using statement
None.gif
namespace  MyNameSpace
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
class HelloWorld
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        AnotherClass obj 
= new AnotherClass();
InBlock.gif        obj.Func();
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gifIn the .NET library, System 
is  the top - level  namespace   in  which other namespaces exist. By  default , there exists a global  namespace , so a  class  defined outside a  namespace  goes directly into  this  global  namespace ; hence, you can access  this   class  without any qualifier.
None.gif
None.gifyou can also define nested namespaces.
None.gif
None.gifUsing
None.gifThe #include directive 
is  replaced with the  " using "  keyword, which  is  followed by a  namespace  name. Just  as   in   " using System " , above.  " System "   is  the  base - level  namespace   in  which all other namespaces and classes are packed. The  base   class   for  all  object   is  Object  in  the System  namespace .
None.gif
None.gifVariables
None.gifVariables 
in  C# are almost the same  as   in  C ++ , except  for  these differences:
None.gif
None.gifVariables 
in  C# (unlike C ++ ) always need to be initialized before you access them; otherwise, you will  get  a compile time error. Hence, it ' s impossible to access an uninitialized variable. 
None.gif
You can ' t access a .dangling. pointer in C#. 
None.gif
An expression that indexes an array beyond its bounds  is  also not accessible. 
None.gifThere are no global variables or functions 
in  C# and the behavior of globals  is  acheived through  static  functions and  static  variables. 
None.gifData Types
None.gifAll types of C# are derived from a 
base - class   object . There are two types of data types:
None.gif
None.gifBasic
/ Built - in  types 
None.gifUser
- defined types 
None.gifFollowing 
is  a table that lists built - in  C# types:
None.gif
None.gifType
None.gif Bytes
None.gif Desc
None.gif 
None.gif
byte   1  unsigned  byte  
None.gif
sbyte   1  signed  byte  
None.gif
short   2  signed  short  
None.gif
ushort   2  unsigned  short  
None.gif
int   4  signed integer 
None.gif
uint   4  unsigned integer 
None.gif
long   8  signed  long  
None.gif
ulong   8  unsigned  long  
None.gif
float   4  floating point number 
None.gif
double   8   double  precision number 
None.gif
decimal   8   fixed  precision number 
None.gif
string   unicode  string  
None.gif
char   unicode  char  
None.gif
bool   true false  boolean 
None.gif
None.gifNote: Type range 
in  C# and C ++  are different;  for  example,  long   in  C ++   is   4  bytes, and  in  C# it  is   8  bytes. Also, the  bool  type and  string  types are different than those  in  C ++ . Bool accepts only  true  and  false  and not any integer.
None.gifUser
- defined types include:
None.gif
None.gifClasses 
None.gifStructs 
None.gifInterfaces 
None.gifMemory allocation of the data types divides them into two types:
None.gif
None.gifValue Types 
None.gifReference Types 
None.gifValue types
None.gifValue types are those data types that are allocated 
in  the stack. They include:
None.gif
None.gifAll basic or built
- in  types except strings 
None.gifStructs 
None.gifEnum types 
None.gifReference type
None.gifReference types are allocated on the heap and are garbage collected when they are no longer being used. They are created 
using  the  new   operator , and there  is  no delete  operator   for  these types, unlike  in  C ++ , where the user has to explicitely delete the types created  using  the delete  operator . In C#, they are automatically collected by the garbage collector.
None.gif
None.gifReference types include:
None.gif
None.gifClasses 
None.gifInterfaces 
None.gifCollection types such 
as  arrays 
None.gifString 
None.gifEnumeration
None.gifEnumerations 
in  C# are exactly like C ++ . They are defined through a  enum  keyword.
None.gif
None.gifExample:
None.gif
None.gif
enum  Weekdays
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday
ExpandedBlockEnd.gif}

None.gif
None.gifClasses and Structs
None.gifClasses and structs are same 
as   in  C ++ , except  in  the difference of their memory allocation. Objects of classes are allocated  in  the heap, and are created  using   new , where  as  structs are allocated  in  the stack. Structs  in  C# are very light and fast datatypes. For heavy datatypes, you should create classes.
None.gif
None.gifExamples:
None.gif
None.gif
struct  Date
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int day;
InBlock.gif    
int month;
InBlock.gif    
int year;
ExpandedBlockEnd.gif}

None.gif
None.gif
class  Date
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int day;
InBlock.gif    
int month;
InBlock.gif    
int year;
InBlock.gif    
string weekday;
InBlock.gif    
string monthName;
InBlock.gif    
public int GetDay()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return day;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public int GetMonth()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return month;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public int GetYear()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return year;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetDay(int Day)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        day 
= Day ;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetMonth(int Month)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        month 
= Month;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetYear(int Year)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        year 
= Year;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public bool IsLeapYear()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return (year/4 == 0);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetDate (int day, int month, int year)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockEnd.gif    }

InBlock.gif    dot.gif
ExpandedBlockEnd.gif}

None.gif
None.gifProperties
None.gifIf you familiar with the 
object - oriented way of C ++ , you must have an idea of properties. Properties  in  the above example of the Date  class  are day, month, and year  for  which  in  C ++ , you write Get and Set methods. C# provides a more convinient, simple, and straightforward way of accessing properties.
None.gif
None.gifSo, the above 
class  can be written  as :
None.gif
None.gif
using  System;
None.gif
class  Date
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int Daydot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gif{
InBlock.gif            
return day;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{
InBlock.gif            day 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
int day;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int Monthdot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gif{
InBlock.gif            
return month;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{
InBlock.gif            month 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
int month;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int Yeardot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gif{
InBlock.gif            
return year;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{
InBlock.gif            year 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
int year;
InBlock.gif
InBlock.gif    
public bool IsLeapYear(int year)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return year%4== 0 ? truefalse;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void SetDate (int day, int month, int year)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.day   = day;
InBlock.gif        
this.month = month;
InBlock.gif        
this.year  = year;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gifHere 
is  the way you will  get  and  set  these properties:
None.gif
None.gif
class  User
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif   
public static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif   
dot.gif{
InBlock.gif        Date date 
= new Date();
InBlock.gif        date.Day 
= 27;
InBlock.gif        date.Month 
= 6;
InBlock.gif        date.Year 
= 2003;
InBlock.gif        Console.WriteLine(
"Date: {0}/{1}/{2}", date.Day,
InBlock.gif                                               date.Month,
InBlock.gif                                               date.Year);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gifModifiers
None.gifYou must be aware of 
public private , and  protected  modifers that are commonly used  in  C ++ . Here, I will discuss some  new  modifiers introduced by C#.
None.gif
None.gif
readonly
None.gifThe 
readonly  modifier  is  used only  for  the  class  data members. As the name indicates, the  readonly  data members can only be read once they are written either directly initializing them or assigning values to them  in  constructor. The difference between the  readonly  and  const  data members  is  that  const  requires you to initialize with the declaration, that  is  directly. See  this  example code:
None.gif
None.gif
class  MyClass
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
const int constInt = 100;    //directly
InBlock.gif
    readonly int myInt = 5;      //directly
InBlock.gif
    readonly int myInt2;
InBlock.gif
InBlock.gif    
public MyClass()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        myInt2 
= 8;              //Indirectly
ExpandedSubBlockEnd.gif
    }

InBlock.gif    
public Func()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        myInt 
= 7;               //Illegal
InBlock.gif
        Console.WriteLine(myInt2.ToString());
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gif
sealed
None.gifthe 
sealed  modifier with a  class  doesn ' t let you derive any class from it. So, you use this sealed keyword for the classes that you don ' t want to be inherited from.
None.gif
None.gif
sealed   class  CanNotbeTheParent
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int a = 5;
ExpandedBlockEnd.gif}

None.gif
None.gif
unsafe
None.gifYou can define an 
unsafe  context  in  C# by  using  an  unsafe  modifier. In the  unsafe  context, you can write an  unsafe  code;  for  example, C ++  pointers and so forth. See the following code:
None.gif
None.gif
public   unsafe  MyFunction(  int   *  pInt,  double *  pDouble)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int* pAnotherInt = new int;
InBlock.gif    
*pAnotherInt  = 10;
InBlock.gif    pInt 
= pAnotherInt;
InBlock.gif    dot.gif
InBlock.gif    
*pDouble = 8.9;
ExpandedBlockEnd.gif}

None.gif
None.gifInterfaces
None.gifIf you have an idea of the COM, you will immediately know what I am talking about. An 
interface   is  the  abstract   base   class  containing only the function signatures whose implementation  is  provided by the child  class . In C#, you define such classes  as  interfaces  using  the  interface  keyword. .NET  is  based on such interfaces. In C#, where you can ' t use multiple class inheritance, which was previously allowed in C++, the essence of multiple inheritance is acheived through interfaces. That ' s how your child  class  may implement multiple interfaces.
None.gif
None.gif
using  System;
None.gif
interface  myDrawing
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int originx
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
get;
InBlock.gif        
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
int originy
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
get;
InBlock.gif        
set;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
void Draw(object shape);
ExpandedBlockEnd.gif}

None.gif
None.gif
class  Shape: myDrawing
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int OriX;
InBlock.gif    
int OriY;
InBlock.gif
InBlock.gif    
public int originx
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
getdot.gif{
InBlock.gif            
return OriX;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
setdot.gif{
InBlock.gif            OriX 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
public int originy
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
getdot.gif{
InBlock.gif            
return OriY;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
setdot.gif{
InBlock.gif            OriY 
= value;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
public void Draw(object shape)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        dot.gif    
// do something
ExpandedSubBlockEnd.gif
    }

InBlock.gif
InBlock.gif    
// class's own method
InBlock.gif
    public void MoveShape(int newX, int newY)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif    dot.gif..
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gifArrays
None.gifArrays 
in  C# are much better than  in  C ++ . Arrays are allocated  in  the heap and thus are of the reference type. You can ' t access an out-of-bound element in an array. So, C# prevents you from that type of bug. Also, some helper functions to iterate array elements are provided. foreach is the statement for such an iteration. The difference between the syntax of the C++ and C# array is:
None.gif

None.gifThe square brackets are placed after the type and not after the variable name. 
None.gifYou create element locations 
using   new   operator
None.gifC# supports single dimensional, multi dimensional, and jagged array (array of an array).
None.gif
None.gifExamples:
None.gif
None.gif    
int [] array  =   new   int [ 10 ];               //  single-dimensional
None.gif                                            
//  array of int
None.gif
     for  ( int  i  =   0 ; i  <  array.Length; i ++ )
None.gif        array[i] 
=  i;
None.gif
None.gif    
int [,] array2  =   new   int [ 5 , 10 ];           //  2-dimensional array
None.gif                                            
//  of int
None.gif
    array2[ 1 , 2 =   5 ;
None.gif
None.gif    
int [,,] array3  =   new   int [ 5 , 10 , 5 ];        //  3-dimensional array
None.gif                                            
//  of int
None.gif
    array3[ 0 , 2 , 4 =   9 ;
None.gif
None.gif    
int [][] arrayOfarray  =   =   new   int [ 2 ];     //  Jagged array -
None.gif                                            
//  array of array of
None.gif                                            
//  int
None.gif
    arrayOfarray[ 0 =   new   int [ 4 ];
ExpandedBlockStart.gifContractedBlock.gif    arrayOfarray[
0 =   new   int []  dot.gif {1,2,15} ;
None.gif
None.gifIndexers
None.gifAn indexer 
is  used to write a method to access an element from a collection  using  the straight way of  using  [], like an array. All you need  is  to specify the index to access an instance or element. The syntax of an indexer  is  same  as  that of  class  properties, except they take the input parameter, that  is  the index of the element.
None.gif
None.gifExample:
None.gif
None.gifNote: CollectionBase 
is  the library  class  used  for  making collections. List  is  the  protected  member of CollectionBase, which stores the collection list.
None.gif
class  Shapes: CollectionBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public void add(Shape shp)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        List.Add(shp);
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
//indexer
InBlock.gif
    public Shape this[int index]
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
get dot.gif{
InBlock.gif            
return (Shape) List[index];
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
set dot.gif{
InBlock.gif            List[index] 
= value ;
ExpandedSubBlockEnd.gif         }

ExpandedSubBlockEnd.gif     }

ExpandedBlockEnd.gif}

None.gif
None.gifBoxing
/ Unboxing
None.gifThe idea of boxing 
is   new   in  C#. As mentioned above, all data types, built - in  or user defined, are derived from a  base   class   object   in  the System  namespace . So, the packing of basic or primitive types into an  object   is  called boxing, whereas the reverse of  this  known  as  unboxing.
None.gif
None.gifExample:
None.gif
None.gif
class  Test
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif   
static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif   
dot.gif{
InBlock.gif      
int myInt = 12;
InBlock.gif      
object obj = myInt ;       // boxing
InBlock.gif
      int myInt2 = (int) obj;    // unboxing
ExpandedSubBlockEnd.gif
   }

ExpandedBlockEnd.gif}

None.gif
None.gifThe example shows both boxing and unboxing. An 
int  value can be converted to an  object  and back again to an  int . When a variable of a value type needs to be converted to a reference type, an  object  box  is  allocated to hold the value, and the value  is  copied into the box. Unboxing  is  just the opposite. When an  object  box  is  cast back to its original value type, the value  is  copied  out  of the box and into the appropriate storage location.
None.gif
None.gifFunction Parameters
None.gifParameters 
in  C# are of three types:
None.gif
None.gifBy
- Value / In parameters 
None.gifBy
- Reference / In - Out parameters 
None.gifOut pParameters 
None.gifIf you have an idea of the COM 
interface  and its parameters types, you will easily understand the C# parameter types.
None.gif
None.gifBy
- Value / In parameters
None.gifThe concept of value parameters 
is  the same  as   in  C ++ . The value of the passed value  is  copied into a location and  is  passed to the function.
None.gif
None.gifExample:
None.gif
None.gifSetDay(
5 );
None.gifdot.gif
None.gif
void  SetDay( int  day)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    dot.gif.
ExpandedBlockEnd.gif}

None.gif
None.gifBy
- Reference / In - Out Parameters
None.gifThe reference parameters 
in  C ++  are passed either through pointers or a reference  operator & . In C#, reference parameters are less error prone. Reference parameters are also called In - Out parameters because you pass a reference address of the location, so you pass an input value and  get  an output value from that function.
None.gif
None.gifYou cannot pass an uninitialized reference parameter into a function. C# uses a keyword 
ref   for  the reference parameters. You also have to use keyword  ref  with an argument  while  passing it to a function - demanding reference parameter.
None.gif
None.gifExample:
None.gif
None.gif    
int  a =   5 ;
None.gif    FunctionA(
ref  a);         //  use ref with argument or you will
None.gif                             
//  get a compiler error
None.gif
    Console.WriteLine(a);     //  prints 20
None.gif

None.gif    
void  FunctionA( ref   int  Val)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
int x= Val;
InBlock.gif        Val 
= x* 4;
ExpandedBlockEnd.gif    }

None.gif
None.gifOut parameter
None.gifThe Out parameter 
is  the parameter that only returns a value from the function. The input value  is  not required. C# uses the keyword  out   for  the  out  parameters
None.gif
None.gifExample:
None.gif
None.gif    
int  Val;
None.gif    GetNodeValue(Val);
None.gif
None.gif    
bool  GetNodeValue( out   int  Val)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        Val 
= value;
InBlock.gif        
return true;
ExpandedBlockEnd.gif    }

None.gif
None.gifVariable number of parameters and arrays
None.gifArrays 
in  C# are passed through a keyword  params . An array - type parameter should always be the right - most argument of the function. Only one parameter can be of the array type. You can pass any number of elements  as  an argument of type of that array. You can better understand it from the following example.
None.gif
None.gifExample:
None.gif
None.gif    
void  Func( params   int [] array)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        Console.WriteLine(
"number of elements {0}",
InBlock.gif                           array.Length);
ExpandedBlockEnd.gif    }

None.gif
None.gif    Func();                      
//  prints 0
None.gif
    Func( 5 );                      //  prints 1
None.gif
    Func( 7 , 9 );                    //  prints 2
ExpandedBlockStart.gifContractedBlock.gif
    Func( new   int []  dot.gif {3,8,10} );     //  prints 3
ExpandedBlockStart.gifContractedBlock.gif
     int [] array  =   new   int [ 8 dot.gif {1,3,4,5,5,6,7,5} ;
None.gif    Func(array);                 
//  prints 8
None.gif

None.gifOperators and Expressions
None.gifOperators are exactly the same 
as  om C ++  and thus the expression, also. However, some  new  and useful operators have been added. Some of them are discussed here.
None.gif
None.gif
is   operator
None.gifThe 
is   operator   is  used to check whether the operand types are equal or convertable. The  is   operator   is  particularly useful  in  the polymorphism scenarios. The  is   operator  takes two operands and the result  is  a boolean. See the example:
None.gif
None.gif
void  function( object  param)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
if(param is ClassA)
InBlock.gif        
//do something
InBlock.gif
    else if(param is MyStruct)
InBlock.gif        
//do something
ExpandedBlockEnd.gif
    }

None.gif}
None.gif
None.gif
as   operator
None.gifThe 
as   operator  checks whether the type of the operands are convertable or equal ( as   is  done by  is   operator ) and  if  it  is , the result  is  a converted or boxed  object  ( if  the operand can be boxed into the target type, see boxing / unboxing). If the objects are not convertable or boxable, the  return   is  a  null . Have a look at the example below to better understand the concept.
None.gif
None.gifShape shp 
=   new  Shape();
None.gifVehicle veh 
=  shp  as  Vehicle;    //  result is null, types are not
None.gif                                
//  convertable
None.gif

None.gifCircle cir 
=   new  Circle();
None.gifShape shp 
=  cir;
None.gifCircle cir2 
=  shp  as  Circle;     // will be converted
None.gif

None.gif
object [] objects  =   new   object [ 2 ];
None.gifobjects[
0 =   " Aisha " ;
None.gif
object [ 1 =   new  Shape();
None.gif
None.gif
string  str;
None.gif
for ( int  i = 0 ; i &<  objects.Length; i ++ )
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    str 
= objects[i] as string;
InBlock.gif    
if(str == null)
InBlock.gif        Console.WriteLine(
"can not be converted");
InBlock.gif    
else
InBlock.gif        Console.WriteLine(
"{0}",str);
ExpandedBlockEnd.gif}

None.gif
None.gifOutput:
None.gifAisha
None.gifcan not be converted
None.gif
None.gifStatements
None.gifStatements 
in  C# are just like  in  C ++  except some additions of  new  statements and modifications  in  some statements.
None.gif
None.gifThe following are 
new  statements:
None.gif
None.gif
foreach
None.gifFor iteration of collections, such 
as  arrays, and so forth.
None.gif
None.gifExample:
None.gif
None.gif    
foreach  ( string  s  in  array)
None.gif        Console.WriteLine(s);
None.gif
None.gif
lock
None.gifUsed 
in  threads  for  locking a block of code, making it a critical section.
None.gif
None.gif
checked / unchecked
None.gifThe statements are 
for  overflow checking  in  numeric operations.
None.gif
None.gifExample:
None.gif
None.gif
int  x  =  Int32.MaxValue; x ++ ;     //  Overflow checked
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gifx
++;                            // Exception
ExpandedBlockEnd.gif
}

None.gif
unchecked
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gifx
++;                            // Overflow}
ExpandedBlockEnd.gif
}

None.gif
None.gifThe following statements are modified:
None.gif
None.gifSwitch
None.gifThe Switch statement 
is  modified  in  C#.
None.gif
None.gifNow, after executing a 
case  statement, program flow cannot jump to the next  case , which was previously allowed  in  C ++ .
None.gifExample: 
None.gif
int  var  =   100 ;
None.gif
switch  (var)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
case 100: Console.WriteLine("<Value is 100>");
InBlock.gif        
// No break here
InBlock.gif
    case 200: Console.WriteLine("<Value is 200>"); break;
ExpandedBlockEnd.gif}

None.gifOutput 
in  C ++ :
None.gif    
< Value  is   100 >< Value  is   200 >
None.gif
None.gifIn C#, you 
get  a compile time error:
None.gif
None.giferror CS0163: Control cannot fall through from one 
case  label
None.gif(
' case 100: ' ) to another
None.gif
None.gifHowever, you can 
do   this  similarly to the way you  do  it  in  C ++
None.gif
switch  (var)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
case 100:
InBlock.gif    
case 200: Console.WriteLine("100 or 200<VALUE is 200>");
InBlock.gif              
break;
ExpandedBlockEnd.gif}

None.gif
None.gifYou also can use constant variables 
for   case  values: 
None.gifExample:
None.gif
None.gif
const   string  WeekEnd   =   " Sunday " ;
None.gif
const   string  WeekDay1  =   " Monday " ;
None.gif
None.gifdot.gif.
None.gif
None.gif
string  WeekDay  =  Console.ReadLine();
None.gif
switch  (WeekDay )
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
case WeekEnd: Console.WriteLine("It's weekend!!"); break;
InBlock.gif
case WeekDay1: Console.WriteLine("It's Monday"); break;
InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gifDelegates
None.gifDelegates let us store function references into a variable. In C
++ this   is  like  using  and storing a function pointer  for  which we usually use typedef.
None.gif
None.gifDelegates are declared 
using  a keyword  delegate . Have a look at  this  example, and you will understand what delegates are:
None.gif
None.gifExample:
None.gif
None.gif
delegate   int  Operation( int  val1,  int  val2);
None.gif
public   int  Add( int  val1,  int  val2)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
return val1 + val2;
ExpandedBlockEnd.gif}

None.gif
public   int  Subtract ( int  val1,  int  val2)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
return val1- val2;
ExpandedBlockEnd.gif}

None.gif
None.gif
public   void  Perform()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    Operation Oper;
InBlock.gif    Console.WriteLine(
"Enter + or - ");
InBlock.gif    
string optor = Console.ReadLine();
InBlock.gif    Console.WriteLine(
"Enter 2 operands");
InBlock.gif
InBlock.gif    
string opnd1 = Console.ReadLine();
InBlock.gif    
string opnd2 = Console.ReadLine();
InBlock.gif
InBlock.gif    
int val1 = Convert.ToInt32 (opnd1);
InBlock.gif    
int val2 = Convert.ToInt32 (opnd2);
InBlock.gif
InBlock.gif    
if (optor == "+")
InBlock.gif        Oper 
= new Operation(Add);
InBlock.gif    
else
InBlock.gif        Oper 
= new Operation(Subtract);
InBlock.gif
InBlock.gif    Console.WriteLine(
" Result = {0}", Oper(val1, val2));
ExpandedBlockEnd.gif}

None.gif
None.gifInheritance and Polymorphism
None.gifOnly single inheritance 
is  allowed  in  C#. Mutiple inheritance can be acheived by  using  interfaces.
None.gif
None.gifExample:
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class  Parent dot.gif {
ExpandedBlockEnd.gif}

None.gif
None.gif
class  Child : Parent
None.gif
None.gifVirtual Functions
None.gifVirtual functions implement the concept of polymorphism are the same 
as   in  C#, except that you use the  override  keyword with the  virtual  function implementaion  in  the child  class . The parent  class  uses the same  virtual  keyword. Every  class  that overrides the  virtual  method will use the  override  keyword.
None.gif
None.gif
class  Shape
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public virtual void Draw()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Shape.Draw")    ;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
class  Rectangle : Shape
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public override void Draw()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Rectangle.Draw");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
class  Square : Rectangle
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public override void Draw()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Square.Draw");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
class  MainClass
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Shape[] shp 
= new Shape[3];
InBlock.gif        Rectangle rect 
= new Rectangle();
InBlock.gif
InBlock.gif        shp[
0= new Shape();
InBlock.gif        shp[
1= rect;
InBlock.gif        shp[
2= new Square();
InBlock.gif
InBlock.gif        shp[
0].Draw();
InBlock.gif        shp[
1].Draw();
InBlock.gif        shp[
2].Draw();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gifOutput:
None.gifShape.Draw
None.gifRectangle.Draw
None.gifSquare.Draw
None.gif
None.gifHiding parent functions 
using   " new "
None.gifYou can define 
in  a child  class  a  new  version of a function, hiding the one which  is   in   base   class . A  new  keyword  is  used to define a  new  version. Consider the example below, which  is  a modified version of the above example and note the output  this  time, when I replace the  override  keyword with a  new  keyword  in  the Rectangle  class .
None.gif
None.gif
class  Shape
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public virtual void Draw()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Shape.Draw")    ;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
class  Rectangle : Shape
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public new void Draw()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Rectangle.Draw");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
class  Square : Rectangle
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
//wouldn't let you override it here
InBlock.gif
    public new void Draw()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Square.Draw");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
class  MainClass
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Using Polymorphism:");
InBlock.gif        Shape[] shp 
= new Shape[3];
InBlock.gif        Rectangle rect 
= new Rectangle();
InBlock.gif
InBlock.gif        shp[
0= new Shape();
InBlock.gif        shp[
1= rect;
InBlock.gif        shp[
2= new Square();
InBlock.gif
InBlock.gif        shp[
0].Draw();
InBlock.gif        shp[
1].Draw();
InBlock.gif        shp[
2].Draw();
InBlock.gif
InBlock.gif        Console.WriteLine(
"Using without Polymorphism:");
InBlock.gif        rect.Draw();
InBlock.gif        Square sqr 
= new Square();
InBlock.gif        sqr.Draw();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gifOutput:
None.gifUsing Polymorphism
None.gifShape.Draw
None.gifShape.Draw
None.gifShape.Draw
None.gifUsing without Polymorphism:
None.gifRectangle.Draw
None.gifSquare.Draw
None.gif
None.gifThe polymorphism doesn
' t take the Rectangle class ' s Draw method  as  a polymorphic form of the Shape ' s Draw method. Instead, it considers it a different method. So, to avoid the naming conflict between parent and child, we have used the new modifier.
None.gif

None.gifNote: You cannot use the two version of a method 
in  the same  class , one with  new  modifier and other with  override  or  virtual . As  in  the above example, I cannot add another method named Draw  in  the Rectangle  class  which  is  a  virtual  or  override  method. Also,  in  the Square  class , I can ' t override the virtual Draw method of the Shape class.
None.gif
Calling  base   class  members
None.gifIf the child 
class  has the data members with same name  as  that of  base   class , to avoid naming conflicts,  base   class  data members and functions are accessed  using  a keyword  base . See  in  the examples how the  base   class  constructors are called and how the data members are used.
None.gif
None.gif
public  Child( int  val) : base (val)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    myVar 
= 5;
InBlock.gif    
base.myVar;
ExpandedBlockEnd.gif}

None.gif
None.gifOR
None.gif
None.gif
public  Child( int  val)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
base(val);
InBlock.gif    myVar 
= 5 ;
InBlock.gif    
base.myVar;
ExpandedBlockEnd.gif}

None.gif
None.gifFuture Additions:
None.gifThis article 
is  just a quick overwiew of the C# language so that you can just become familiar with the langauge features. Although I have tried to discuss almost all the major concepts  in  C#  in  a brief and comprehensive way with code examples, I think there  is  lot much to be added and discussed.
None.gif
None.gifIn the future, I would like to add more commands and concepts not yet discussed including events and so forth. I would also like to write about Windows programming 
using  C#  for  beginners.
None.gif
None.gifReferences
None.gifour most commonly known MSDN 
None.gifInside C# by Tom Archer 
None.gifA Programmer
' s Introduction to C# by Eric Gunnerson 
None.gif
Beginning C# by Karli Watson 
None.gifProgramming C# (O
' Reilly) 
None.gif
About the Author
None.gifAisha 
is  a Master of Science  in  Computer Science from Quaid - i - Azam Univeristy. She has worked  in  VC ++   6 , MFC, ATL, COM / DCOM, ActiveX, C ++ , SQL, and so forth. These days she  is  working on .NET framework and C#. Inspired with nature, she loves to seek knowledge. She  is  also fond of travelling. She keeps a free source code and articles Web site at http: // aishai.netfirms.com.

转载于:https://www.cnblogs.com/Dicky/archive/2005/03/21/122574.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值