web-dev-qa-db-ja.com

GetType()。Nameを使用してイベントハンドラーで送信者オブジェクトをキャストします

テキストボックスとRichTextBoxのイベントハンドラーがあります。コードは同じですが、

ハンドラー#1で:

RichTextBox tb = (RichTextBox)sender

ハンドラー#2に応じて:

TextBox tb = (TextBox)sender

そうすることで、送信コントロールを完全に操作できます。私が知りたいのは、送信オブジェクトをそのタイプに応じてTextboxまたはRichTextboxにキャストする方法です

sender.GetType().Name

次に、実行時にコントロールを作成して操作します。そうすれば、必要なイベントハンドラー関数は1つだけです。コードが少なく、エラーが少なく、保守が簡単で、DRY :-)

22
tfl

必要なプロパティに応じて、TextBoxとRichTextBoxの両方がそのサブクラスを継承するため、送信者をTextBoxBaseとしてキャストできます。

3
Kieron

キャストする必要はありません。始めたときと同じように考えていましたが、この「パターン」は間違っており、実際には論理的ではありません。

あなたの最善の策は次のようなものを使用することです:

if (sender is TextBox)
{
  TextBox tb = (TextBox)sender;
}
else if (sender is RichTextBox)
{
  RichTextBox rtb = (RichTextBox)sender;
}
else
{
  // etc
}
30
leppie

これは非常に古い投稿であることは知っていますが、Framework 4では、送信者をコントロールとしてキャストできます。

Control cntrl = (Control)sender;
cntrl.Text = "This is a " + sender.GetType().ToString();

異なるコントロールのすべてに共通するコントロール(つまりテキスト)のみを参照できることに注意してください。

6
Mark Kram
RichTextBox textbox = sender as RichTextBox;
if (textbox != null)
{
   // do stuff as a rtb
   textbox.Text = "I'm a rtb";
   return;
}

TextBox textbox = sender as TextBox;
if (textbox != null)
{
   // do stuff as a textbox
   textbox.Text = "I'm a textbox";
}
4
Chris S

キャストはコンパイル時にのみ実行できるため、コンパイル時にキャストしたい型を知る必要があります。したがって、キャスト時にランタイムタイプ(GetType()によって返される)は使用できません。

探しているポリモーフィズムの場合、リフレクションを介してNameプロパティにアクセスできます。イベントハンドラを再利用できるようにするためだけに、私はそのようには行きません。

厳密な型指定が必要な場合は、2つの送信者の共通の基本クラスまたはインターフェイスが唯一の方法です。

3
Peter Lillevold

タイプ名ではなく、「 is 」を使用できます。

タイプを知りたいだけで、オブジェクト参照が必要ない場合:

if (sender is RichTextBox)
{
    // ...
}
else if (sender is TextBox)
{
    // ...
}

ただし、通常はオブジェクトが必要です。C#7には、インラインで値をテストおよび取得できるNice構文があります。

if (sender is RichTextBox richTextBox)
{
    richTextBox.Text = "I am rich";
}
else if (sender is TextBox textBox)
{
    textBox.Text = "I am not rich";
}
2
stuartd

また、インライン一時変数を使用してキャストを処理することもできます。

if (sender is RichTextBox tb)
{
    // ... //
} 
else if (sender is TextBox tb)
{
    // ... //
}
1
Chris Stillwell

コードが同一の場合、注意する必要がありますか? Controlにキャストしても必要なものがすべて得られないのではないかと思います...

1つの複雑なハンドラーは、いくつかの単純なハンドラーよりも必ずしも優れているとは限りません。どちらにしても、haveこのルートに行く場合は、「as」/「is」が望ましい(文字列などに依存しません):

TextBox tb = sender as TextBox;
if(tb!=null) {/* TextBox specific code */}
...
0
Marc Gravell

上記のコードの一般的なバージョン:

public static void CastAndUse<T>(object item, Action<T> action) where T : class
{
    T thing = item as T;

    if (thing != null)
    {
        action(thing);
    }
}

使用されます:

CastAndUse(sender, new Action((foo) => foo = bar));

完璧ではありませんが、便利です。

0
Josh

コードを繰り返したくない場合は、両方のコントロールをキャストし、共通アクションをTextBoxBaseを引数として使用する別のメソッドにリファクタリングできます。そして、イベントハンドラーで、コントロールをSystem.Windows.Forms.TextBoxBaseに変換します。これは、両方のコントロールがTexbBoxBaseから派生し、メソッドを呼び出すためです。

これらのコントロールの特定のプロパティが必要な場合は、このリファクタリングが機能しないことに注意してください。

0
gk.