你能从这两种方法中重构一个共同的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
Func
到Func
。
这使我能够使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
变量?