方法

方法在類中用於執行計算或其它行為的成員.聲明格式:

method-header

  method-body

其中方法頭method-header的格式:

attributes method-modifiers return-type member-name (formal-parameter-list)

傳遞給方法的參數在方法的形式參數表formal-parameter-list中聲明

在方法的聲明中,至少應包括方法名稱,修飾符和參數類型,返回值和參數名則不是必須的.

注意:方法名member-name不應與同一個類中的其它方法同名,也不能與類中的其它成員名稱

相同.

修飾符

方法的修飾符method-modifier可以是:

new

public

protected

internal

private

static

virtual

sealed

override

abstract

extern

對於使用了atstract和extern修飾符的方法,方法的執行體method-body僅僅只有一個簡單

的分號.其它所有的方法執行體中應包含調用該方法所需要執行的語句.

返回值

方法的返回值的類型可以是合法的C#的數據類型.C#在方法的執行部分通過return語句得到

返回值,如

using System;

class Test

{

  public int max(int x,int y)

  {

    if(x>y)

      return x;

    else

      return y;

  }

}

public void Main()

{

  Console.WriteLine("the max of 6 and 8 is:{0}",max(6,8));

}

如果在return後不跟隨任何值,方法返回值是void型的.

方法中的參數

C#中方法的參數有四种類型:

值參數,不含任何修飾符.

引用型參數,以ref修飾符聲明.

輸出參數,以out修飾符聲明.

數組型參數,以params修飾符聲明.

值參數

當利用值向方法傳遞參數時,編譯程序給實參的值做一份拷貝,並且將此拷貝傳遞給該方法.

被調用的方法不會修改內存中實參的值,所以使用值參數時,可以保證實際值是安全的.

下面的例子可以說明這個問題

using system;

class Test

{

  static void Swap(int x,int y)

  {

    int temp=x;

    x=y;

    y=temp;

  }

  static void Main()

  {

    int i=1,j=2;

    Swap(i,j);

    Console.WriteLine("i={0},j={1}",i,j);

  }

}

程序輸出的結果是:

i=1,j=2

程序並沒有達到交換的目的.

引用型參數

和值參不同的是,引用型參數並不開辟新的內存區域.當利用引用型參數向方法傳遞形參時,

編譯程序將把實際值在內存中的地址傳遞給方法.

下面的例子有說明這個

using System;

class Test

{

  static void Swap(ref int x,ref int y)

  {

    int temp=x;

    x=y;

    y=temp;

  }

  static void Main()

  {

    int i=1,j=2;

    Swap(ref i,ref j);

    Console.WriteLine("i={0},j={1}",i,j);

  }

}

程序運行的輸出結果是:

i=2,j=1

在方法中使用引用型參數,會經常可能多個變量名指向同一處內存地址.見下面的例子:

using System;

using System.Collections.Generic;

using System.Windows.Forms;

namespace WindowsApplication2

{

    class A

    {

        public string s="ssss";

        void F(ref string a, ref string b)

        {

            s = "One";

            a = "Two";

            b = "Three";

        }

        public void G()

        {

            F(ref s, ref s);

        }

        public void R()

        {

            Console.WriteLine("S:{0}", s);

        }

    }

    class T

    {

        public static void Main()

        {

            A a=new A();

            a.G();

            a.R();

        }

    }

}

程序運行的結果是

S:Three

在方法G對F的調用過程中,S的引用被同時傳遞給了a和b.此時,s,a,b同時指向了同一塊內存

區域.

輸出參數

與引用型參數類似,輸出型參數也不開辟新的內存區域,與引用型參數的差別在於,調用方法

前無需對變量進行初始化.輸出型參數用於傳遞方法返回數據.

out修飾符後應跟隨與形參的類型相同的類型聲明.在方法返回後,傳遞的變量被認為經過了

初始化.

using System;

class Test

{

  static void SplitPath(string path,out string dir,out string name)

  {

    int i=path.Length;

    while(i>0)

    {

      char ch=path[i-1];

      if(ch=='\\' || ch=='/' || ch==':') break;

      i--;

    }

    dir=path.Substring(0,i);

    name=path.Substring(i);

  }

  static void Main()

  {

    string dir,name;

    SplitPath("c:\\Window\\System\\hello.txt",out dir,out name);

    Console.WriteLine(dir);

    Console.WriteLine(name);

  }

}

程序輸出結果:

c:\Windwo\System\

hello.txt

我們看到,變量dir和name在傳遞給SplitPath之前並未初始化,在調用之後它們則有了明確

的值.

數組型參數

如果形參表中包含了數組型參數,那麼它必須在參數表中位於最後.另外,參數只允許是一維

數組.比如,string[]和string[][]類型都可以作為數組型參數,而string[,]則不能.最後數

組型參數不能再有ref和out修飾符.

using System;

class Test

{

  static void F(params int[] args)

  {

    Console.WriteLine("Array contains {0} elements:",args.Length);

    foreach (int i in args) Console.Write("{0},",i);

    Console.WriteLine();

  }

  public static void Main()

  {

    int[] a={1,2,3};

    F(a);

    F(10,20,30,40);

    F();

  }

}

程序運行結果:

Array contains 3 elements:

1,2,3,

Array contains 4 elements:

10,20,30,40,

Array contains 0 elements:

靜態和非靜態的方法

C#的類定義中可以包含兩种方法:靜態的和非靜態的.使用了static修飾符的方法為靜態方

法,反之則是非靜態的.

靜態方法是一种特殊的成員方法,它不屬於類的某一個具體的實例.非靜態方法可以訪問類

中的任何成員,而靜態方法只能訪問類中的靜態成員.

下面這個列子說明這一點.

class A

{

  int x;

  static int y;

  static int F()

  {

    x=1; //錯誤,不允許訪問

    y=2; //正確,允許訪問

  }

}

在這個類定議中,靜態方法F()可以訪問類中靜態成員s,但不能訪問非靜態的成員x.這是因

為,x作為非靜態成員,在類的每個實例中都占有一個存儲(或者說有一個副本),而靜態方法

是類所共享的,它無法判斷出當前的x屬於那個類的實例.所以不知道應該到內存的哪個地址

去讀取當前x的值.而y是靜態成員,所有類的實例都公用一個副本,靜態方法F使用它就不存

什麼問題.

是不是靜態方法就無法識別類的實例了呢?答案:不是.

我下面看一下有關windows窗口的例子

using System;

class Window

{

  public string m_caption;  //窗口的標題

  public bool IsActive;     //窗口是否被激活

  public handle m_handle;   //窗口的句柄

  public static int m_total;//當前打開的窗口數目

  public handle Window()

  {

    m_total++;

    return m_handle;

  }

  ~Window()

  {

    m_total--;

  }

  public static string GetWindowCaption(Window w)

  {

    return w.m_caption;

  }

}

分析一下上面例子中的代碼,每個窗口都有窗口標題m_caption,窗口句柄m_handle,窗口是

否激活IsActive三個非靜態的數據成員(窗口句柄是Windows操作系統中保存窗口相關信息

的一种數據結構,我們在這個例子中簡化了對句柄的使用).系統中總共打開窗口的數目

m_total作為一個靜態成員.每個窗口調用構造函數創建,這時候m_total的值加1.窗口關閉

或因為其它行為撤消時,通過析構函數m_total的值減1.我們要注意窗口類的靜態方法

GetWindowCaption(Window w).這里它通過參數w將對像傳遞給方法執行,這樣它就可以通過

具體實例中的類的實例指明調用的對像,這時它可以訪問具體實例中的成員,無論是靜態成

員還是非靜態成員.

方法的重載

類中兩個以上的方法(包括隱藏的繼承而來的方法),取的名字相同,只要使用的參數類型或

者參數個數不同,編譯器便知道在何种情況下應該調用哪個方法,這就叫做方法的重載.

下面看個例子

using System;

class Student

{

    public string s_name;

    public int s_age;

    public float s_weight;

    public Student(string n, int a, float w)

    {

        s_name = n;

        s_age = a;

        s_weight = w;

    }

    public int max(int x, int y)

    {

        if (x > y) return x;

        else return y;

    }

    public float max(float x, float y)

    {

        if (x > y) return x;

        else return y;

    }

}

class test

{

    public static void Main()

  {

    Student s1=new Student("Mike",21,70);

    Student s2=new Student("John",21,70);

    if (s1.max(s1.s_age, s2.s_age) == s1.s_age)

        Console.WriteLine("{0} age is bigger than {1}.", s1.s_name, s2.s_name);

    else

        Console.WriteLine("{0} age is smaller than {1}.", s1.s_name,

s2.s_name);

    if (s1.max(s1.s_weight, s2.s_weight) == s1.s_weight)

        Console.WriteLine("{0} age is bigger than {1}.", s1.s_name, s2.s_name);

    else

        Console.WriteLine("{0} age is smaller than {1}.", s1.s_name,

s2.s_name);

  }

}

程序運行的結果:

Mike age is bigger than John.

Mike age is bigger than John.

操作符重載

C#中,操作符重載總是在類中進行聲明,並且通過調用類的成員方法來實現.操作作重載的聲

明的格式為:

type  operator  operator-name  (formal-param-list)

C#中,下列操作符都是可以重載的

+  -  !  ~  ++  --  TRUE  FALSE

*  /  %  |  ^   <<  >>    ==   !=   >   <   >=  <=

但也有一些操作符是不允許進行重載的,如:

=,&&,||,?:,NEW,TYPEOF,SIZEOF,IS

一元操作符重載,一元操作符重載時操作符只作個用於一個對像,此時參數表為空,當前對像

作為操作符的單操作數.

下面我們舉一個角色類遊戲中經常遇到的例子.扮演的角色有內力,體力,經驗值,剩餘體力,

剩餘內力五個屬性,每當經驗值達到一定程度時,角色便會升級,體力,內力上升,剩餘體力和

內力補滿."升級"我們使用重載操作符"++"來實現.

using System;

class Player

{

    public int neili;

    public int tili;

    public int jingyan;

    public int neili_r;

    public int tili_r;

    public Player()

    {

        neili = 10;

        tili = 50;

        jingyan = 0;

        neili_r = 50;

        tili_r = 50;

    }

    public static Player operator ++(Player p)

    {

        p.neili = p.neili + 50;

        p.tili = p.tili + 100;

        p.neili_r = p.neili;

        p.tili_r = p.tili;

        return p;

    }

    public void Show()

    {

        Console.WriteLine("Tili:{0}", tili);

        Console.WriteLine("Jingyan:{0}", jingyan);

        Console.WriteLine("Neili:{0}", neili);

        Console.WriteLine("Tili_Full:{0}", tili_r);

        Console.WriteLine("Neili_Full:{0}", neili_r);

    }

}

class Test

{

    public static void Main()

    {

        Player man = new Player();

        man.Show();

        man++;

        Console.WriteLine("Now upgrading...");

        man.Show();

    }

}

程序輸出結果:

Tili:50

Jingyan:0

Neili:10

Tili_Full:50

Neili_Full:50

Now upgrading...

Tili:150

Jingyan:0

Neili:60

Tili_Full:150

Neili_Full:60

二元操作符重載

大多數情況下我們使用二元操作符重載.這時參數表中有一個參數,當前對像作為該操作符

的左操作數,參數作為操作符的右操作數.

下面是一個二元操作符重載的例子.即笛卡兒坐標相加.

using System;

class DKR

{

    public int x, y, z;

    public DKR(int vx, int vy, int vz)

    {

        x = vx;

        y = vy;

        z = vz;

    }

    public static DKR operator +(DKR d1, DKR d2)

    {

        DKR dkr = new DKR(0, 0, 0);

        dkr.x = d1.x + d2.x;

        dkr.y = d1.y + d2.y;

        dkr.z = d1.z + d2.z;

        return dkr;

    }

}

class Test

{

    public static void Main()

  {

    DKR d1 = new DKR(3,2,1);

    DKR d2 = new DKR(0, 6, 5);

    DKR d3 = d1 + d2;

    Console.WriteLine("The 3d location of d3 is:{0},{1},{2}",d3.x,d3.y,d3.z);

  }

}

程序輸出結果:

The 3d location of d3 is:3,8,6


申明

非源创博文中的内容均收集自网上,若有侵权之处,请及时联络,我会在第一时间内删除.再次说声抱歉!!!