如何比较可为空的对象

How to Compare nullable objects

我需要将数据库中的当前对象列表与新的对象列表进行比较。我想比较它们并为用户突出显示那些已经改变的(在这种情况下,return TRUE 它们是不同的)。

由于我的一些对象是可空的,这涉及到 NewObj 和 CurrentObj 方面的很多 IF NOT IS Nothing ......我试图找到一种更有效的方式来编写下面的内容,因为我必须用它来比较大约 30 个不同类型的对象,IE Date、Decimal、Int 等。

下面的方法一直有效,直到说 Obj 中的任何一个没有 Rank,因此是 Nothing

建议?

Dim Rank As Boolean = CompareData(NewObj, CurrentObj, "Rank")
Dim Regiment As Boolean = CompareData(NewObj, CurrentObj, "Rank")
Dim DateofBirth As Boolean = CompareData(NewObj, CurrentObj, "DoB")

Private Function CompareData(NewObj As Business.Casualty, CurrentObj As Business.Casualty, FieldToComapre As String) As Boolean

Select Case FieldToComapre
        Case "DateOfBirth"
            Return (Nullable.Equals(NewCasualty.DateOfBirth, CurrentCasualty.DateOfBirth))
        Case "Age"
            Return (Nullable.Equals(NewCasualty.Age, CurrentCasualty.Age))            
        Case "Rank"
            Return (Nullable.Equals(NewCasualty.Rank.ID, CurrentCasualty.Rank.ID))
        Case "Regiment"
            Return (Nullable.Equals(NewCasualty.Regiment.ID, CurrentCasualty.Regiment.ID))           
        Case Else
            Return True
    End Select

End Function

我的第一个建议是将函数名称更改为类似 AreFieldValuesTheSame 的名称。我的第二个建议是否定函数的目的。换句话说,return当值相同时为真。

如果您遵循我的前两个建议,那么对于您的每个案例,而不是简单地

Return (Nullable.Equals(a.ID, b.ID))

你需要更像

Return ((a Is Nothing And b Is Nothing) Or (a.ID Is Nothing And b.ID Is Nothing) Or (Nullable.Equals(a.ID, b.ID)))

例如a代表NewCasualty.Rank,b代表CurrentCasualty.Rank。在尝试检查对象的属性之前,您需要检查对象是否为 Nothing(换句话说,为 null)。

另外,在函数的开头,需要判断NewObj是否为Nothing,CurrentObj是否为Nothing:

If (NewObj Is Nothing) And (CurrentObj Is Nothing) Then
    Return True
Else If (NewObj Is Nothing) Or (CurrentObj Is Nothing)
    Return False

如果我的 VB 语法不完美,请原谅我。 (我的 C# 更流利了。)

实际上我最终只是使用了扩展方法..它在我看来更简单、更干净。

Dim Rank As Boolean = CompareData(NewObj, CurrentObj, "Rank")
Dim Regiment As Boolean = CompareData(NewObj, CurrentObj, "Regiment")
Dim Trade As Boolean = CompareData(NewObj, CurrentObj, "Trade")

Private Function CompareData(NewObj As Business.Casualty, CurrentObj As Business.Casualty, FieldToComapre As String) As Boolean

 Select Case FieldToComapre
        Case "Trade"
            Return NewCasualty.Trade.NullableEquals(CurrentCasualty.Trade)
        Case "Rank"
            Return NewCasualty.Rank.NullableEquals(CurrentCasualty.Rank)
        Case "Regiment"
            Return NewCasualty.Regiment.NullableEquals(CurrentCasualty.Regiment)                     
    Case Else
        Return True
End Select

End Function

public static class NullableCompare 
{
    public static bool NullableEquals<T>(this T s1, T s2)
                               where T : class
    {
        if (s1 == null)
        {
            return s2 == null;
        }

        return s1.Equals(s2);
    }

}
public partial class Rank 
{
public override bool Equals(object obj)
    {
        var p2 = obj as Rank;

        if (p2 == null)
        {
            return false;
        }

        if (this.ID != p2.ID)
        {
            return false;
        }

        return this.ID == p2.ID;
    }

    public override int GetHashCode()
    {
        return this.ID.GetHashCode();
    }
}