2011-10-28 81 views
2

尋找建議從這個片段中去除重複刪除重複:從這個代碼片段

foreach (Car car in carList) { 
    DataRow row = NewRow(); 

    StringBuilder sbConfigurations = new StringBuilder();  
    foreach (ConfigurationItem configurationItem in car.Configurations) 
     sbConfigurations.AppendFormat("{0}: {1}\n", configurationItem.Name, configurationItem.Value); 

    row["configurations"] = sbConfigurations; 


    StringBuilder sbOptionals = new StringBuilder(); 
    foreach (OptionalItem optionalItem in car.Optionals) 
     sbOptionals.AppendFormat("{0}, ", optionalItem.Name); 

    row["optionals"] = sbOptionals; 

    Rows.Add(row); 
} 

編輯:這是一個簡化的背景下,可能會有更多列表加入這樣的

+0

我在想什麼使用索引名稱的數組,但後來我看到你正在調用'car.Optionals'。你可以通過反射來做到這一點,但這並不會讓它變得更好。 – Marnix

+0

配置和選項是否來自一個公共基類?如果不是,那麼重要的簡化可能會涉及反思。如果你要這麼做很多,你可以證明編寫obj.FormattedOutput(「{Name}:{Value} \ n」)函數是合理的。 –

回答

2

我同意沒有太多的重複,但也許這「直譯」成LINQ的擴展 是你在找什麼(類型的瀏覽器,所以沒有測試 - 至今):

foreach (Car car in carList) { 
    DataRow row = NewRow(); 

    row["configurations"] = car.Configurations.Aggregate(new StringBuilder(), (a,i) => a.AppendFormat("{0}: {1}\n", i.Name, i.Value)); 
    row["optionals"] = car.Optionals.Aggregate(new StringBuilder(), (a,i) => a.AppendFormat("{0}, ", i.Name)); 

    Rows.Add(row); 
} 

另外,你可以把它寫稍微更清晰(/效率?)沒有stringbuilders:

提取拉姆達作出線較短:

Func<Car, string> nameValue = car => string.Format("{0}: {1}\n", car.Name, car.Value); 

foreach (var car in carList) { 
    var row = new Dictionary<string, string>(); 

    row["configurations"] = string.Join("\n", car.Configurations.Select(nameValue)); 
    row["optionals"]  = string.Join(", ", car.Optionals.Select(i => i.Name)); 

    list.Add(row); 
} 

注意前C#4.0中,您需要在第二個參數附加.ToArray()調用string.Join

+0

剛剛學到了一個新的c#特性:P,雖然我覺得在同一行中有太多的函數調用,但我也在尋找乾淨的代碼。 –

+1

呵呵。改善了一點 - 解決了「長線」的抱怨。 – sehe

3

我不真的不認爲去除你所說的「重複」是必要的。您沒有兩次出現相同的代碼,但有兩次出現類似的代碼。這是常見的,沒有什麼值得關注的。

+0

這是一個觀點,但我仍然認爲我可以實現一些內容來抽象行列中的插入操作列表。 –

+0

@arkilus:是的,你可以,但我;我不確定它是否有意義,在這樣一個簡單的情況下,將在一分鐘後發佈解決方案 – sll

+0

在我的例子中只有1個「重複」,如果我要添加更多像這些列? –

2

如何思考這個問題顛倒。而不是使每個對象的功能都瞭解DataRow格式,讓每個對象都瞭解DataRow格式。如果你不使用object.ToString()什麼,你可以讓ConfigurationItemOptionalItem實施object.ToString()

class ConfigurationItem 
{ 
    public string override ToString() 
    { 
     return string.Format("{0}: {1}\n", Name, Value); 
    } 
} 

class OptionalItem 
{ 
    public string override ToString() 
    { 
     return string.Format("{0}, ", Name); 
    } 
} 

現在你可以使用一個循環對所有類型的對象:

string BuildDataRowString(IEnumerable collection) 
{ 
    var sb = new StringBuilder(); 
    foreach (var o in collection) sb.Append(o.ToString()); 
    return sb.ToString(); 
} 

row["configurations"] = car.Configurations.BuildDataRowString(); 
row["optionals"] = car.Optionals.BuildDataRowString(); 

如果您需要object.ToString()出於其他目的,您可以添加一個自定義格式爲「DataRow格式」:

class ConfigurationItem : IFormattable 
{ 
    public string override ToString(string format, IFormatProvider formatProvider) 
    { 
     if (format == "D") { 
      return string.Format(formatProvider, "{0}: {1}\n", Name, Value); 
     } 
     return this.ToString(); // otherwise format as default 
    } 
} 

class OptionalItem : IFormattable 
{ 
    public string override ToString(string format, IFormatProvider formatProvider) 
    { 
     if (format == "D") { 
      return string.Format(formatProvider, "{0}, ", Name); 
     } 
     return this.ToString(); // otherwise format as default 
    } 
} 

string BuildDataRowString(this IEnumerable e, string format) 
{ 
    StringBuilder sb = new StringBuilder(); 
    foreach (var o in e) sb.AppendFormat("{0:D}", o); 
    return sb.ToString(); 
} 
相關問題