Что {{{0}}} на string.Format?
В пространстве имен MS.Internal
существует класс с именем NamedObject
.
У этого есть странный блок кода:
public override string ToString()
{
if (_name[0] != '{')
{
// lazily add {} around the name, to avoid allocating a string
// until it actually needed
_name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", _name);
}
return _name;
}
Мне интересен этот комментарий:
// lazily add {} around the name, to avoid allocating a string
// until it actually needed
_name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", _name);
Как это "лениво"? Что делать, чтобы быть ленивым?
Полный класс из справочного источника :
//----------------------------------------------------------------------------
//
// <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 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.
Ответы
Ответ 1
Вы избегаете фигурной скобки с фигурной скобкой, т.е. {{
создает {
, а }}
создает }
.
{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;
}
Эта реализация сразу же добавляет фигурные скобки, хотя она и не подозревает, что имя, заключенное в фигурные скобки, будет необходимо.
Ответ 2
Как это "лениво"? Что делать, чтобы быть ленивым?
Лень приходит от if (_name[0] != '{')
до этого.
Он только изменяет поле _name
, когда оно запрашивается в первый раз.
И как все уже указывали, String.Format("{{{0}}}", _name);
следует читать как "{{ {0} }}"
или "\{ {0} \}"
. Внутренний {0}
является фактическим полем для замены с первым аргументом, внешние {{
и }}
являются специальным обозначением для получения одиночного {}
Ответ 3
{{
и }}
просто дают вам буквальные {
и }
. (Скрытые фигурные скобки)
поэтому, если у вас есть {{{0}}}
, и вы дадите foo
, вывод будет {foo}
Ответ 4
var value = "value";
String.Format(CultureInfo.InvariantCulture, "{{{0}}}", value); // will output {value}