55

In the namespace MS.Internal, there is a class named NamedObject.

It has a weird block of code:

public override string ToString()
{
  if (_name[0] != '{')
  {
    // lazily add {} around the name, to avoid allocating a string 
    // until it's actually needed
    _name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", _name);
  }

  return _name;
}

I'm curious about this comment specifically:

    // lazily add {} around the name, to avoid allocating a string 
    // until it's actually needed
    _name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", _name);

How is that 'lazy'? What does it do to be lazy?


Full class from the reference source:

//---------------------------------------------------------------------------- 
//
// <copyright file="NamedObject.cs" company="Microsoft">
//    Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright> 
//
// Description: Placeholder object, with a name that appears in the debugger 
// 
//---------------------------------------------------------------------------

using System;
using System.Globalization;
using MS.Internal.WindowsBase;

namespace MS.Internal
{
  /// <summary> 
  /// An instance of this class can be used wherever you might otherwise use
  /// "new Object()".  The name will show up in the debugger, instead of 
  /// merely "{object}"
  /// </summary>
  [FriendAccessAllowed]   // Built into Base, also used by Framework.
  internal class NamedObject
  {
    public NamedObject(string name)
    {
      if (String.IsNullOrEmpty(name))
        throw new ArgumentNullException(name);

      _name = name;
    }

    public override string ToString()
    {
      if (_name[0] != '{')
      {
        // lazily add {} around the name, to avoid allocating a string 
        // until it's actually needed
        _name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", _name);
      }

      return _name;
    }

    string _name;
  }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Mafii
  • 7,227
  • 1
  • 35
  • 55
  • It only assigns to _name once if its not already done so – Alex K. Jul 18 '16 at 12:36
  • 6
    It is considered as lazy because the curly-bracketed string is not generated until the first call to `ToString()`. You can read *lazy* as *on-demand* here. – Frédéric Hamidi Jul 18 '16 at 12:37
  • 1
    @FrédéricHamidi oh, thats a sneaky little hack – Mafii Jul 18 '16 at 12:39
  • 3
    @Mafii I know the term "lazy" sound pejorative, but lazy evaluation is not a hack in any way. In fact, whole languages are built around that paradigm. In this case, the implementer of `NamedObject` used encapsulation to guarantee that the object behaves as one would expect, while saving some performance in certain cases. – KABoissonneault Jul 18 '16 at 13:11
  • @KABoissonneault it was in no way meant pejoratively. I love how amazing lazy evaluation is - but it confuses me more often than not to think of what happens when and why, especially in this case. It is implicitely lazy, and more of a workaround. Its a fine piece of code imo, because it is commendet :) – Mafii Jul 18 '16 at 13:28

4 Answers4

66

You escape a curly brace with a curly brace, i.e. {{ produces {, and }} produces }.

The {0} in the middle is interpreted as usual - i.e. a reference to parameter at index zero.

{{ {0} }}
^^ ^^^ ^^
|   |  |
|   |  +--- Closing curly brace
|   +------ Parameter reference
+---------- Opening curly brace

The end result is the value of parameter zero enclosed in curly braces:

var res = string.Format("{{{0}}}", "hello"); // produces {hello}

How is that 'lazy'?

They call it lazy with respect to this alternative "eager" implementation:

internal class NamedObject {
    public NamedObject(string name) {
        if (String.IsNullOrEmpty(name))
            throw new ArgumentNullException(name);
        if (name[0] != '{') {
            // eagerly add {} around the name
            _name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", name);
        } else {
            _name = name;
        }
    }
    public override string ToString() {
        return _name;
    }
    string _name;
}

This implementation adds curly braces right away, even though it has no idea that the name enclosed in curly braces is going to be needed.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • So the string is not being initialized until the contidional in the if is true because the compiler doesnt know if it will be run? (it tricks the compiler?) – Mafii Jul 18 '16 at 12:47
  • @Mafii I replaced the explanation with a "non-lazy" alternative. It looks like they want to minimize the impact of making `NamedObject` instances in case when nobody is planning to call `ToString`. – Sergey Kalinichenko Jul 18 '16 at 13:04
  • Oh, that's cool. Very good explanation, easy to understand. I didn't even think about that. Pretty badass that they do that (considering its only one string) – Mafii Jul 18 '16 at 13:07
15

How is that 'lazy'? What does it do to be lazy?

The laziness comes from the if (_name[0] != '{') before it.

It only changes the _name field when it is requested for the first time.

And like everybody already pointed out, String.Format("{{{0}}}", _name); should be read as "{{ {0} }}" or "\{ {0} \}". The inner {0} is the actual field to substitute with the first argument, the outer {{ and }} are a special notation to get single {}

H H
  • 263,252
  • 30
  • 330
  • 514
10

{{ and }} just give you literal { and }. (Escaped curly braces)

so, if you have {{{0}}}, and you give along foo, the output will be {foo}

nl-x
  • 11,762
  • 7
  • 33
  • 61
6
var value = "value";
String.Format(CultureInfo.InvariantCulture, "{{{0}}}", value); // will output {value}
Backs
  • 24,430
  • 5
  • 58
  • 85