Vb.net 有没有一种快速有效的方法使课堂公平?

Vb.net 有没有一种快速有效的方法使课堂公平?,vb.net,.net-4.0,equality,Vb.net,.net 4.0,Equality,我有很多类,通常有许多基本类型的属性/字段 Public Class ClassN Public P1 As Integer Public P2 As Byte() Public P3 As String Public P4 As Short? '... Public P17 As Boolean Public P18 As Char() End Class 在这一点上,我提出了一个解决方案,使用和“平等服务类”执行平等测试。但是,有没有

我有很多类,通常有许多基本类型的属性/字段

Public Class ClassN
    Public P1 As Integer
    Public P2 As Byte()
    Public P3 As String
    Public P4 As Short?
    '...
    Public P17 As Boolean
    Public P18 As Char()
End Class
在这一点上,我提出了一个解决方案,使用和“平等服务类”执行平等测试。但是,有没有一种更快更有效的方法来实现这一点

代码隐藏

<AttributeUsage((AttributeTargets.Field Or AttributeTargets.Property), AllowMultiple:=False, Inherited:=False)> _
Public Class EquatableAttribute
    Inherits Attribute
End Class

Public Class ClassN
    Implements IEquatable(Of ClassN)

    <Equatable()> Public P1 As Integer
    <Equatable()> Public P2 As Byte()
    <Equatable()> Public P3 As String
    <Equatable()> Public P4 As Short?
    '...
    <Equatable()> Public P17 As Boolean
    <Equatable()> Public P18 As Char()

    Public Overrides Function Equals(obj As Object) As Boolean
        Return Me.Equals(TryCast(obj, ClassN))
    End Function

    Public Overloads Function Equals(obj As ClassN) As Boolean Implements System.IEquatable(Of ClassN).Equals
        Return EqualityServices.Equals(Of ClassN)(Me, obj)
    End Function

End Class

Public NotInheritable Class EqualityServices

    Private Sub New()
    End Sub

    Public Overloads Shared Function Equals(Of T)(obj1 As T, obj2 As T) As Boolean
        If (obj1 Is Nothing) Then
            Return obj2 Is Nothing
        End If
        If (obj2 Is Nothing) Then
            Return False
        End If
        Dim type As Type = GetType(T)
        Dim members As MemberInfo() = Nothing
        If (Not EqualityServices.EquatableAttributeCache.TryGetValue(type, members)) Then
            members = New MemberInfo(-1) {}
            For Each info As MemberInfo In type.GetMembers((BindingFlags.Public Or BindingFlags.Instance))
                If (info.GetCustomAttributes(EqualityServices.EquatableAttributeType, False).Length > 0) Then
                    Select Case info.MemberType
                        Case MemberTypes.Field
                            Exit Select
                        Case MemberTypes.Property
                            With DirectCast(info, PropertyInfo)
                                If ((Not .CanRead) OrElse (.GetIndexParameters().Length > 0)) Then
                                    Continue For
                                End If
                            End With
                            Exit Select
                        Case Else
                            Continue For
                    End Select
                    ReDim Preserve members(members.Length)
                    members(members.Length - 1) = info
                End If
            Next
            EqualityServices.EquatableAttributeCache.Add(type, members)
        End If
        If (members.Length > 0) Then
            Dim value1 As Object = Nothing
            Dim value2 As Object = Nothing
            For Each info As MemberInfo In members
                Select Case info.MemberType
                    Case MemberTypes.Field
                        With DirectCast(info, FieldInfo)
                            type = .FieldType
                            value1 = .GetValue(obj1)
                            value2 = .GetValue(obj2)
                        End With
                        Exit Select
                    Case MemberTypes.Property
                        With DirectCast(info, PropertyInfo)
                            type = .PropertyType
                            value1 = .GetValue(obj1, Nothing)
                            value2 = .GetValue(obj2, Nothing)
                        End With
                        Exit Select
                    Case Else
                        Continue For
                End Select
                If (type.BaseType Is EqualityServices.ArrayType) Then
                    If (Not EqualityServices.SequenceEqual(CType(value1, Array), CType(value2, Array))) Then
                        Return False
                    End If
                Else
                    If (Not Object.Equals(value1, value2)) Then
                        Return False
                    End If
                End If
            Next
            Return True
        End If
        Return False
    End Function

    Private Shared Function SequenceEqual(ByVal array1 As Array, array2 As Array) As Boolean
        If (array1 Is Nothing) Then
            Return array2 Is Nothing
        End If
        If (array2 Is Nothing) Then
            Return False
        End If
        If (array1.Rank <> array2.Rank) Then
            Return False
        End If
        If (array1.Length <> array2.Length) Then
            Return False
        End If
        Dim length As Integer = (array1.Length - 1)
        If (length > -1) Then
            Dim list1 As IList = CType(array1, IList)
            Dim list2 As IList = CType(array2, IList)
            For index = 0 To length
                If (Not Object.Equals(list1.Item(index), list2.Item(index))) Then
                    Return False
                End If
            Next
        End If
        Return True
    End Function

    Private Shared ReadOnly EquatableAttributeCache As New Dictionary(Of Type, MemberInfo())
    Private Shared ReadOnly EquatableAttributeType As Type = GetType(EquatableAttribute)
    Private Shared ReadOnly ArrayType As Type = GetType(Array)

End Class
_
公共类equalableAttribute
继承属性
末级
公共类
实现IEquatable(类n的)
公共P1为整数
作为字节()的公共P2
公共P3作为字符串
公共P4短吗?
'...
公共P17作为布尔值
公共P18作为字符()
公共重写函数等于布尔值(对象为obj)
返回我.Equals(TryCast(obj,ClassN))
端函数
Public重载函数Equals(obj作为ClassN)作为布尔实现System.IEquatable(属于ClassN).Equals
返回EqualityServices.Equals(属于类别N)(Me,obj)
端函数
末级
公共不可继承类EqualityServices
私人分新
端接头
公共重载共享函数等于(Of T)(obj1为T,obj2为T)作为布尔值
如果(obj1为空),则
返回obj2什么都不是
如果结束
如果(obj2为空),则
返回错误
如果结束
Dim type As type=GetType(T)
将成员设置为MemberInfo()=无
如果(不是EqualityServices.EqualableAttributeCache.TryGetValue(类型,成员)),则
成员=新成员信息(-1){}
对于类型为.GetMembers((BindingFlags.Public或BindingFlags.Instance))中作为MemberInfo的每个信息
如果(info.GetCustomAttributes(EqualityServices.equalableAttribute,False).Length>0),则
选择Case info.MemberType
案例成员类型。字段
退出选择
Case MemberTypes.Property
使用DirectCast(信息、属性信息)
如果((Not.CanRead)OrElse(.GetIndexParameters().Length>0)),则
继续
如果结束
以
退出选择
其他情况
继续
结束选择
ReDim保留成员(成员.长度)
成员(members.Length-1)=信息
如果结束
下一个
EqualityServices.EqualableAttributeCache.Add(类型,成员)
如果结束
如果(members.Length>0),则
作为对象的尺寸值1=无
作为对象的尺寸值2=无
对于每个信息作为成员中的成员信息
选择Case info.MemberType
案例成员类型。字段
使用DirectCast(信息、字段信息)
类型=.FieldType
value1=.GetValue(obj1)
value2=.GetValue(obj2)
以
退出选择
Case MemberTypes.Property
使用DirectCast(信息、属性信息)
类型=.PropertyType
value1=.GetValue(obj1,无)
value2=.GetValue(obj2,无)
以
退出选择
其他情况
继续
结束选择
如果(type.BaseType为EqualityServices.ArrayType),则
如果(不是EqualityServices.SequenceEqual(CType(value1,数组),CType(value2,数组)),则
返回错误
如果结束
其他的
如果(不是Object.Equals(value1,value2)),则
返回错误
如果结束
如果结束
下一个
返回真值
如果结束
返回错误
端函数
私有共享函数SequenceEqual(ByVal array1作为数组,array2作为数组)作为布尔值
如果(array1为空),则
返回数组2不算什么
如果结束
如果(array2不算什么)那么
返回错误
如果结束
如果(array1.Rank array2.Rank)那么
返回错误
如果结束
如果(array1.Length array2.Length)那么
返回错误
如果结束
整数形式的Dim长度=(array1.length-1)
如果(长度>-1),则
Dim list1为IList=CType(数组1,IList)
Dim list2作为IList=CType(数组2,IList)
对于索引=0到长度
如果(不是Object.Equals(list1.Item(index)、list2.Item(index)),那么
返回错误
如果结束
下一个
如果结束
返回真值
端函数
私有共享只读EqualableAttributeCache作为新字典(类型为MemberInfo())
私有共享只读EqualTableAttribute类型为Type=GetType(EqualTableAttribute)
私有共享只读ArrayType As Type=GetType(数组)
末级
可以为您生成相关的
Equals
GetHashCode
等或
IEqualityComparer
代码

你只是需要再竖琴

这里有一个例子(它是C#,因为我手头只有C#版本的ReSharper):


ReSharper可以为您生成相关的
Equals
GetHashCode
等或
IEqualityComparer
代码。你只需要重新竖琴。谢谢@DominicKexel,我会看一看。@DominicKexel因为没有人回答我的问题,你能把你的评论总结成一个答案,我会接受吗?我明天会做,这样我可以添加一些漂亮的小屏幕截图。@DominicKexel没问题!慢慢来:)