zoukankan      html  css  js  c++  java
  • C#速成(Quick C#)

    标题:C#速成(Quick C#)
    原作者:Aisha Ikram
    翻译:bigqiang
    网站:http://www.fazhuan.com/
    信箱:bigqiang@sina.com
    --------------------------------------------------------------------------------

    使用环境: .NET, C#, Win XP, Win 2000

    绪论

    C#是这样的一种语言,具有C++的特点,象Java一样的编程风格, 并且象Basic一样的快速开发模型。如果你已经知道了C++,本文会在不到一个小时的时间内让你迅速掌握C#的语法。熟悉Java的括会更好,因为Java的程序结构、打包(Packages)和垃圾收集的概念有助于你更快的了解C#。因此在讨论C#的构造时,我会假定你了解C++。

    本文会讨论C#语言的构造与特点,同时会采取简洁的和你能理解的方式使用些代码示例,我们会尽量让你能稍微看看这些代码就能理解这些概念。

    注意:本文不是为C#高手(C# gurus)所写. 这是针对在C#学习上还是初学者的文章。

    下面是将要讨论的C#问题的目录:

    程序结构
    命名空间
    数据类型
    变量
    运算符和表达式
    枚举
    语句(Statements )
    类(Classes)和结构(Structs)
    修饰符(Modifiers)
    属性(Properties)
    接口(Interfaces)
    方法参数(Function Parameters)
    数组(Arrays)
    索引器(Indexers)
    装箱及拆箱操作
    委托(Delegates)
    继承和多态

    下面的内容将不会在被讨论之列:

    C++与C#谁更通用
    诸如垃圾回收、线程以及文件处理等概念
    数据的类型转换
    异常处理
    .NET库

    -------------------
    程序结构
    -------------------
    这一点象C++,C#是一种对大小写字母敏感的语言,分号“;”是语句间的分隔符。与C++不同的是,C#当中声明代码文件(头文件)与实现代码文件(cpp文件)不是独立存在的,所有代码(类声明和类实现)都位于一个扩展名为cs的文件内。

    让我们瞧瞧C#当中的 Hello world 程序是怎样的。

    using System;

    namespace MyNameSpace

    {

    class HelloWorld

    {
    static void Main(string[] args)
    {
    Console.WriteLine ("Hello World");
    }
    }

    }

    在C#当中的每样东西都被封装到一个类中,C#的类又被封装到一个命名空间当中(就象一个文件夹中的文件)。类似于 C++,main方法是你的程序的入口点。C++的main函数调用名称是"main",而C#的main函数是以大写字母M为起点的名称是"Main"。

    没有必要把分号分隔符放在类语句块或者结构定义语句块后。这在C++当中被要求,但在C#当中却不是。

    -------------------
    命名空间
    -------------------
    每一个类都被包装进一个命名空间。命名空间的概念与C++的完全相同,但在C#当中使用命名空间的频率较C++还高。你可以使用点限定符(dot qulifier)访问一个类。在上面的hello world程序当中MyNameSpace就是一个命名空间。

    现在思考这样的一个问题,你想从某些别的类的命名空间当中来访问HelloWorld这个类该如何操作。
    这有一个例子:

    using System;
    namespace AnotherNameSpace
    {
    class AnotherClass
    {
    public void Func()
    {
    Console.WriteLine ("Hello World");
    }
    }
    }

    现在,从你的HelloWorld类里你能象这样去访问上面的这个AnotherNameSpace的命名空间:

    using System;
    using AnotherNameSpace; // you will add this using statement
    namespace MyNameSpace
    {
    class HelloWorld
    {
    static void Main(string[] args)
    {
    AnotherClass obj = new AnotherClass();
    obj.Func();
    }
    }
    }

    在.NET库当中,System是位于顶层的命名空间,别的命名空间都存在这个命名空间之下。默认状态下,存在一个全局的命名空间,因此一个在命名空间外定义的类将直接在这个全局命名空间之下;因此,你能在没有任何点限定符的情况下访问这个类。

    你也可以象下面这样定义嵌套的命名空间。

    Using
    C++当中的"#include"指示被C#的"using"关键字取代,它后面跟着一个命名空间的名字。正如上面的"using System"。"System"是别的所有被封装的命名空间和类中最底层的命名空间。所有对象的基类都是System命名空间内的Object类派生的。

    -------------------
    变量
    -------------------
    除以下并别外,C#当中的变量几乎与C++同:

    与C++不同,C#变量被访问之前必须被初始化;否则编译时会报错。因此,访问一个未初始化变量是不可能的事。
    C#中你不会访问到一个不确定的指针。(译者注:严格说起来C#已经把指针概念异化,限制更严格。所以有些资料上会说C#取消了指针概念)
    一个超出数组边界的表达式是不可访问的。
    C#中没有全局的的变量或全局函数,全局方式的操作是通过静态函数和静态变量来实现的。


    -------------------
    数据类型
    -------------------
    所有C#数据类型都派生自基类Object。这里有两类数据类型:

    基本型/内置型 用户自定义型

    下面一个C#内置类型列表:

    类型 字节数 解释
    byte 1 无符号字节型
    sbyte 1 有符号字节型
    short 2 有符号短字节型
    ushort 2 无符号短字节型
    int 4 有符号整型
    uint 4 无符号整型
    long 8 有符号长整型
    ulong 8 无符号长整型
    float 4 浮点数
    double 8 双精度数
    decimal 8 固定精度数
    string unicode字串型
    char unicode字符型
    bool 真假布尔型

    注意:C#当中的类型范围与C++有所不同;例如,C++的long型是4个字节,而在C#当中是8个字节。同样地,bool型和string型都不同于C++。bool型只接受true和false两种值。不接受任何整数类型。

    用户定义类型包括:

    类类型(class)
    结构类型(struct)
    接口类型(interface)

    数据类型的内存分配形式的不同又把它们分成了两种类型:

    值类型(value Types)
    引用类型(Reference Types)

    值类型:
    值类型数据在栈中分配。他们包括:所有基本或内置类型(不包括string类型)、结构类型、枚举类型(enum type)

    引用类型:
    引用类型在堆中分配,当它们不再被使用时将被垃圾收集。它们使用new运算符来创建,对这些类型而言,不存在C++当中的delete操作符,根本不同于C++会显式使用delete这个运算符去释放创建的这个类型。C#中,通过垃圾收集器,这些类型会自动被收集处理。

    引用类型包括:类类型、接口类型、象数组这样的集合类型类型、字串类型、枚举类型

    枚举类型与C++当中的概念非常相似。它们都通过一个enum关键字来定义。

    示例:

    enum Weekdays
    {
    Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday
    }

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

    示例:

    struct Date
    {
    int day;
    int month;
    int year;
    }

    class Date
    {
    int day;
    int month;
    int year;
    string weekday;
    string monthName;
    public int GetDay()
    {
    return day;
    }
    public int GetMonth()
    {
    return month;
    }
    public int GetYear()
    {
    return year;
    }
    public void SetDay(int Day)
    {
    day = Day ;
    }
    public void SetMonth(int Month)
    {
    month = Month;
    }
    public void SetYear(int Year)
    {
    year = Year;
    }
    public bool IsLeapYear()
    {
    return (year/4 == 0);
    }
    public void SetDate (int day, int month, int year)
    {
    }
    ...
    }



    -------------------
    属性
    -------------------
    如果你熟悉C++面象对象的方式,你就一定有一个属性的概念。在上面示例当中,以C++的观点来看,Data类的属性就是day、month和year。用C#方式,你可以把它们写成Get和Set方法。C#提供了一个更方便、简单、直接的方式来访问属性。

    因此上面的类可以被写成:

    using System;
    class Date
    {
    public int Day{
    get {
    return day;
    }
    set {
    day = value;
    }
    }
    int day;

    public int Month{
    get {
    return month;
    }
    set {
    month = value;
    }
    }
    int month;

    public int Year{
    get {
    return year;
    }
    set {
    year = value;
    }
    }
    int year;

    public bool IsLeapYear(int year)
    {
    return year%4== 0 ? true: false;
    }
    public void SetDate (int day, int month, int year)
    {
    this.day = day;
    this.month = month;
    this.year = year;
    }
    }

    你可在这里得到并设置这些属性:

    class User
    {
    public static void Main()
    {
    Date date = new Date();
    date.Day = 27;
    date.Month = 6;
    date.Year = 2003;
    Console.WriteLine("Date: {0}/{1}/{2}", date.Day,
    date.Month,
    date.Year);
    }
    }




    -------------------
    修饰符
    -------------------
    你必须已经知道public、private、protected这些常在C++当中使用的修饰符。这里我会讨论一些C#引入的新的修饰符。

    readonly(只读)
    readonly修饰符仅在类的数据成员中使用。正如这名字所提示的,readonly 数据成员仅能只读,它们只能在构造函数或是直接初始化操作下赋值一次。readonly与const数据成员不同,const 要求你在声明中初始化,这是直接进行的。看下面的示例代码:

    class MyClass
    {
    const int constInt = 100; //直接初始化
    readonly int myInt = 5; //直接初始化
    readonly int myInt2; //译者注:仅做声明,未做初始化

    public MyClass()
    {
    myInt2 = 8; //间接的
    }
    public Func()
    {
    myInt = 7; //非法操作(译者注:不得赋值两次)
    Console.WriteLine(myInt2.ToString());
    }

    }

    sealed(密封)
    密封类不允许任何类继承,它没有派生类。因此,你可以对你不想被继承的类使用sealed关键字。

    sealed class CanNotbeTheParent
    {
    int a = 5;
    }

    unsafe(不安全)
    你可使用unsafe修饰符来定义一个不安全的上下文。在不安全的上下文里,你能写些如C++指针这样的不安全的代码。看下面的示例代码:

    public unsafe MyFunction( int * pInt, double* pDouble)
    {
    int* pAnotherInt = new int;
    *pAnotherInt = 10;
    pInt = pAnotherInt;
    ...
    *pDouble = 8.9;
    }




    -------------------
    interface(接口)
    -------------------

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

    using System;
    interface myDrawing
    {
    int originx
    {
    get;
    set;
    }
    int originy
    {
    get;
    set;
    }
    void Draw(object shape);
    }

    class Shape: myDrawing
    {
    int OriX;
    int OriY;

    public int originx
    {
    get{
    return OriX;
    }
    set{
    OriX = value;
    }
    }
    public int originy
    {
    get{
    return OriY;
    }
    set{
    OriY = value;
    }
    }
    public void Draw(object shape)
    {
    ... // do something
    }

    // class's own method
    public void MoveShape(int newX, int newY)
    {
    .....
    }

    }




    -------------------
    Arrays(数组)
    -------------------

    C#中的数组比C++的表现更好。数组被分配在堆中,因此是引用类型。你不可能访问超出一个数组边界的元素。因此,C#会防止这样类型的bug。一些辅助方式可以循环依次访问数组元素的功能也被提供了,foreach就是这样的一个语句。与C++相比,C#在数组语法上的特点如下:

    方括号被置于数据类型之后而不是在变量名之后。
    创建数组元素要使用new操作符。
    C#支持一维、多维以及交错数组(数组中的数组)。

    示例:

    int[] array = new int[10]; // 整型一维数组
    for (int i = 0; i < array.Length; i++)
    array[i] = i;

    int[,] array2 = new int[5,10]; // 整型二维数组
    array2[1,2] = 5;

    int[,,] array3 = new int[5,10,5]; // 整型的三维数组
    array3[0,2,4] = 9;

    int[][] arrayOfarray = = new int[2]; // 整型交错数组(数组中的数组)
    arrayOfarray[0] = new int[4];
    arrayOfarray[0] = new int[] {1,2,15};




    -------------------
    索引器
    -------------------

    索引器被用于写一个访问集合元素的方法,集合使用"[]"这样的直接方式,类似于数组。你所要做的就是列出访问实例或元素的索引清单。类的属性带的是输入参数,而索引器带的是元素的索引表,除此而外,他们二者的语法相同。

    示例:

    注意:CollectionBase是一个制作集合的库类。List是一个protected型的CollectionBase成员,储存着集合清单列表。
    class Shapes: CollectionBase
    {
    public void add(Shape shp)
    {
    List.Add(shp);
    }

    //indexer
    public Shape this[int index]
    {
    get {
    return (Shape) List[index];
    }
    set {
    List[index] = value ;
    }
    }
    }




    -------------------
    装箱和拆箱操作(Boxing/Unboxing)
    -------------------

    C#的装箱思想是全新的。上面提到过所有的数据类型,不论内置或用户自定义,全都从命名空间System的一个基类object派生出来。因此把基本的或者原始类型转换成object类型被称做装箱,反之,这种方式的逆操作被称为拆箱。

    示例:

    class Test
    {
    static void Main()
    {
    int myInt = 12;
    object obj = myInt ; // 装箱
    int myInt2 = (int) obj; // 拆箱
    }
    }

    示例展示了装箱和拆箱操作。一个整型值转换成object类型,然后又转换回整型。当一个值类型的变量需要转换成引用类型时,一个object的箱子会被分配容纳这个值的空间,这个值会被复制进这个箱子。拆箱与此相反,一个object箱子中的数据被转换成它的原始值类型时,这个值将被从箱中复制到适当的存储位置。

  • 相关阅读:
    时间及时间戳相互转换
    指针偏移
    C# TreeView模糊查找节点
    Checkedlistbox只能单选不能多选
    获取本机的IP地址
    检测插件是否已注册,注册插件
    知道内存中一个图片的指针IntPtr大小,转换成图片显示
    C# 判断点是否在矩形框内
    C# 从图片中截取一部分图片,并返回所截取的图片
    C# 管道通信 (client —— server)Framework2.0版本也可用
  • 原文地址:https://www.cnblogs.com/y0umer/p/3839333.html
Copyright © 2011-2022 走看看