一、類型的各種成員

分類

成員

是否支持靜態(static)

是否可反射訪問

説明

1. 數據成員

常量(Constants)

✅(隱式靜態)

✅(有限,通常是編譯期替換)

const定義,編譯時確定,不可更改,隱式是靜態的

字段(Fields)

✅(支持靜態字段)


變量,可以是實例字段或靜態字段

2. 函數成員

方法(Methods)

✅(支持靜態方法)


行為邏輯,可以是實例方法或靜態方法

操作符重載(Operator Overloads)

✅(必須靜態)


自定義操作符行為,如 +, ==,必須是靜態方法

轉換運算符(Conversion Operators)

✅(必須靜態)


自定義類型間轉換,如 implicit operator int(MyClass c),必須是靜態方法

3. 封裝與訪問成員

屬性(Properties)

✅(支持靜態屬性)


帶有 get/set的“智能字段”

4. 事件成員

事件(Events)

✅(支持靜態事件)


用於發佈/訂閲通知機制,如 event Action OnChange;

5. 構造與初始化成員

實例構造器(Instance Constructors)

❌(只能是實例)


用於創建對象實例,如 public MyClass() { }

類型構造器(靜態構造器 / Type Initializer)

✅(靜態,唯一)


用於初始化靜態成員,自動調用,如 static MyClass() { }

6. 類型本身(元數據)

類型(Type)


✅(核心)

表示一個類型本身,是反射和動態系統的核心,如 typeof(MyClass)

常量

定義:使用 const關鍵字聲明,值在編譯時確定且不可更改

public class MyConstants
{
    public const int MaxValue = 100;
}

字段

定義:類或結構體中聲明的變量,可以是 實例字段靜態字段

public class Person
{
    public static int Count = 0;           // 靜態字段
    public string Name;                    // 實例字段
}

實例構造器

定義:用於創建類型實例的特殊方法,如 public MyClass() { }

public class MyClass
{
    public MyClass() { }
    public MyClass(int id) { }
}

類型構造器

用於初始化靜態成員,每個類型有且只有一個,無參數,自動調用。

public class Logger
{
    static Logger() { Console.WriteLine("靜態構造器被調用"); }
}

方法

定義:類中定義的行為或邏輯單元,可以是 實例方法靜態方法

public class Calculator
{
    public static int Add(int a, int b) => a + b;
    public int Multiply(int a, int b) => a * b;
}

操作符重載

定義:自定義操作符行為,如 +, -, ==, !=等。 必須為靜態方法

public class Vector
{
    public static Vector operator +(Vector a, Vector b) { ... }
}

轉換符重載

定義:定義類型之間的 隱式或顯式轉換,如 implicit operator int(MyClass c) 必須為靜態方法

public class MyClass
{
    public static implicit operator int(MyClass c) => 42;
}

屬性

定義:一種帶有 get和/或 set訪問器的成員,提供對字段的受控訪問。

public class Account
{
    public static decimal InterestRate { get; set; }
    public string Owner { get; set; }
}

事件

定義:允許訂閲和觸發通知的成員,通常是委託類型,如 event Action OnChange;

public class Button
{
    public static event Action OnClick;
}

類型

定義:表示一個類型本身,是反射和動態系統的核心,比如 typeof(string)obj.GetType()

Type t = typeof(string);
TypeInfo ti = t.GetTypeInfo();

二、類型的可見性

訪問修飾符

説明

可訪問範圍

public

公開的,任何代碼都可以訪問

任何地方(本程序集、其他程序集)

private

私有的,只有當前類內部可以訪問

僅限當前類內部

protected

受保護的,當前類及其派生類可以訪問

當前類 + 子類(無論是否在同一個程序集)

internal

內部的,只有當前程序集(Assembly)內可以訪問

同一個程序集內(如同一個項目)

protected internal

受保護或內部的(二選一即可訪問)  即:protected internal的並集

當前程序集內任意代碼任意程序集中的子類

private protected

私有且受保護的(僅當前程序集中的子類可訪問)

C#要求原始成員和重寫成員具有相同的可訪問性。

class BaseClass
{
    // 原始方法是 public
    public virtual void Show()
    {
        Console.WriteLine("Base Show");
    }
}

class DerivedClass : BaseClass
{
    // 錯誤:嘗試將 public 方法重寫為 protected(縮小了可訪問性)
    // 編譯錯誤 “DerivedClass.Show()”: 當重寫“public”繼承成員“BaseClass.Show()”時,無法更改訪問修飾符
    protected override void Show() 
    {
        Console.WriteLine("Derived Show");
    }
}

三、幾個關鍵字

關鍵字

修飾類型

修飾成員

主要作用

abstract


方法/屬性/事件

強制派生類實現

virtual


方法/屬性/事件

允許派生類重寫

override


方法/屬性/事件

重寫基類虛成員

sealed


重寫的方法

防止進一步繼承/重寫

new

嵌套類型

方法/屬性/字段

顯式隱藏基類成員

  • 普通方法:不能重寫,適合固定邏輯。
  • 虛方法:可以重寫,適合“有默認實現,但允許定製”的場景。
  • 抽象方法:沒有實現,強制子類實現,適合“只定義接口,不提供默認行為”的場景。

abstract的例子

using System;

// 抽象類 - 不能實例化
public abstract class Shape
{
    // 抽象類可以有字段,但不能有抽象字段
    protected string name;

    // 抽象屬性 - 必須在派生類中實現
    public abstract double Area { get; }
    public abstract double Perimeter { get; }

    // 抽象方法 - 必須在派生類中實現
    public abstract void Draw();

    // 普通方法 - 可以提供默認實現
    public void DisplayInfo()
    {
        Console.WriteLine($"形狀: {name}, 面積: {Area}, 周長: {Perimeter}");
    }

    //  抽象類不能有抽象構造函數
    // public abstract Shape(); // 編譯錯誤
}

// 具體實現類
public class Circle : Shape
{
    private double radius;

    public Circle(double r)
    {
        name = "圓形";
        radius = r;
    }

    // 必須實現所有抽象成員
    public override double Area => Math.PI * radius * radius;

    public override double Perimeter => 2 * Math.PI * radius;

    public override void Draw()
    {
        Console.WriteLine($"繪製半徑為 {radius} 的圓形");
    }
}

public class Rectangle : Shape
{
    private double _width,_height;
    public Rectangle(double width, double height)
    {
        name = "矩形";
        _width = width;
        _height = height;
    }
    public override double Area => _width * _height;

    public override double Perimeter => 2 * (_width + _height);

    public override void Draw()
    {
        Console.WriteLine($"繪製 {width}x{height} 的矩形");
    }
}

virtual 例子

using System;

public class Animal
{
    // 虛屬性 - 可以在派生類中重寫
    public virtual string Species { get; set; } = "未知動物";

    // 虛方法 - 可以在派生類中重寫
    public virtual void MakeSound()
    {
        Console.WriteLine("動物發出聲音");
    }

    // 虛方法帶默認實現
    public virtual void Move()
    {
        Console.WriteLine("動物移動");
    }

    // 不能將字段聲明為virtual
    // public virtual string name; // 編譯錯誤
}

public class Dog : Animal
{
    public Dog()
    {
        Species = "犬科";
    }

    // 重寫虛方法
    public override void MakeSound()
    {
        Console.WriteLine("汪汪汪!");
    }

    public override void Move()
    {
        Console.WriteLine("狗用四條腿奔跑");
    }
}

public class Bird : Animal
{
    public Bird()
    {
        Species = "鳥類";
    }

    public override void MakeSound()
    {
        Console.WriteLine("啾啾啾!");
    }

    public override void Move()
    {
        Console.WriteLine("鳥在天空中飛翔");
    }
}

sealed例子

using System;

// 密封類 - 不能作為基類
public sealed class SealedClass
{
    public void Method()
    {
        Console.WriteLine("密封類的方法");
    }
}

// 編譯錯誤 - 不能繼承密封類
// public class DerivedSealed : SealedClass { } // 錯誤

// 密封方法示例
public class BaseVehicle
{
    public virtual void StartEngine()
    {
        Console.WriteLine("引擎啓動");
    }
}

public class Car : BaseVehicle
{
    // 密封重寫的方法 - 不能再被重寫
    public sealed override void StartEngine()
    {
        Console.WriteLine("汽車引擎啓動 - 帶鑰匙點火");
    }

    // 普通虛方法仍可被重寫
    public virtual void Drive()
    {
        Console.WriteLine("駕駛汽車");
    }
}

public class SportsCar : Car
{
    // 編譯錯誤 - 不能重寫密封方法
    // public override void StartEngine() { } // 錯誤

    // 可以重寫其他虛方法
    public override void Drive()
    {
        Console.WriteLine("高速駕駛跑車");
    }
}