c# - ¿Qué hace{{{0}}} en string.Format?
lazy-evaluation (4)
¿Cómo es eso ''perezoso''? ¿Qué hace ser perezoso?
La pereza proviene del
if (_name[0] != ''{'')
Antes que él.
Solo cambia el campo
_name
cuando se solicita por primera vez.
Y como todo el mundo ya señaló,
String.Format("{{{0}}}", _name);
debe leerse como
"{{ {0} }}"
o
"/{ {0} /}"
.
El
{0}
interno es el campo real para sustituir con el primer argumento, el
{{
y
}}
externo es una notación especial para obtener un solo
{}
En el espacio de nombres
MS.Internal
, hay una clase llamada
NamedObject
.
Tiene un extraño bloque de código:
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;
}
Tengo curiosidad sobre este comentario específicamente:
// lazily add {} around the name, to avoid allocating a string
// until it''s actually needed
_name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", _name);
¿Cómo es eso ''perezoso''? ¿Qué hace ser perezoso?
Clase completa de la fuente de referencia :
//----------------------------------------------------------------------------
//
// <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.
Escapa de una llave con una llave
, es decir,
{{
produce
{
y
}}
produce
}
.
El
{0}
en el medio se interpreta como de costumbre, es decir, una referencia al parámetro en el índice cero.
{{ {0} }}
^^ ^^^ ^^
| | |
| | +--- Closing curly brace
| +------ Parameter reference
+---------- Opening curly brace
El resultado final es el valor del parámetro cero encerrado entre llaves:
var res = string.Format("{{{0}}}", "hello"); // produces {hello}
¿Cómo es eso ''perezoso''?
Lo llaman perezoso con respecto a esta implementación alternativa "entusiasta":
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;
}
Esta implementación agrega llaves inmediatamente, a pesar de que no tiene idea de que el nombre encerrado entre llaves será necesario.
{{
y
}}
solo te da literal
{
y
}
.
(Frenillos rizados escapados)
entonces, si tienes
{{{0}}}
, y le das a
foo
, el resultado será
{foo}
var value = "value";
String.Format(CultureInfo.InvariantCulture, "{{{0}}}", value); // will output {value}