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

C# Control 型別轉換與模式比對:is、as、switch 型別模式完整指南

     編輯:關於C語言

前言

WinForms/WebForms 開發常需遍歷控制項集合並針對特定型別執行邏輯。本文系統說明 Control 基類轉換為衍生型別的三種主流方式:is 型別模式、as 運算子、switch 型別模式,並對比傳統 GetType() 字串比較的缺陷。

問題情境


// 遍歷面板內所有控制項
foreach (Control ctrl in this.panel1.Controls)
{
    // 需針對 TextBox、Button 執行不同邏輯
}

方式一:is 型別模式 (C# 7+ 推薦)


foreach (Control ctrl in this.panel1.Controls)
{
    // 型別檢查 + 宣告變數,一步完成
    if (ctrl is TextBox txt)
    {
        txt.Text = "處理 TextBox";
        txt.BackColor = Color.Yellow;
    }
    else if (ctrl is Button btn)
    {
        btn.Text = "已處理";
        btn.Enabled = false;
    }
    else if (ctrl is Panel pnl && pnl.Name == "PanelX")
    {
        pnl.Visible = false;
        pnl.Enabled = false;
    }
}

優點:語法簡潔、型別安全、自動轉換、支援模式比對條件 (如 pnl.Name == "PanelX")

方式二:as 運算子 + null 檢查


foreach (Control ctrl in this.panel1.Controls)
{
    TextBox txt = ctrl as TextBox;
    if (txt != null)
    {
        txt.Text = "處理 TextBox";
        continue;
    }
    
    Button btn = ctrl as Button;
    if (btn != null)
    {
        btn.Text = "";
        continue;
    }
    
    Panel pnl = ctrl as Panel;
    if (pnl != null && pnl.Name == "PanelX")
    {
        pnl.Visible = false;
    }
}

優點:C# 所有版本支援、邏輯明確
缺點:較冗長、需手動 null 檢查

方式三:switch 型別模式 (C# 8+)


foreach (Control ctrl in this.panel1.Controls)
{
    switch (ctrl)
    {
        case TextBox txt:
            txt.Text = "處理 TextBox";
            break;
        case Button btn:
            btn.Text = "";
            break;
        case Panel pnl when pnl.Name == "PanelX":
            pnl.Visible = false;
            pnl.Enabled = false;
            break;
        case Panel pnl:
            pnl.Visible = true;
            pnl.Enabled = true;
            break;
    }
}

優點:多型別分派清晰、支援 when 守衛條件、結構化

傳統寫法缺陷分析

❌ GetType() 字串比較


// 反模式:脆弱、效能差、不支援繼承
if (ctrl.GetType().ToString() == "System.Windows.Forms.TextBox") 
{
    // 錯誤:繼承自 TextBox 的自訂類別會失敗
}

❌ typeof 比較


// 稍好但仍不支援繼承
if (ctrl.GetType() == typeof(TextBox)) 
{
    // 自訂類別 MyTextBox : TextBox 會回傳 false
}

正確型別檢查原則

方法支援繼承語法推薦度
is Type var✅ 是簡潔⭐⭐⭐⭐⭐
as Type✅ 是中等⭐⭐⭐⭐
switch (var) { case Type v: }✅ 是結構化⭐⭐⭐⭐⭐
GetType() == typeof(Type)❌ 否 (精確匹配)冗長⭐⭐
GetType().Name == "TypeName"❌ 否脆弱⭐

遞迴遍歷所有子控制項


public IEnumerable GetAllControls(Control root)
{
    foreach (Control ctrl in root.Controls)
    {
        yield return ctrl;
        foreach (var child in GetAllControls(ctrl))
            yield return child;
    }
}

// 使用
foreach (var ctrl in GetAllControls(this))
{
    if (ctrl is TextBox txt) txt.Clear();
}

實務範例:表單驗證與重設


public void ValidateForm(Control container)
{
    foreach (Control ctrl in container.Controls)
    {
        switch (ctrl)
        {
            case TextBox txt when string.IsNullOrWhiteSpace(txt.Text):
                errorProvider.SetError(txt, "必填欄位");
                break;
            case ComboBox cmb when cmb.SelectedIndex < 0:
                errorProvider.SetError(cmb, "請選擇項目");
                break;
            case CheckBox chk when !chk.Checked && chk.Tag?.ToString() == "Required":
                errorProvider.SetError(chk, "必須勾選同意條款");
                break;
        }
    }
}

public void ResetForm(Control container)
{
    foreach (Control ctrl in container.Controls)
    {
        switch (ctrl)
        {
            case TextBox txt: txt.Clear(); break;
            case ComboBox cmb: cmb.SelectedIndex = -1; break;
            case CheckBox chk: chk.Checked = false; break;
            case RadioButton rb: rb.Checked = false; break;
            case DateTimePicker dtp: dtp.Value = DateTime.Today; break;
        }
    }
}

總結

現代 C# (is 型別模式、switch 型別模式) 提供優雅、型別安全、支援繼承的控制項轉換方式。棄用 GetType() 字串比較與 typeof 精確匹配,拥抱模式比對語法,能寫出更健壯、可維護的 UI 邏輯代碼。

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