是否有更好(更快,更方便)的方法来连接多个(可空)对象?

时间:2015-11-19 14:15:32

标签: c# .net

我最终编写了自己的帮助类来连接对象:ConcatHelper.cs

您会在要点中看到一些示例,但也会在以下代码段中看到:

model.Summary = new ConcatHelper(", ")
.Concat(diploma.CodeProfession /* can be any object, will be null checked and ToString() called */)
.BraceStart() // if everything between the braces is null or empty, the braces will not appear
.Concat(diploma.CodeDiplomaType)
.Concat(label: DiplomaMessage.SrkRegisterId, labelSeparator: " ", valueDecorator: string.Empty, valueToAdd: diploma.SrkRegisterId)
.BraceEnd()
.Concat(diploma.CodeCountry)
.BraceStart()
.Concat(diploma.DateOfIssue?.Year.ToString(CultureInfo.InvariantCulture)) // no separator will be added if concatenated string is null or empty (no ", ,")
.BraceEnd()
.Concat(DiplomaMessage.Recognition, " ", string.Empty, diploma.DateOfRecognition?.Year.ToString(CultureInfo.InvariantCulture))
.ToString(); // results in something like: Drogist / Drogistin (Eidgenössischer Abschluss, SRK-Registrierungsnummer 3099-239), Irland (1991)

优点:

  • null检查你,避免if / else分支。
  • 支持标注,装饰和分隔值。如果值为null,则不添加标签。
  • 加入一切,流利的符号 - 少代码
  • 很好地做域对象的摘要。

魂斗罗:

  • 相当慢:
    • 我为上述例子测量了7毫秒
    • 我在实际例子中测量了每个连接0.01026ms(参见unit-test gist
    • 它不是静态的(可能是吗?)
    • 需要一个列表来跟踪所有内容。
    • 可能是矫枉过正。

因此我现在开始覆盖域对象的许多ToString()方法,如果有更好的方法,我不确定。

通过更好我的意思是:

  • 是否有一个库已经完成了我需要的东西?
  • 如果没有,可以加速而不会失去方便的流利符号吗?

如果你告诉我一个方便的方法,在没有帮助的情况下获得相同的结果,或者帮助我改进这门课程,我会很高兴。

问候, FLO

更新

请查看此gist以获取真实的UnitTest。

2 个答案:

答案 0 :(得分:0)

变体1 - 像

这样的流
var sb = new StringBuilder();
const string delimiter = ", ";
var first = true;
Action<object> append = _ => {
    if(null!=_){
        if(!first){ sb.Append(delimiter);}
        first = false;
        sb.Append(_.ToString()); 
    }
}
append(diploma.X);
append(diploma.Y);
...

另一个 - 收集

var data = new List<object>();
data.Add(diploma.X);
data.Add(diploma.Y);
...
var result = string.Join(", ",data.Where(_=>null!=_).Select(_=>_.ToString()));

它的效率不高,但它允许您在数据准备和加入之间添加一些步骤来对收集本身做一些事情。

答案 1 :(得分:0)

我认为您的代码没有任何实际问题。但我更喜欢更简化的语法。它最终可能看起来像这样:

string result = ConcatHelper.Concat(
                    diploma.CodeProfession,
                    new Brace(
                        diploma.CodeDiplomaType,
                        new LabeledItem(label: DiplomaMessage.SrkRegisterId, labelSeparator: " ",
                            valueDecorator: string.Empty, valueToAdd: diploma.SrkRegisterId) 
                        ),
                    diploma.CodeCountry,
                    new Brace(
                        diploma.DateOfIssue?.Year.ToString(CultureInfo.InvariantCulture)
                        ),
                    DiplomaMessage.Recognition
                    ).ToString();
  • 没有文字墙
  • 你不必一遍又一遍地重复Concat
  • 现在有机会混淆牙箍
在这种情况下,

Concat()属于static ConcatHelper Concat(objs object[] params)类型。当然,BraceLabeledItem需要由ConcatHelper处理(if (obj is LabeledItem) { ... })。

关于你的对照:

  • 它应该足够快(10us /呼叫应该没问题)。如果你真的需要它更快,你可能应该使用一个String.Format()
  • Concat可以是静态的。只需在Concat调用中创建ConcatHelper对象即可。
  • 是的,它需要一个清单。有问题吗?
  • 可能是矫枉过正,也可能不是。如果您经常使用这种类型的代码,Utility类可以节省您很多时间并使代码更具可读性。