2016-07-18 3 views
54

В пространстве имен MS.Internal существует класс с именем NamedObject.Что делает {{{0}}} на string.Format?

Он имеет странный блок кода:

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

Мне любопытно, этот комментарий конкретно:

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

Как это 'ленивый'? Что делать, чтобы быть ленивым?


Полный класс от 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. 
+0

Это только присваивает _NAME один раз, если его не было сделано ранее –

+6

Это считается ленивым, потому что строка с фигурной скобкой не создается до первого вызова 'ToString()'. Вы можете читать * ленивый * как * по запросу * здесь. –

+1

@ FrédéricHamidi oh, thats sneaky little hack – Mafii

ответ

64

Вы escape a curly brace with a curly brace, т.е. {{ производит { и }} производит }.

{0} в середине интерпретируется как обычно - то есть ссылка на параметр с нулевым индексом.

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

Конечный результат является значением параметра нуля, заключенное в фигурных скобках:

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

Как это 'ленивый'?

Они называют его ленивым относительно этой альтернативы «нетерпеливый» реализация:

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

Эта реализация добавляет фигурные скобки сразу же, несмотря на то, что не имеет ни малейшего представления о том, что название, заключенное в фигурные скобки собирается необходимо.

+0

Итак, строка не инициализируется до тех пор, пока contidional в if не будет истинным, потому что компилятор не знает, будет ли он запущен? (он обманывает компилятор?) – Mafii

+0

@Mafii Я заменил объяснение «не ленивой» альтернативой. Похоже, они хотят минимизировать влияние создания экземпляров 'NamedObject' в случае, когда никто не планирует называть' ToString'. – dasblinkenlight

+0

О, это круто. Очень хорошее объяснение, легко понять. Я даже об этом не думал. Довольно плохо, что они делают это (учитывая только одну строку) – Mafii

10

{{ и }} просто дайте буквально { и }. (Сбежавшие фигурные скобки)

так, если у вас есть {{{0}}}, а ты по foo, выход будет {foo}

6
var value = "value"; 
String.Format(CultureInfo.InvariantCulture, "{{{0}}}", value); // will output {value} 
+0

Я не вижу разницы с кодом, отправленным OP в любом случае. Если он захочет запустить его, он может просто запустить его. –

15

Как это 'ленивый'? Что делать, чтобы быть ленивым?

Лень исходит от if (_name[0] != '{') перед этим.

Это поле изменяет только поле _name, когда оно запрашивается в первый раз.

И как все уже указывали, String.Format("{{{0}}}", _name); следует читать как "{{ {0} }}" или "\{ {0} \}".Внутренний {0} фактическое поле, чтобы заменить с первым аргументом, внешний {{ и }} являются специальные обозначения для получения одного {}