2009-11-25 74 views
32

使用C#和.NET 3.5,處理這種情況的最佳方法是什麼。我有數百個字段來比較各種來源(主要是字符串)。有時源會返回字符串字段爲空,有時爲空。當然,有時在這些領域還有文字。例如,我當前對strA!= strB的比較並不是因爲strA爲空而是strB爲「」而導致的。我知道我可以做string.IsNullOrEmpty,這會導致雙重比較和一些醜陋。有沒有更好的方法來處理這個問題?我以爲擴展方法,但你不能擴展運算符。String比較null和empty是否相等

我想我正在尋找一個性感的方式來做到這一點。

+2

你能不thave「源」返回字符串空呢,還是希望有一個可用的空字符串? – 2009-11-25 15:00:43

回答

51

既然你已經有了數百比較做的,這聽起來像你需要一個函數來調用,以便減少代碼中的混亂和重複。我不認爲有一個內置的功能做一個空/空字符串/對比檢查於一身,但你可能只是自己做一個:

static class Comparison 
{ 
    public static bool AreEqual(string a, string b) 
    { 
     if (string.IsNullOrEmpty(a)) 
     { 
      return string.IsNullOrEmpty(b); 
     } 
     else 
     { 
      return string.Equals(a, b); 
     } 
    } 
} 

然後,你可以只使用一個調用你的每一個對比功能:

 if(Comparison.AreEqual(strA[0], strB[0])) { // ... } 
     if(Comparison.AreEqual(strA[1], strB[1])) { // ... } 
     if(Comparison.AreEqual(strA[2], strB[2])) { // ... } 
     if(Comparison.AreEqual(strA[3], strB[3])) { // ... } 

這種方法也更容易擴大,如果你以後發現你需要擔心的其他情況,如在一開始忽略空格或字符串的結束;那麼你可以在你的函數中添加更多的邏輯來做一些修整或者其他的操作,而且你不需要對調用你的函數的數百行代碼做任何修改。

+0

String.Equals(a,b)也處理null比較,因此可以刪除字符串.IsNullOrEmpty()檢查 https://msdn.microsoft.com/en-us/library/1hkt4325(v=vs .90).aspx – abhaybhatia 2016-10-06 16:06:35

+1

@abhaybhatia String.Equals(a,b)不認爲null等於空字符串,這是所期望的。因此,string.IsNullOrEmpty檢查是必需的。 – 2016-10-15 00:36:46

54

不消除額外的潛在的比較,但對於性感的因素,你可以使用這樣的事情:

(strA ?? "") == (strB ?? "") 

或略少的性感,但最好形式:

(strA ?? string.Empty) == (strB ?? string.Empty) 
+0

那麼,我試圖繞過重做數百個擴展方法的比較,但我想我將不得不咬緊牙關。我最終可能會寫出一個在幕後執行此操作的方法。謝謝。 – billb 2009-11-25 15:00:51

+8

+1,但只有其中包含'String.Empty'的部分! – user7116 2009-11-25 15:04:13

+0

'string.Empty'不像性感(不太緊湊),這就是爲什麼我包括這兩個,但是,使用'string.Empty'是首選。 – iammichael 2009-11-25 15:07:40

5

那麼

strA ?? "" == strB ?? "" 
2

string.IsNullOrEmpty()有什麼問題?我相信,因爲它是.NET框架的一部分,所以它被優化,可能比我們可以編寫的東西更有效率。它可能不夠性感,但它的工作原理。編寫容易閱讀的代碼,並讓編譯器梳理細節。

+0

因爲有兩個檢查,我必須現在用所有這些噪音取代數百個比較。 – billb 2009-11-25 14:59:29

+0

這可能是,但不能找到替換幫助你更新代碼? – TLiebe 2009-11-25 15:02:08

+0

當然,但是你不打算取代數百個比較嗎?你打算如何在沒有人工努力的情況下替換'!='? – 2009-11-25 15:02:23

9

不夠性感的??,但你可以避開當時的雙比較部分,如果你將其短路:

string.IsNullOrEmpty(strA) ? string.IsNullOrEmpty(strB) : (strA == strB) 
0

如果你的2組字段是在某種集合中,你可能可以使用LINQ來獲得你的優勢。如果他們在某種集合,它允許您通過密鑰來訪問他們,他們都具有相同的鍵,你可以使用這個(準備粘貼到LINQPad):

Dictionary<string,string> fields1 = new Dictionary<string,string>(); 
Dictionary<string,string> fields2 = new Dictionary<string,string>(); 

fields1.Add("field1", "this"); 
fields2.Add("field1", "this"); 
fields1.Add("field2", "is"); 
fields2.Add("field2", ""); 
fields1.Add("field3", "a"); 
fields2.Add("field3", null); 
fields1.Add("field4", "test"); 
fields2.Add("field4", "test"); 

var test = 
from f1 in fields1 
    join f2 in fields2 
    on f1.Key equals f2.Key 
select (f1.Value ?? "") == (f2.Value ?? ""); 

test.Dump(); 

如果你的套在2個索引收藏領域以相同的順序,你可以使用這樣的事情:

string[] strings1 = { "this", "is", "a", "test" }; 
string[] strings2 = { "this", "", null, "test" }; 

var test = 
from s1 in strings1.Select((value,index) => new {value, index}) 
    join s2 in strings2.Select((value,index) => new {value, index}) 
    on s1.index equals s2.index 
select (s1.value ?? "") == (s2.value ?? ""); 

test.Dump(); 
0

的解決方案,其他人,放棄,包括提出以定義字符串的比較類的人,忘了寫一個新的GetHashCode你的琴絃。

這意味着您的字符串不能用於取決於GetHashCode的類,如Dictionary<T>HashSet<T>

Why is it important to override GetHashCode when Equals method is overridden?

當你決定改變任何類平等的概念,你應該寫這個類的EqualityComparer。這可以確保,如果根據您更改的等於對象的定義被認爲相等,則它們的GetHashCode將返回相等的值。

public class NullStringComparer : EqualityComparer<string> 
{ 
    public override bool Equals(string x, string y) 
    { 
     // equal if string.Equals(x, y) 
     // or both StringIsNullOrEmpty 
     return String.Equals(x, y) 
      || (String.IsNullOrEmpty(x) && String.IsNullOrEmpty(y)); 
    } 

    public override int GetHashCode(string obj) 
    { 
     if (String.IsNullOrEmpty(obj)) 
      return 0; 
     else 
      return obj.GetHashCode(); 
    } 
} 

用法:

public static void Main() 
{ 
    string x = null; 
    string y = String.Empty; 

    Console.WriteLine($"Standard string comparison: {StringComparer.Ordinal.Equals(x, y)}"); 

    IEqualityComparer<string> equalityComparer = new NullStringComparer(); 
    Console.WriteLine($"My string comparison {equalityComparer.Equals(x, y)}"); 

    int hashX = equalityComparer.GetHashCode(x); 
    int hashY = equalityComparer.GetHashCode(y); 
    Console.WriteLine($"hash X = {hashX}, hash Y = {hashY}"); 
}