簡體   English   中英

在C#中,將字符串與null進行比較以及“”返回true的最佳方法是什么

[英]In C#, what is the best way to compare strings with null and “” return true

我有以下代碼(因為我試圖檢測字段的更改)

 if (person.State != source.State)
 {
      //update my data . .
  }

問題是我遇到的情況是person.State為NULL而source.State為“”,因此返回true。

如果一個為null而另一個是空字符串,我想將它們視為相等並且不更新我的數據。 這樣做最干凈的方法是什么? 我是否需要創建自己的Comparer對象,因為這似乎是一個普遍的問題

如果你真的需要,你可以這樣做:

if ((person.State ?? string.Empty) != (source.State ?? string.Empty))
{
    // ...
}

但是,根據您的需要,更好的解決方案可能是修改person.State屬性永遠不會返回空值。

public class Person
{
    string _state = string.Empty;
    public string State
    {
        get { return _state; }
        set { _state = value ?? string.Empty; }
    }
}

就個人而言,我會對上游進行消毒/規范化,但如果我必須在這里進行:

// check different, treating null & "" as equivalent
if ((person.State ?? "") != (source.State ?? ""))

雖然其他答案都很好,但我會將它們引入自己的方法,以使讀者更清楚:

public static bool StatesEqual(string first, string second)
{
  return first ?? "" == second ?? "";
}

如果您在多個位置比較這些狀態,或者允許您處理其他奇怪的情況,這將是有益的。 (示例可能是將其更改為不區分大小寫,或者如果兩個狀態在文本上不同,但是一個是另一個的縮寫,即您希望“WI”等於“Wisconsin”。

你認為會有一個StringComparison枚舉值來處理這個String.Equals ...或一個CompareOptions枚舉值來處理它與String.Compare ...但沒有。

無論如何,我認為你仍然應該使用String.Equals作為最佳實踐。

string s1 = null;
string s2 = string.Empty;

bool areEqual = string.Equals(s1 ?? string.Empty, s2 ?? string.Empty);

// areEqual is now true.

像這樣你可以輕松添加案例或文化字符串比較選項...

bool areEqual = string.Equals(s1 ?? string.Empty, s2 ?? string.Empty, StringComparison.OrdinalIgnoreCase);

我是否需要創建自己的Comparer對象,因為這似乎是一個普遍的問題

現在應該從這里的好答案中清楚地知道,你沒有,但如果你反復進行這種比較,或者想要將狀態用作鍵,那么:

public class NullEmptStringComparer : IComparer<string>
{
  public Equals(string x, string y)
  {
    return (x ?? string.Empty) == (y ?? string.Empty);
  }
  public int GetHashCode(string str)
  {
    return (str ?? string.Empty).GetHashCode();
  }
}

或者基於另一個比較,如果默認==比較不合適(它很少,真的):

public class NullEmptCustStringComparer : IComparer<string>
{
  private readonly IComparer<string> _baseCmp;
  public NullEmptCustStringComparer(IComparer<string> baseCmp)
  {
    _baseCmp = baseCmp;
  }
  public Equals(string x, string y)
  {
    return _baseCmp.Equals(x ?? string.Empty, y ?? string.Empty);
  }
  public int GetHashCode(string str)
  {
    return _baseCmp.GetHashCode(str ?? string.Empty);
  }
}

這聽起來像是擴展方法的完美解決方案。

    public static bool IsEqualNoNulls(this String str, string cmp) //bad name, but you get the point
    {
        return (str ?? "") == (cmp ?? "");
    }

....或者只是使用我可能更喜歡的擴展方法的主體,因為我不認為這是一個太多的樣式問題。

String類有一個函數“IsNullOrEmpty”,它接受一個字符串。

http://msdn.microsoft.com/en-us/library/system.string.isnullorempty.aspx

從文檔:

IsNullOrEmpty是一種便捷方法,使您可以同時測試String是否為null或其值是否為 它等同於以下代碼:

result = s == null || s == String.Empty;

例如:

if (!(string.IsNullOrEmpty(person.State) && string.IsNullOrEmpty(source.State)))
{
      //update your data . .
}

或者,您可以使用擴展方法,類似於@Earlz概述的方法

你可以在這里了解更多關於它們的信息http://msdn.microsoft.com/en-us/library/bb383977.aspx

因此,假設我有一個如下所示的擴展方法:

public static bool IsBlank(this string str)
{
    return string.IsNullOrEmpty(str);
}

這將允許你做類似的事情

if(!(person.State.IsBlank() && source.State.IsBlank())
{
     //do something
}

這個工作的原因,即使person.State或source.State為null ,因為擴展方法看起來像字符串類的方法,實際上轉換為靜態方法,字符串變量作為它的參數(根據文檔),即使字符串變量未設置為字符串實例,它也會很愉快地工作。

但請記住,如果您正在閱讀代碼並嘗試在person.State或source.State設置為null時嘗試找出其工作原理,那么這樣做可能會在以后絆倒您:P

或者,你知道,或者我只是寫出一個完整的比較:)

所有給出的答案都將通過土耳其測試 試試這個:

public static bool StatesEqual(string first, string second)
{
    if (first == null || second == null)
        return false; // You can also use return first == second if you want to compare null values.

    return first.Equals(second, StringComparison.InvariantCulture);
}

好吧,空和null不是一回事,所以你不是指這里的一般問題。 您的域名問題是您的業務規則要求特定評估為真。 您總是可以編寫一個如下所示的方法:

public static bool AreMyStringsCustomEqual(string s1, string s2) {
    return (s1 == null || s1 == "" && s2 == null || s2 == "");
}

或類似的東西。 然后從各處調用它。 你甚至可以把它作為一種擴展方法。

我相信這是Decorator模式的一個案例。 你需要裝飾一個庫存StringComparer來做你想要的:

public enum Collapse
{
  None                      = 0 ,
  EmptyAndWhitespace        = 1 ,
  NullAndWhitespace         = 2 ,
  NullAndEmpty              = 3 ,
  NullAndEmptyAndWhitespace = 4 ,
}

public class MySpecialStringComparerDecorator : StringComparer
{
  const   string         COLLAPSED_VALUE = "" ;
  private StringComparer instance ;
  private Collapse     rule     ;

  public StringComparer Decorate( StringComparer sc , Collapse equivalencyRule )
  {
    StringComparer instance = new MySpecialStringComparer( sc , equivalencyRule ) ;
    return instance ;
  }

  private MySpecialStringComparerDecorator( StringComparer comparer , Collapse equivalencyRule )
  {
    if ( comparer == null                                  ) throw new ArgumentNullException("comparer") ;
    if ( !Enum.IsDefined(typeof(Collapse),equivalencyRule) ) throw new ArgumentOutOfRangeException("equivalencyRule") ;

    this.instance = comparer ;
    this.rule     = equivalencyRule ;

    return ;
  }

  private string CollapseAccordingToRule( string s )
    {
        string collapsed = s ;
        if ( rule != Collapse.None )
        {
            if ( string.IsNullOrWhiteSpace(s) )
            {
                bool isNull  = ( s == null ? true : false ) ;
                bool isEmpty = ( s == ""   ? true : false ) ;
                bool isWS    = !isNull && !isEmpty ;

                switch ( rule )
                {
                    case Collapse.EmptyAndWhitespace        : if ( isNull||isWS          ) collapsed = COLLAPSED_VALUE ; break ;
                    case Collapse.NullAndEmpty              : if ( isNull||isEmpty       ) collapsed = COLLAPSED_VALUE ; break ;
                    case Collapse.NullAndEmptyAndWhitespace : if ( isNull||isEmpty||isWS ) collapsed = COLLAPSED_VALUE ; break ;
                    case Collapse.NullAndWhitespace         : if ( isNull||isWS          ) collapsed = COLLAPSED_VALUE ; break ;
                    default                                 : throw new InvalidOperationException() ;
                }
            }
        }
        return collapsed ;
    }

  public override int Compare( string x , string y )
  {
    string a     = CollapseAccordingToRule(x) ;
    string b     = CollapseAccordingToRule(y) ;
    int    value = instance.Compare(a,b);
    return value ;
  }

  public override bool Equals( string x , string y )
  {
    string a     = CollapseAccordingToRule(x) ;
    string b     = CollapseAccordingToRule(y) ;
    bool   value = instance.Equals(a,b) ;
    return value ;
  }

  public override int GetHashCode( string obj )
  {
    string s     = CollapseAccordingToRule(obj) ;
    int    value = instance.GetHashCode( s ) ;
    return value ;
  }

}

用法很簡單:

StringComparer sc = new MySpecialStringDecorator( StringComparer.CurrentCultureIgnoreCase , Collapse.NullAndEmptyAndWhitespace ) ;

// go to town

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM