微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Winforms 将 Control 转换为其他控件类型并分配特定的事件处理程序

如何解决Winforms 将 Control 转换为其他控件类型并分配特定的事件处理程序

至于问题,我正在以编程方式创建控件并根据变量我需要创建不同的控件类型,然后将它们添加到面板中。

当我尝试从 Control 投射 CheckBox添加 CheckedChanged 事件时,我得到“Control 不包含该 [...] 的定义”。

我知道我可以只复制 Panel.Add(Control) 行并避免使用通用控件,但我想知道是否可以从更通用的控件正确转换控件

          Control val;
          if (dataType.Equals(COIL))
          {
            val = new CheckBox
            {
              Name = $"txt{i}"
            };
            val.CheckedChanged += ChangeValue;
          }
          else
          {
            val = new TextBox
            {
              Name = $"txt{i}",Size = new Size(70,20),TextAlign = HorizontalAlignment.Center,TabIndex = i
            };
          }

          flpValues.Controls.AddRange(new Control[] { lbl,val });

解决方法


有什么问题?

你有这样的代码:

Control val;
// ...
val = new CheckBox
{
    Name = $"txt{i}"
};
val.CheckedChanged += ChangeValue;

它不起作用,因为 CheckedChanged 中没有 Control,而 val 尽管是 CheckBox,但被键入为 Control


如何解决?

你可以投射它:

Control val;
// ...
val = new CheckBox
{
    Name = $"txt{i}"
};
((CheckBox)val).CheckedChanged += ChangeValue;

然而,在我看来,这是在做不必要的额外工作。我会改用另一个变量:

Control val;
// ...
var checkBox = new CheckBox
{
    Name = $"txt{i}"
};
checkBox.CheckedChanged += ChangeValue;
val = checkBox;

事实上,这可以很容易地将这些行提取到另一种方法中,让您:

Control val;
// ...
val = CreateCheckBox(i);

你能安全施放吗?

也许你更感兴趣的是你是否可以安全地施放它。毕竟,当您编写 ((CheckBox)val) 时,编译器不会检查类型是否正确,而是在运行时进行检查(如果失败则抛出,这不会发生)。

有几种方法可以进行安全转换,从 as 开始:

Control val;
// ...
val = new CheckBox
{
    Name = $"txt{i}"
};
(val as CheckBox).CheckedChanged += ChangeValue;

现在,根据您的分析器,您可能会收到警告。由于使用 as 进行转换不会抛出,但可能返回 null。这在理论上会导致异常。当然,我们知道这种情况不会发生(因此您可以取消任何警告,如果有的话)。

另一种选择是使用 is

Control val;
// ...
val = new CheckBox
{
    Name = $"txt{i}"
};
if (val is CheckBox checkBox)
{
    checkBox.CheckedChanged += ChangeValue;   
}

现在我已经引入了一个条件语句(我们知道它总是正确的)和一个新变量。至少它没有警告。然而,很明显,仅仅使用我最初建议的附加变量比这更好(因为该解决方案没有条件)。


编译器会优化吗?

也许你担心编译器能不能优化代码。

代码 ((CheckBox)val) 将产生 castclass 操作码。 (val as CheckBox) 将产生 isinst 操作码。类似地,if (val is CheckBox checkBox) 将导致 isinst,加上分支(我在sharplab 中得到了 brfalse.s)。

不是,JIT 编译器似乎也没有优化它。事实上,使用新变量的 the suggested solution 没有任何与转换或检查类型相关的操作码。它也是 JIT asm 中较短的代码。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。