by Oliver
9. August 2014 12:52
Today, I found this dusty piece of code in our code base: Stone-age version public string GetIframeIds() { var result = new StringBuilder(); var first = true; foreach (var iframe in _iframes) { if (!first) result.Append(','); else first = false; result.Append("'" + iframe.ClientID + "'"); } return result.ToString(); } … and just had to rewrite it to this: Updated version public string GetIframeIds() { return string.Join(",", _iframes.Select(ifr => "'" + ifr.ClientID + "'")); } I couldn't bear but run some micro-performance test on these code snippets since StringBuilder is usually quite fast. I ran each of the snippets with an _iframes length of 30 in a loop of 10.000 iterations and yes, the first version is faster with 215ms vs. 360ms. But then, in production I run that code block only once per request, not 10.000 times as in the test. Spending 21ns or 36ns in that method won't make any significant difference, especially when looking at request execution times of beyond 100ms. Why should you or I care? The second code block is arguably easier to read, quicker to write, and harder to get wrong. Happy coding!
by Oliver
28. June 2011 01:27
Three year old code: 1: protected string CpeBehaviorIds()
2: {
3: var cpeIds = "";
4:
5: var helpItems = GetHelpItems(divGlobal);
6:
7: foreach (var helpItem in helpItems)
8: cpeIds += helpItem.CollapsiblePanelBehaviorID + ',';
9:
10: // remove comma at end
11: if (cpeIds.Length > 0)
12: cpeIds = cpeIds.Remove(cpeIds.Length - 1);
13:
14: return cpeIds;
15: }
16:
17: protected string CpeExpandIds()
18: {
19: var cpeIds = "";
20:
21: var helpItems = GetHelpItems(divGlobal);
22:
23: foreach (var helpItem in helpItems)
24: cpeIds += helpItem.CollapsiblePanelExpandID + ',';
25:
26: // remove comma at end
27: if (cpeIds.Length > 0)
28: cpeIds = cpeIds.Remove(cpeIds.Length - 1);
29:
30: return cpeIds;
31: }
32:
33: protected static List<HelpItem> GetHelpItems(Control control)
34: {
35: var idList = new List<HelpItem>();
36:
37: if (control is HelpItem)
38: idList.Add(control as HelpItem);
39: else
40: foreach (Control child in control.Controls)
41: idList.AddRange(GetHelpItems(child));
42:
43: return idList;
44: }
New code:
1: protected string CpeBehaviorIds()
2: {
3: return divGlobal.Controls<HelpItem>().Select(h => h.CollapsiblePanelBehaviorID).JoinNonEmpty(",");
4: }
5:
6: protected string CpeExpandIds()
7: {
8: return divGlobal.Controls<HelpItem>().Select(h => h.CollapsiblePanelExpandID).JoinNonEmpty(",");
9: }
10:
11: public static string JoinNonEmpty(this IEnumerable<string> values, string separator)
12: {
13: return String.Join(separator, values.Where(s => !string.IsNullOrEmpty(s)).ToArray());
14: }
LINQ – we love you!
Oliver
P.S. Controls<Type>() is another extension method defined like this:
1: /// <summary>
2: /// Returns all controls of the given Type that are found inside this control.
3: /// Searches recursively.
4: /// </summary>
5: public static IEnumerable<T> Controls<T>(this Control control) where T : Control
6: {
7: var controls = control.Controls;
8:
9: if (controls.Count == 0) return new List<T>(0);
10:
11: var newColl = new HashedSet<T>();
12: foreach (Control child in controls)
13: {
14: if (child is T)
15: newColl.Add((T) child);
16:
17: var childColl = child.Controls<T>();
18: foreach (T ctrl in childColl)
19: newColl.Add(ctrl);
20: }
21:
22: return newColl;
23: }