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

C# 使用GetType()在事件处理程序中强制转换发件人对象。名称,c#,late-binding,C#,Late Binding,我有一个用于Textbox和RichTextBox的事件处理程序。 代码是相同的,但是 在handler#1中,我会: 相应地,在处理程序2中: TextBox tb = (TextBox)sender 这样我就可以完全操纵发送控件。 我想知道的是如何根据发送对象的类型使用 sender.GetType().Name 然后在运行时创建控件并使用它。这样,我只需要一个事件处理函数:更少的代码、更少的错误、更易于维护和删除:-)而不是您可以使用的类型名称“” 如果您只想知道类型而不需要对象引用:

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

在handler#1中,我会:

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

TextBox tb = (TextBox)sender
这样我就可以完全操纵发送控件。 我想知道的是如何根据发送对象的类型使用

sender.GetType().Name

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

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

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

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

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

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


如果需要强类型,两个发送方上的公共基类或接口是唯一的选择。

您永远不必强制转换。我开始的时候也这么想,这个“模式”是不正确的,也不符合逻辑

您最好使用以下方法:

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

如果代码相同,您需要注意吗?我想知道,如果将角色转换为
控制
是否不能提供您所需的一切

一个复杂的处理程序并不一定比几个简单的处理程序好。无论哪种方式,如果必须走这条路线,最好使用“as”/“is”(它不依赖于字符串等):


根据需要的属性,可以将发送方强制转换为TextBoxBase,因为TextBox和RichTextBox都继承自该子类。

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


请注意,如果您需要这些控件中任何一个的特定属性,则此重构将不起作用。

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

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

注意:您只能引用所有不同控件的共同控件(即文本)。

上述代码的通用版本:

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

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

不完美,但很方便。

您还可以使用一个内联临时变量为您处理强制转换

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

你能举一个在两个这样的类型之间共享的多态方法或属性的例子吗?但是没有被一个公共接口公开?这是可以的,但是@Chris suggestion更好。由于你要立即对对象执行某些操作,这将为你节省额外的施法时间。一旦你确定了对象的类型,你实际上是在施法,所以你必须施法,但这绝对是正确的方法,因为它不依赖(缓慢的)反射。
Control cntrl = (Control)sender;
cntrl.Text = "This is a " + sender.GetType().ToString();
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));
if (sender is RichTextBox tb)
{
    // ... //
} 
else if (sender is TextBox tb)
{
    // ... //
}