2012-02-08 49 views
4

的類型,我有這樣的代碼:限制一個基類參數

public static void ToUpperCase(params Control[] controls) 
{ 
    foreach (Control oControl in controls) 
    { 
     if (oControl is TextBox) 
     { 
      oControl.TextChanged += (sndr, evnt) => 
      { 
       TextBox txtControl = sndr as TextBox; 
       int pos = txtControl.SelectionStart; 
       txtControl.Text = txtControl.Text.ToUpper(); 
       txtControl.SelectionStart = pos; 
      }; 
     } 
     else if (oControl is ComboBox) 
     { 
      oControl.TextChanged += (sndr, evnt) => 
      { 
       ComboBox cmbControl = sndr as ComboBox; 
       int pos = cmbControl.SelectionStart; 
       cmbControl.Text = cmbControl.Text.ToUpper(); 
       cmbControl.SelectionStart = pos; 
      }; 
     } 
     else throw new NotImplementedException(oControl.GetType().DeclaringType.ToString() + " is not allowed."); 
    } 
} 

我想限制params Control[] controls只接受一個TextBoxComboBox類型。

我的代碼是在C#中,框架4,構建在VS2010Pro中,項目在WinForms中。

請幫忙。提前致謝。

+0

獨佔一個或另一個 - 如在,它將是一個TextBoxes數組或一個ComboBoxes數組?或者它可能是一個TextBoxes和ComboBoxes數組? – Zenexer 2012-02-08 01:54:40

回答

4

通常情況下,您應該爲TextBox或ComboBox使用通用的基類,但那已經是Control了。你也不能改變它們的基類。

我能想到的最好方法是添加一個Debug.Assert來檢查類型。 喜歡的東西:

foreach (var control in controls) 
    Debug.Assert((control is TextBox) || (control is ComboBox)); 
+2

這是最可行的答案。 – Zenexer 2012-02-08 02:00:52

5

您不能 - 他們沒有一個良好的共同祖先。

一下就可以了(也許應該)做的就是讓你的方法的兩個重載,這需要每一個參數:

public static void ToUpperCase(params TextBox[] controls) 
{ 
    foreach (TextBox oControl in controls) 
     oControl.TextChanged += (sndr, evnt) => 
     { 
      TextBox txtControl = sndr as TextBox ; 
      int pos = txtControl.SelectionStart; 
      txtControl.Text = txtControl.Text.ToUpper(); 
      txtControl.SelectionStart = pos; 
     }; 
} 

public static void ToUpperCase(params ComboBox[] controls) 
{ 
    foreach (ComboBoxControl oControl in controls) 
     oControl.TextChanged += (sndr, evnt) => 
     { 
      ComboBox txtControl = sndr as ComboBox; 
      int pos = txtControl.SelectionStart; 
      txtControl.Text = txtControl.Text.ToUpper(); 
      txtControl.SelectionStart = pos; 
     }; 
} 
+1

如果你想同時傳遞TextBox和ComboBox對象,這將不起作用,所以它是否是正確的答案取決於原始的海報對我的第一個評論的回答。 – Zenexer 2012-02-08 02:01:17

+0

當然不是。然而,沒有什麼可以的,因爲我說他們沒有一個好的共同祖先。他們最具體的基類是Control。正如Michael Keijzers所建議的那樣,另一種選擇是在運行時進行驗證。 – 2012-02-08 02:02:52

+2

是的,非常真實。這是我能想到的兩個最佳答案。 – Zenexer 2012-02-08 02:05:26

4

OPTION ONE

如果你希望能夠通過在你的函數中混合了文本框和組合框,並且仍然有靜態類型檢查,你可以做的是以下面的方式實現它。

public interface ISupportUpperCase { 
    event EventHandler ValueChanged; 
    void TransformValueToUpperCase(); 
} 

public class UpperCaseableTextbox : Textbox, ISupportUpperCase { 
    //TextChanged event is already here, just use it. 

    //Implement TransformValueToUpperCase in a way that suits your control 
    public void TransformValueToUpperCase() { 
    int pos = this.SelectionStart; 
    this.Text = this.Text.ToUpper(); 
    this.SelectionStart = pos; 
    } 
} 

public class UpperCaseableComboBox : ComboBox, ISupportUpperCase { 
    //TextChanged event is already here, just use it. 
    //Implement TransformValueToUpperCase in a way that suits your control 
} 

那麼你的功能將是:

public static void ToUpperCase(params ISupportUpperCase[] controls) 
{ 
    foreach (var oControl in controls) 
    { 
     oControl.TextChanged += (sndr, evnt) => 
     { 
      oControl.TransformValueToUpperCase(); 
     } 
    } 
} 

通過這樣做,你最終得到更好的封裝,因爲只有特定的控制應該知道如何使其價值大寫,而不是一些神奇的功能,各地的地方。 您還可以輕鬆引入更多支持此功能的控件,而無需更改其他功能。

選項二

事實上,你可以擺脫這個功能在所有使用相同的方法,只是稍微改變接口:

public interface ISupportUpperCase { 
    bool AlwaysInUpperCase { get; set } 
} 

所以你的控件將全面負責爲此功能基於此標誌:

public class UpperCaseableTextbox : Textbox, ISupportUpperCase { 

    public bool AlwaysInUpperCase { get; set } 

    //constructor 
    public UpperCaseableTextbox() { 
    this.TextChanged += (sender, args) => { 
     if (this.AlwaysInUpperCase) { 
      int pos = this.SelectionStart; 
      this.Text = this.Text.ToUpper(); 
      this.SelectionStart = pos; 
     } 
    } 
    } 
} 

因此,而不是有一個功能,你可以設置道具當你需要控制始終處於大寫狀態並且控制將自行管理時。