【问题标题】:VB.NET assignment of object default property valueVB.NET 对象默认属性值的赋值
【发布时间】:2012-07-11 05:15:54
【问题描述】:

这是一个非常奇怪的问题,你可能会发现。 我正在做一个从 VB6 到 VB.NET 2010 的大型迁移项目。作为 VB6 的一部分,我们有一个常量定义为 NullString = "" 在 .NET 中,它也在类似的行上迁移并使用。 我们遇到的问题是,当将 RecordSet 中的值(它只是 DataTable 的一个包装器)与这个 NullString 进行比较时,我们会得到比较错误。 由于该项目正在积极开发中,我们必须依赖迁移工具(VB MIgration Partner),它了解很少的 Pragma 但不太先进。 我创建了一个类(NullStringClass)并重载了“=”和“”运算符,它对我的​​比较问题进行了排序。 但是在某些地方,我们有 someVar = NullString,其中 someVar 是一个字符串变量。现在,我收到无法从 NullStringClass 转换为字符串的错误。 我试图重载 ToString 方法并返回 "" 并在类上放置一个属性,如下所示:

<System.Reflection.DefaultMember("Value")> _
Public Class NullStringClass

属性定义为:

Public Property Value() As String
    Get
        Return ""
    End Get
    Set(ByVal value As String)

    End Set
End Property

但它仍然抛出异常。 据我所知,这应该解决了我的问题,但没有运气。 我仍然得到同样的错误。 所以,我的问题是一样的。 有什么方法可以将该 NullString 变量转换为一个类并使用运算符重载进行不同的比较(包括 Null 和 Nothing),并且还可以用作对字符串变量的正常分配? 例如。意思是

Dim s as String
s = NullString

应该和下面的一样工作:

If rsData("MyField").Value <> NullString Then
'Note: rsData("MyField").Value is DbNull

这是运算符重载的示例(如果有人感兴趣)

Public Shared Operator <>(ByVal mmyVal As Object, ByVal objVal As NullStringClass) As Boolean
    If TypeOf mmyVal Is String Then
        Return (Not String.IsNullOrEmpty(mmyVal))
    Else 'If TypeOf mmyVal Is Object Then
        Return (Not IsDBNull(mmyVal))
    End If
End Operator

谢谢, 尼克

【问题讨论】:

  • 只是另一个想法。将 NullString 保持为字符串(不是写一个类),而是通过扩展方法为 String 类重载 运算符。有可能吗?
  • 您正试图将 .net 转换为 VB6 沿着这条路线走下去,这在很多层面上都是个坏主意。最重要的是,“”不是空的,也不是 DBNull,使它们等价只是在延续无知。
  • 该应用程序正在迁移,因为 Microsoft 已停止支持 VB6 :-) 另一个全新的 Web 应用程序正在取代这个应用程序。迁移此应用的唯一原因是让它再运行几年。
  • 为什么不使用你的空字符串,而不是使用 String.Empty ?这是 .net 为此类目的提供的。
  • 这就是 NullString 变量的值。但问题是当我将它与 DbNull 进行比较时,它会引发异常。因此,我需要一些类来处理 String 和 DbNull 即对象。请看我的回答:-)

标签: operator-overloading variable-assignment default-value assignment-operator


【解决方案1】:

在挣扎了 2 天并为使“=”起作用而挠头后,我提出了这个问题。 (操作员过载在 1 小时内工作正常)。 正确获取“s = NullString”的解决方案是为我的 NullStringClass 放置隐式运算符。

Public Shared Widening Operator CType(ByVal obj As String) As NullStringClass
    Return New NullStringClass()
End Operator

Public Shared Narrowing Operator CType(ByVal obj As NullStringClass) As String
    Return String.Empty
End Operator

虽然只有 Narrowing Operator 就足够了,但我也加入了 Widening(将在生产代码中删除,因为它不是必需的)。 希望这对像我这样的人有帮助:-)

【讨论】:

    【解决方案2】:

    在 vb.net 中,string 类型的存储位置包含 null 或未初始化的值,在语义上与空字符串不同。如果您希望将此类存储位置与另一个已知不为空的字符串进行比较,并且如果存储位置为空(而不是引发异常),则此类比较仅返回 false,您可以将表达式编写为 "Whatever".Equals(storageLocation) .如果您希望比较两个字符串,其中一个或两个可能为空,并且空字符串比较彼此相等但不与其他任何字符串(包括空字符串)比较,您可以使用String.Equals(string1, string2)。如果你想确定一个字符串是空还是空,你可以使用String.IsNullorEmpty(theString)。如果您希望以将空字符串视为空的方式执行比较,您可以编写自己的静态比较,以这种方式执行比较,或者您可以编写一个函数,给定string,如果非空则返回传入的字符串,否则返回String.Empty。

    希望以上之一就是您所追求的。请注意,它们与 VB6 所谓的“默认属性”无关,但您的问题似乎不是在询问 VB6 属性(以及 Let 和 Set 之间的相关区别。

    附录

    如果你想要一个大多数情况下可以像普通字符串一样使用的字符串类型,但默认为空字符串而不是Nothing,你可以使用这样的东西(不完整,但应该是一个好的开始)

    Public Structure SafeString
        Implements IComparable(Of SafeString), IEquatable(Of SafeString)
    
        Dim _St As String
    
        Sub New(St As String)
            _St = St
        End Sub
    
        Public Overrides Function ToString() As String
            Return If(_St, "")
        End Function
    
        Public Overrides Function GetHashCode() As Integer
            Return If(_St, "").GetHashCode()
        End Function
    
        Public Overrides Function Equals(obj As Object) As Boolean
            If obj Is Nothing OrElse Not (TypeOf (obj) Is SafeString) Then Return False
            Return If(_St, "") = If(CType(obj, SafeString)._St, "")
        End Function
    
        Public Function CompareTo(other As SafeString) As Integer Implements System.IComparable(Of SafeString).CompareTo
            Return If(_St, "").CompareTo(If(other._St, ""))
        End Function
    
        Public Overloads Function Equals(other As SafeString) As Boolean Implements System.IEquatable(Of SafeString).Equals
            Return If(_St, "") = If(other._St, "")
        End Function
    
        Public Shared Widening Operator CType(st As String) As SafeString
            Dim ret As New SafeString
            ret._St = st
            Return ret
        End Operator
    
        Public Shared Widening Operator CType(safeSt As SafeString) As String
            Return If(safeSt._St, "")
        End Operator
    
        Function Length() As Integer
            Return If(_St, "").Length()
        End Function
        Function SubString(startIndex As Integer) As String
            Return If(_St, "").Substring(startIndex, Length)
        End Function
        Function SubString(startIndex As Integer, length As Integer) As String
            Return If(_St, "").Substring(startIndex, length)
        End Function
    

    您会注意到一个非常常见的模式If(_St, "")。该函数将使用 _St 如果它不为空,或者如果它是空字符串。它不支持String 所做的所有方法,但是如果您需要任何还不能工作的方法,您应该可以按照Length 等显示的模式进行分配和比较String 和SafeString 应该按预期工作,除了 Object.Equals 不会将任何 String 视为等于任何 SafeString (无法更改 String 覆盖的行为以使字符串比较等于任何其他类型的对象;如果"Test".Equals(New SafeString("Test")) 将比较为假,那么(New SafeString("Test")).Equals("Test") 也必须这样做。

    【讨论】:

    • 抱歉回复晚了。但是如果我正在编写新代码,所有这些都适用,但是对于迁移,不幸的是,我不能:-(因此我不得不使用隐式运算符。
    猜你喜欢
    • 2016-08-15
    • 2016-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多