使用GetType()在事件处理程序中转发发件人对象。名称

时间:2009-03-11 11:18:04

标签: c# late-binding

我有一个Textbox和RichTextBox的事件处理程序。 代码相同,但

在处理程序#1中我做:

RichTextBox tb = (RichTextBox)sender

相应地在处理程序#2中:

TextBox tb = (TextBox)sender

这样做我可以完全操纵发送控件。 我想知道的是如何使用

将发送对象根据其类型转换为Textbox或RichTextbox
sender.GetType().Name

然后在运行时创建控件并使用它。这样我只需要一个事件处理函数:更少的代码,更少的错误,更容易维护和干: - )

10 个答案:

答案 0 :(得分:29)

你永远不必投。

当我开始时,我曾经以同样的方式思考,这种“模式”是不正确的,而且不合逻辑。

你最好的选择是使用类似的东西:

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

答案 1 :(得分:6)

我知道这是一篇非常古老的帖子,但在Framework 4中,您可以将发件人转换为控件:

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

请注意,您只能引用所有不同控件共有的控件(即Text)。

答案 2 :(得分:4)

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";
}

答案 3 :(得分:3)

转换只能在编译时完成,因此您需要知道在编译时要转换的类型。因此,在转换时不能使用运行时类型(由GetType()返回)。

如果是您正在寻找的多态,您可以通过反射访问Name属性。我不会这样做只是为了能够重用事件处理程序。

如果您想要强类型,两个发件人的公共基类或接口是唯一的方法。

答案 4 :(得分:3)

根据您需要的属性,您可以将发件人转换为TextBoxBase,因为TextBox和RichTextBox都从该子类继承。

答案 5 :(得分:2)

您可以使用“is”而不是类型名称。

如果您只想知道类型并且不需要对象引用:

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

但是你通常需要这个对象:C#7有一个很好的语法,允许你测试并获取内联值:

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

答案 6 :(得分:1)

您还可以使用内联临时变量来处理演员表。

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

答案 7 :(得分:0)

如果代码相同,您需要关心吗?我想知道施放到Control是否会给你所需的一切......

一个复杂的处理程序不一定比几个简单的处理程序更好。无论哪种方式,如果你去这条路线,“as”/“is”是可取的(它不依赖于字符串等):

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

答案 8 :(得分:0)

如果您不想重复代码,那么您可以转换两个控件,将常用操作重构为一个单独的方法,该方法将TextBoxBase作为参数。在您的事件处理程序中,处理程序将控件转换为System.Windows.Forms.TextBoxBase,因为两个控件都是从TexbBoxBase派生的,并调用该方法。

请注意如果您需要任何这些控件的特定属性,那么这种重构将不起作用。

答案 9 :(得分:0)

上述代码的通用版本:

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));

不完美,但很方便。