2011-02-15 18 views
2

想知道是否有更好的方法來處理多個相似的條件語句和操作,如下面的示例代碼片段所示。避免連續的類似條件塊的方式

private void AddCommonDictionaryItemsForAllAttributes(MyCustomType dc, string statusFlag) 
{ 
    if (dc.xmlAttributes == null) { 
     dc.xmlAttributes = new Dictionary<string, string>(); 
    } 
    dc.xmlAttributes.Add(Constant.CD_1, statusFlag); 
    dc.xmlAttributes.Add(Constant.CD_2, statusFlag); 
    dc.xmlAttributes.Add(Constant.CD_3, statusFlag); 
    if (dc.primaryZone != null) { 
     dc.xmlAttributes.Add(Constant.CD_4, statusFlag); 
    } 
    if (dc.Mgr1 != null) { 
     dc.xmlAttributes.Add(Constant.CD_10, statusFlag); 
    } 
    if (dc.Mgr2 != null) { 
     dc.xmlAttributes.Add(Constant.CD_11, statusFlag); 
    } 
    if (dc.Mgr3 != null) { 
     dc.xmlAttributes.Add(Constant.CD_5, statusFlag); 
    }  
    if (dc.Producer != null) { 
     dc.xmlAttributes.Add(Constant.CD_6, statusFlag); 
    } 
    if (dc.CountTest > 0) { 
     dc.xmlAttributes.Add(Constant.CD_7, statusFlag); 
    } 
    if (dc.List1 != null && dc.List1.Count > 0) { 
     dc.xmlAttributes.Add(Constant.CD_8, statusFlag); 
    } 
    if (dc.List2 != null && dc.List2.Count > 0) { 
     dc.xmlAttributes.Add(Constant.CD_9, statusFlag); 
    } 
} 

的,如果條件和除了字典操作在我看來,作爲冗餘,從而尋找出更高效,更優雅的方式實現代碼。

謝謝!

更新:我使用.NET 3.5

+0

爲了減少空間,您可以將語句放在與條件相同的行上,但我無法看到任何方式來擺脫長長的條件列表。抱歉。 – Darkhydro 2011-02-15 07:37:29

回答

4

您可以創建一個輔助類,它提供了一個試驗中對MyCustomType的實例執行,關鍵在xmlAttributes字典使用:

class Rule 
{ 
    private readonly Predicate<MyCustomType> _test; 
    private readonly string _key; 

    public Predicate<MyCustomType> Test { get { return _test; } } 
    public string Key { get { return _key; } } 

    public Rule(Predicate<MyCustomType> test, string key) 
    { 
     _test = test; 
     _key = key; 
    } 
} 

然後,您可以創建一組規則並列舉它們:

private void AddCommonDictionaryItemsForAllAttributes(MyCustomType dc, string statusFlag) 
    { 

     var rules = new Rule[] 
     { 
      new Rule(x => x.Mgr1 != null, Constant.CD_4), 
      new Rule(x => x.Mgr2 != null, Constant.CD_10), 
      //...snip... 
      new Rule(x => x.List2 != null && x.List2.Count > 0, Constant.CD_9) 
     }; 

     foreach(var rule in rules.Where(r => r.Test(dc))) 
      dc.xmlAttributes.Add(rule.Key, statusFlag); 
    } 
-1

有兩種方式: 1.使用開關的情況下 2.使用三元操作符

都將讓你的代碼看起來很乾淨,但在你的情況下開關的情況下無法正常工作。

+0

只有在只有一種情況適用的情況下,才能使用開關盒。我不認爲這是這種情況。我也不知道三元運營商將如何幫助這裏。 – codymanix 2011-02-15 08:14:08

2

一種選擇是有某種條件列表和這些條件所代表的常量。例如:

var list = new List<Tuple<Predicate<MyCustomType>, string>> 
{ 
    Tuple.Create(dc => true, Constant.CD_1), 
    Tuple.Create(dc => true, Constant.CD_2), 
    Tuple.Create(dc => true, Constant.CD_3), 
    Tuple.Create(dc => dc.primaryZone != null, Constant.CD_4), 
    Tuple.Create(dc => dc.Mgr1 != null, Constant.CD_5), 
    // etc 
}; 

然後你可以只遍歷列表中,只要謂詞是真實的詞典中的相關設置爲status:您可以設置列表了靜態一旦

foreach (var tuple in list) 
{ 
    if (tuple.Item1(dc)) 
    { 
     dc.xmlAttributes.Add(tuple.Item2, statusFlag); 
    } 
} 

注然後在任何地方重複使用它,因爲列表本身不會改變。

+0

謝謝,但我正在使用.NET 3.5。 :( Tuple將會是什麼合適的替代品? – Dienekes 2011-02-15 12:35:54

+0

@Dienekes:你可以很容易地編寫自己的Tuple等價物,或者根據Fencliff的答案自定義類型 - 儘管我不會使用可變結構 – 2011-02-15 12:47:05

0

考慮在YourCustomClass中封裝屬性集合。這將保護你的屬性免受意外改變,並且它將把屬性填充到它所屬的數據。

優點:

  • 您可以更改屬性,隨時填補實施,在不改變客戶端(條件,謂詞集合等)。
  • 更乾淨客戶
  • 更容易維護

所以,即使您的默認實現使用將是這樣的:

dc.SetStaus(string statusFlag) 

而且所有的骯髒的工作將內部直流完成(BTW我建議使用枚舉CD而不是常量,但它取決於你):

public void SetStatus(string statusFlag) 
{ 
    if (_xmlAttributes == null) 
     _xmlAttributes = new Dictionary<CD, string>(); 

    _xmlAttributes.Add(CD.CD_1, statusFlag); 
    _xmlAttributes.Add(CD.CD_2, statusFlag); 
    _xmlAttributes.Add(CD.CD_3, statusFlag); 

    if (_primaryZone != null) 
     _xmlAttributes.Add(CD.CD_4, statusFlag); 

    if (_mgr1 != null) 
     _xmlAttributes.Add(CD.CD_10, statusFlag); 

    if (_mgr2 != null) 
     _xmlAttributes.Add(CD.CD_11, statusFlag); 

    if (_mgr3 != null) 
     _xmlAttributes.Add(CD.CD_5, statusFlag); 

    if (_producer != null) 
     _xmlAttributes.Add(CD.CD_6, statusFlag); 

    if (_countTest > 0) 
     _xmlAttributes.Add(CD.CD_7, statusFlag); 

    if (_list1 != null && _list1.Count > 0) 
     _xmlAttributes.Add(CD.CD_8, statusFlag); 

    if (_list2 != null && _list2.Count > 0) 
     _xmlAttributes.Add(CD.CD_9, statusFlag); 
} 

Afte r你可以輕鬆地重構實現:

private Dictionary<CD, Func<bool>> _statusSetConditions; 

public MyCustomType() 
{ 
    _statusSetConditions = new Dictionary<CD, Func<bool>>(); 
    _statusSetConditions.Add(CD.CD_1,() => true); 
    _statusSetConditions.Add(CD.CD_2,() => true); 
    _statusSetConditions.Add(CD.CD_3,() => true); 
    _statusSetConditions.Add(CD.CD_4,() => _primaryZone != null); 
    ... 
    _statusSetConditions.Add(CD.CD_11,() => _mgr2 != null); 
} 

public void SetStatus(string statusFlag) 
{ 
    if (_xmlAttributes == null) 
     _xmlAttributes = new Dictionary<CD, string>(); 

    foreach (CD cd in Enum.GetValues(typeof(CD))) 
     AddStatusAttribute(cd, statusFlag); 
} 

private void AddStatusAttribute(CD cd, string statusFlag) 
{ 
    Func<bool> condition; 

    if (!_statusSetConditions.TryGetValue(cd, out condition)) 
     return; // or throw exception 

    if (condition()) 
     _xmlAttributes.Add(cd, statusFlag); 
} 

而客戶端仍然只是調用dc.SetStatus(statusFlag);

也許在封裝這個狀態設置邏輯之後,您只需將狀態保存在YourCustomClass的字段中。

0

梅。這不是真的多餘的,除非你想考慮像java反射這樣的東西。想想輔助方法:

 
void addIfOk(int test, MyCustomType dc, String attr, string statusFlag) { 
    if(test!=0) dc.xmlAttributes.Add(attr, statusFlag); 
} 
void addIfOk(Object test, MyCustomType dc, String attr, string statusFlag) { 
    if(test!=null) dc.xmlAttributes.Add(attr, statusFlag); 
} 
void addIfOk(Collection test, MyCustomType dc, String attr, string statusFlag) { 
    if(test!=null&&!test.isEmpty()) dc.xmlAttributes.Add(attr, statusFlag); 
} 

的代碼就變成了:

 
    addIfOk(dc.Mgr1, dc, Constant.CD_10, statusFlag); 
    addIfOk(dc.Mgr2, dc, Constant.CD_11, statusFlag); 
    addIfOk(dc.Mgr3, dc, Constant.CD_5, statusFlag); 
    addIfOk(dc.Producer, dc, Constant.CD_5, statusFlag); 

等。也許這會更有意義作爲您的自定義類型中的一種方法:setXmlStatusAttributes(statusfFlag)