如何解决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 举报,一经查实,本站将立刻删除。