【问题标题】:Option Strict On disallows implicit conversions between String and Object {String}Option Strict On 不允许 String 和 Object {String} 之间的隐式转换
【发布时间】:2021-03-22 13:43:00
【问题描述】:

我正在尝试使用Option Strict On 来清理我作为初学者程序员的方式。我设法清除了除此之外的所有错误。
我正在使用 ToolStrip 的 Tag 属性来获取一些文本信息。点击 ToolStrip,我需要记住一个字符串中 Tag 的值并更改该 Tag 的值。

如何将 Object {String} sender.tag 转换为 String 以及 String myString 和 Object {字符串}?

Private Sub ToolStrip_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles ToolStrip.ItemClicked
    Dim myString As String = sender.tag
    sender.tag = "It is selected"
    'more code...
End Sub

编辑:请参见此处代码相关部分的屏幕截图:

【问题讨论】:

  • 你确定你现在有Option Strict On吗?你不能用那个选项写这个OnDim myString As String = sender.tag:发件人是Object类型,Object没有Tag属性(e.ClickedItem可以有),所以错误是不同的。
  • @Jimi 谢谢你的回复。我用错误的屏幕截图更新了问题。
  • 如前所述,sender(如您在处理程序定义中所见)是一个对象,Object 没有 Tag 属性。因此,您当然不能要求读取 Type 未提供的属性的值。您需要将sender 转换为实际类型。但是,您真正想阅读的 UI 元素的 Tag 是什么?您是否在那里设置了断点并检查了 sender 实际上是什么?不是点击的项目。是否要读取哪个 UI 元素的 Tag 属性?
  • @Jimi,我使用的是 Winform,工具栏中有几个按钮。每个按钮都有属性 Tab ToolBarButton.Tag Property。创建工具栏后,我双击它,屏幕截图中的 Private Sub 是在 VB 代码中创建的。我添加了我向您展示的行。如果 Strict 为 Off,则代码运行良好。我试过 .ToString

标签: vb.net winforms toolstrip toolstripitem


【解决方案1】:

如果要读取ToolstripItem 的标签属性,则需要读取所选项目的标签。这是由ToolStripItemClickedEventArgs 对象的e.ClickedItem 属性提供的:

获取在 ToolStrip 上被点击的项目。

如果要读取此 Item 所属 ToolStrip 的 Tag 属性,请将 sender 转换为 ToolStrip(或 Control,此属性所属的基类)并将其 Tag 属性转换为 String。

注意:当您双击 ToolStrip 控件时,会创建一个 ItemClicked 处理程序,因为这是 default event of that Control。该事件与 ToolStrip 对象相关,因此事件处理程序中的 sender 对象将是引发事件的 ToolStrip 实例的引用。

Tag Property 属于 Object 类型,这也是你需要转换它的原因。

Private Sub ToolStrip_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles ToolStrip.ItemClicked
    Dim itemTagAsString As String = e.ClickedItem.Tag?.ToString()

    Dim toolStripTagAsString = DirectCast(sender, ToolStrip).Tag?.ToString()
    ' Or, cast to Control, the Tag Property belongs to the base class
    Dim toolStripTagAsString = DirectCast(sender, Control).Tag?.ToString()
End Sub

在这些示例中检查itemTtag 的类型(使用Option Infer On):

Dim itemTtag = e.ClickedItem.Tag
Dim itemTtag = e.ClickedItem.Tag?.ToString()

所以更清楚为什么这不是一个有效的陈述:

Dim itemTtag As String = e.ClickedItem.Tag

注意:这里使用了null conditional operator?,又名 Elvis),因为标签可能为空(Nothing)。如果是,你不会得到异常,只是一个空字符串。

【讨论】:

  • 我觉得只投票一次是不够的。
  • @jmcilhinney 谢谢。不知道你为什么这么说,但我很欣赏评论:)
  • @Jimi,感谢您提供详细示例。我了解如何使用“e”对象,但我需要使用“sender”对象,因为这是唯一在其他情况下具有任何信息的对象,例如 ToolStripSplitButton。
  • 如前所述,sender 对象代表 ToolStrip 本身。不是您添加到其中的控件。如果单击子控件,则 e.ClickedItem 属性会引用它。 SplitMenu 的 MenuItem 不属于 ToolStrip,因此当您选择其中之一时,不会引发事件。正如在 cmets 中已经问过的,您需要哪些控件的标签? ToolStrip 本身(已经在答案中)?它的子控件(已经在答案中)?拆分按钮的菜单项?
  • 尝试更明确地解释您希望从中获取标签属性的控件。
【解决方案2】:

很好,您为您的问题提供了一般性的标题。你需要一个通用的答案。

Option Strict On 是个好东西。它使编码变得更加困难,但运行时的性能会提高,因为隐式数据类型转换会减少。

让我们获取您的代码...sender As Object......sender.tag.. 这是.net中的典型事情。经常会看到object 类型的参数,这意味着可以传递任何数据类型。对象没有定义属于该数据类型的所有属性和方法。

例如

Dim oTxt as object = new TextBox()

oTxt 不会自动拥有Text 属性。你需要cast。当你 100% 知道对象类型时,做

dim str as string = DirectCast(oTxt, TextBox).Text

但有时您不知道您的object 中的Type 是什么。在这种情况下,您尝试强制转换,然后检查 null

dim txtBx as TextBox = TryCast(oTxt, TextBox)
if txtBx IsNot Nothing Then str = txtBx.Text

您真正的问题是您需要了解类型转换。即使您没有Options Strinct On,您也应该显式转换它,因为当您隐式执行x = sender.tag 时,您实际上使用的是后期绑定,这对性能不利。这也为潜在的运行时错误打开了大门。

你的研究主题应该是:类型转换、后期绑定、装箱/拆箱

【讨论】:

  • @t-s,谢谢你的课程。我将它添加到我必须学习的东西列表中。 :-) 我尝试使用 Dim myString As String = TryCast(sender.tag, String),但我得到了同样的错误:BC30574 Option Strict On disallows late binding。
  • @Florin 当然! sendertag 都是对象。因此,您需要添加另一个演员 Dim myString As String = TryCast(DirectCast(sender, Control).tag, String) 但如果您的对象中有 string,则对象具有 ToString 定义。因此这就足够了Dim myString As String = DirectCast(sender, Control).Tag.ToString()
  • @T-S,谢谢。我想我明白你做了什么:不是在 sender.tag 上使用 DirectCast 将其转换为字符串,而是将“发送者”转换为控件,然后读取控件的标签。不幸的是,它不起作用。虽然它在编译时没有给我一个错误,但它给了我一个运行时错误:“无法将'System.Windows.Forms.ToolStripMenuItem'类型的对象转换为'System.Windows.Forms.Control'类型。”跨度>
  • @T-S,捎带你的答案,这有效:= DirectCast(sender, ToolStripMenuItem).Tag.ToString 谢谢你的帮助。
  • @Florin 好的。该错误是不言自明的。显然ToolStripMenuItem 不是从Control 派生的。因此,只需将 Control 替换为 ToolStripMenuItem
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 2012-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多