首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 方法深度解析:參數傳遞 (ref/out/params)、多型 (virtual/override/sealed/abstract) 與外部方法

     編輯:關於C語言

方法分類與存取修飾詞

  • 靜態方法:static,屬於類別,僅能存取靜態成員。
  • 實例方法:預設,屬於物件,可存取實例與靜態成員。
  • 五種存取層級:public, protected, internal, protected internal, private。

四種參數傳遞模式

模式關鍵字行為呼叫端需初始化
傳值(無)複製值 (實值型別) 或複製參考 (參考型別)是
傳址ref傳遞變數位址,方法內修改影響原變數是
輸出out類似 ref,但呼叫端不需初始化;方法內必須賦值否
參數陣列params將可變數量引數封裝為陣列,僅能用於最後一個參數視情況

傳值 vs 傳址 範例


static void SwapRef(ref int x, ref int y) { int t=x; x=y; y=t; }
static void SwapVal(int x, int y) { int t=x; x=y; y=t; }

static void Main()
{
    int i=1, j=2;
    SwapRef(ref i, ref j); Console.WriteLine($"Ref: i={i}, j={j}"); // 2, 1
    SwapVal(i, j);       Console.WriteLine($"Val: i={i}, j={j}"); // 2, 1 (未改變)
}

參考型別傳值的陷阱


class Element { public int Number = 10; }

static void ChangeField(Element e) { e.Number = 100; }      // 修改欄位 -> 影響原物件
static void ChangeRef(Element e) { e = new Element { Number = 100 }; } // 修改參考 -> 不影響原變數

static void Main()
{
    var obj = new Element();
    ChangeField(obj); Console.WriteLine(obj.Number); // 100
    ChangeRef(obj);   Console.WriteLine(obj.Number); // 100 (未變)
}

結論:傳值傳遞的是參考的副本,可修改物件內部狀態,無法替換呼叫端的變數指向。

out 多重回傳值範例


static void SplitName(string full, out string first, out string last)
{
    var parts = full.Split(' ');
    first = parts[0];
    last = parts.Length > 1 ? parts[1] : "";
}

static void Main()
{
    SplitName("Cornfield Lee", out var f, out var l);
    Console.WriteLine($"{f} | {l}"); // Cornfield | Lee
}

params 參數陣列範例


static int Sum(params int[] nums)
{
    int s = 0; foreach (var n in nums) s += n; return s;
}
static void Main()
{
    Console.WriteLine(Sum(1,2,3,4,5));        // 15
    Console.WriteLine(Sum(new int[]{10,20})); // 30
}

方法多載

  • 同名方法,參數列表不同 (型別、數量、順序、ref/out/params 差異)。
  • 回傳型別不同不構成多載。
  • 編譯期靜態繫結 (依靜態型別決定呼叫哪個多載)。

方法繼承與多型關鍵字

關鍵字用途限制
virtual基底類別宣告可被覆寫的方法不可 static、private
override衍生類別提供新實作必須覆寫 virtual/abstract/override 方法,簽章完全一致
sealed override封鎖繼承鏈進一步覆寫僅能用於 override 方法
abstract介面式宣告,無實作,強制衍生類別實作所屬類別必須 abstract,不可 static/private
new隱藏基底成員 (非多型)靜態繫結,base.Method() 仍可呼叫被隱藏版本

虛擬/覆寫/隱藏 行為示範


class Parent
{
    public void F() => Console.WriteLine("Parent.F"); // 非虛擬
    public virtual void G() => Console.WriteLine("Parent.G");
}
class Child : Parent
{
    public new void F() => Console.WriteLine("Child.F"); // 隱藏
    public override void G() => Console.WriteLine("Child.G"); // 覆寫
}
static void Main()
{
    Child c = new Child();
    Parent p = c;
    p.F(); c.F(); // Parent.F / Child.F (靜態繫結看變數型別)
    p.G(); c.G(); // Child.G / Child.G (動態繫結看物件型別)
}

sealed override 防止進一步覆寫


class A { public virtual void M() => Console.WriteLine("A"); }
class B : A { public sealed override void M() => Console.WriteLine("B"); }
class C : B { /* public override void M() => ... */ } // 編譯錯誤:無法覆寫 sealed 方法

抽象方法與抽象類別


abstract class Base
{
    public abstract void DoWork(); // 無實作
    public virtual void Optional() => Console.WriteLine("Base.Optional");
}
class Derived : Base
{
    public override void DoWork() => Console.WriteLine("Derived.Work");
    // Optional 可選擇覆寫或保留基底實作
}
  • 抽象方法可覆寫虛擬方法 (abstract override),強制下一層重新實作。
  • 抽象類別可無抽象方法 (單純防止實例化)。

外部方法 (extern) 與 P/Invoke

呼叫非 C# 實作的函式 (如 Win32 API)。需配合 DllImport 屬性指定 DLL 與封送規則。


using System.Runtime.InteropServices;

class Win32
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int MessageBox(IntPtr hWnd, string text, string caption, int type);
}

class Program
{
    static void Main() => Win32.MessageBox(IntPtr.Zero, "Hello from C#!", "P/Invoke", 0);
}

執行後彈出原生訊息方塊。extern 方法不可為 abstract。

總結

精通參數傳遞語意 (ref/out/params)、多型機制 (virtual/override/sealed/abstract/new) 與外部互操作,是撰寫高效、可維護、可擴充 C# 程式碼的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved