从此代码段中删除重复项

时间:2011-10-28 12:24:12

标签: c# coding-style refactoring duplicates

寻找有关从此代码段删除重复内容的建议:

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);
}

编辑:这是一个简化的上下文,可能会有更多像这样的列表连接

3 个答案:

答案 0 :(得分:3)

我真的不认为删除你所说的“重复”是必要的。您不会出现两次相同的代码,但会出现两次相似的代码。这很常见,无需担心。

答案 1 :(得分:2)

我同意没有太多的重复,但也许这个“字面翻译”进入Linq Extensions 是你正在寻找的(键入浏览器,所以没有测试 - ):

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,你可以写得更清晰(/高效?):

提取lambda会缩短行数:

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次调用

答案 2 :(得分: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();
}