你能从这两种方法中重构一个共同的function吗?

我有两种方法基本上将底层复选框的文本或标记转换为CSV字符串。

这两种方法

  • GetSelectedTextAsCsv()
  • GetTagAsCsv()

不同之处仅在于从SelectedCheckBoxes提取值的属性 ,其类型为IList

  public string GetSelectedTextAsCsv() { var buffer = new StringBuilder(); foreach (var cb in SelectedCheckBoxes) { buffer.Append(cb.Text).Append(","); } return DropLastComma(buffer.ToString()); } public string GetTagAsCsv() { var buffer = new StringBuilder(); foreach (var cb in SelectedCheckBoxes) { buffer.Append(cb.Tag).Append(","); } return DropLastComma(buffer.ToString()); } 

我试图提取一个返回Func的方法,但不知道如何将其拉出来。 我的糟糕尝试如下所示,但我无法弄清楚如何提取属性部分,如ConvertToCsv()中的注释所示

  public Func ConvertToCsv() { return propertyName => { var buffer = new StringBuilder(); foreach (var checkBox in SelectedCheckBoxes) { buffer.Append( /* How can you abstract this portion? like following? */ checkBox.propertyName ).Append(","); } return DropLastComma(buffer.ToString()); }; } 

如果我走错了路,你能告诉我如何重构代码以使用常用方法吗?

[更新1]这是Brian和Jon的答案的组合

  public string ConvertToCsv(Func getValue) { var stringValues = SelectedCheckBoxes.Select( cb => getValue(cb).ToString()).ToArray(); return string.Join(",", stringValues); } public string GetSelectedTextAsCsv() { return ConvertToCsv(cb => cb.Text); } public string GetTagAsCsv() { return ConvertToCsv(cb => cb.Tag); } 

[更新2]版本2

  public string GetAsCsv(Func getValue) { return string.Join(",", SelectedCheckBoxes.Select( cb => getValue(cb).ToString()).ToArray()); } public string GetSelectedTextAsCsv() { return GetAsCsv(cb => cb.Text); } public string GetTagAsCsv() { return GetAsCsv(cb => cb.Tag == null ? string.Empty : cb.Tag.ToString()); } 

[更新3]GetAsCsv()的参数作为CheckBox和string的封闭generics

FuncFunc

这使我能够使GetAsCsv()更简单,更易读。

 private string GetAsCsv(Func getValue) { return string.Join(",", SelectedCheckBoxes.Select(getValue).ToArray()); } 

 public string GetAsCsv(Func getValue) { var buffer = new StringBuilder(); foreach (var cb in SelectedCheckBoxes) { buffer.Append(getValue(cb)).Append(","); } return DropLastComma(buffer.ToString()); } 

然后:

 GetAsCsv(cb => cb.Tag != null ? cb.Tag.ToString() : string.Empty); GetAsCsv(cb => cb.Text); 

我会使用string.Join代替:

 string tags = string.Join(",", SelectedCheckBoxes.Select(cb => Convert.ToString(cb.Tag)) .ToArray()); string text = string.Join(",", SelectedCheckBoxes.Select(cb => cb.Text).ToArray()); 

当然,你可以把它放到一个方法中,但我可能不会只打扰两个电话。

如果你想,那么使用Brian的模板看起来如何:

 public string GetAsCsv(Func getValue) { string[] array = SelectedCheckBoxes.Select(getValue).ToArray(); return string.Join(",", array); } 

你可以使用lambda:

 public string ConvertToCSV(Func cb_prop) { ... buffer.Append(cb_prop(cb)).Append(","); ... } ConvertToCSV(c => c.Tag); 

我只是围绕IEnumerable字符串编写一个简短的扩展方法,它带有一个分隔符:

 public static string Join(this IEnumerable strings, string separator) { return string.Join(separator, strings.ToArray()); } 

然后你可以这样做:

 var text = SelectedCheckBoxes.Select(cb => cb.Text).Join(", "); var tags = SelectedCheckBoxes.Select(cb => (string)cb.Tag).Join(", "); 

由于除了 getter 之外两个函数完全相同,因此您应该从这里开始:移动部分。

还没有刷过我的C#,但有些东西:

  public string GetCsv(Func getter) { var buffer = new StringBuilder(); foreach (var cb in SelectedCheckBoxes) { buffer.Append(getter()).Append(","); } return DropLastComma(buffer.ToString()); } 

应该管用。 另外,使SelectedCheckBoxes变量?