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

时间:2009-04-09 18:55:25

标签: c# .net refactoring csv

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

这两种方法

  • GetSelectedTextAsCsv()
  • GetTagAsCsv()

仅与属性SelectedCheckBoxes中提取值的区别不一,IList<CheckBox>类型为 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<T, TResult>

我试图提取一个返回ConvertToCsv()的方法,但不确定如何将其关闭。 我的糟糕尝试如下所示,但我无法弄清楚如何提取属性部分,如 public Func<T, string> ConvertToCsv<T>() { 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()); }; }

中的注释所示
    public string ConvertToCsv<T>(Func<CheckBox, T> 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);
    }

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

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

    public string GetAsCsv<T>(Func<CheckBox, T> 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());
    }

[更新2] 第2版

GetAsCsv()

[更新3] Func<CheckBox, T>的参数作为CheckBox和字符串的封闭通用

  

Func<CheckBox, string>GetAsCsv()

这使我private string GetAsCsv(Func<CheckBox, string> getValue) { return string.Join(",", SelectedCheckBoxes.Select(getValue).ToArray()); } 更简单,更易读。

{{1}}

5 个答案:

答案 0 :(得分:22)

public string GetAsCsv(Func<CheckBox, string> 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);

答案 1 :(得分:19)

我改用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<CheckBox, string> getValue)
{
    string[] array = SelectedCheckBoxes.Select(getValue).ToArray();
    return string.Join(",", array);
}

答案 2 :(得分:2)

你可以使用lambda:

public string ConvertToCSV(Func<CheckBox, string> cb_prop) {
    ...
    buffer.Append(cb_prop(cb)).Append(",");
    ...

}

ConvertToCSV(c => c.Tag);

答案 3 :(得分:1)

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

public static string Join(this IEnumerable<string> 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(", ");

答案 4 :(得分:0)

由于两个函数完全相同除了之外的getter,这就是你应该开始的地方:移动部分。

还没有刷过我的C#,但是还有以下几点:

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

应该有效。另外,make SelectedCheckBoxes变量?