2016-07-18 186 views
54

Nel namespace MS.Internal, esiste una classe denominata NamedObject.Cosa fa {{{0}}} su string.Formato fare?

Ha un blocco di strano di codice:

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

Sono curioso di sapere questo commento specifico:

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

Come è che 'pigro'? Cosa fa per essere pigro?


classe completa dal 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

Si assegna solo _name volta se non già fatto –

+6

E 'considerato come pigri perché la la stringa con parentesi graffa non viene generata fino alla prima chiamata a 'ToString()'. Puoi leggere * pigro * come * su richiesta * qui. –

+1

@ FrédéricHamidi oh, questo è un piccolo trucco subdolo – Mafii

risposta

64

È escape a curly brace with a curly brace, vale a dire {{ produce {, e }} produce }.

Il {0} nel mezzo è interpretato come al solito - cioè un riferimento al parametro a zero dell'indice.

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

il risultato finale è il valore del parametro a zero racchiuso tra parentesi graffe:

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

Come è che 'pigro'?

Lo chiamano pigri rispetto a questa alternativa implementazione "ansiosi":

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

Questa implementazione aggiunge parentesi graffe subito, anche se non ha alcuna idea che il nome racchiuso tra parentesi graffe sta andando essere necessario

+0

Quindi la stringa non viene inizializzata fino a quando il contidional nel if è vero perché il compilatore non sa se verrà eseguito? (trucchi il compilatore?) – Mafii

+0

@Mafii Ho sostituito la spiegazione con un'alternativa "non-pigra". Sembra che vogliano minimizzare l'impatto delle istanze di 'NamedObject' nel caso in cui nessuno abbia intenzione di chiamare' ToString'. – dasblinkenlight

+0

Oh, è bello. Ottima spiegazione, facile da capire. Non ci ho nemmeno pensato. Abbastanza male che lo fanno (considerando la sua unica stringa) – Mafii

10

{{ e }} solo dare letteralmente { e }. (parentesi graffe) Escaped

modo, se avete {{{0}}}, e si dà lungo foo, l'uscita sarà {foo}

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

Non riesco comunque a vedere una differenza nel codice pubblicato dall'OP. Se gli piacerebbe eseguirlo, potrebbe semplicemente eseguirlo. –

15

Come è che 'pigro'? Cosa fa per essere pigro?

La pigrizia viene dal if (_name[0] != '{') prima di esso.

Cambia solo il campo _name quando viene richiesto per la prima volta.

E come tutti già sottolineato, String.Format("{{{0}}}", _name); dovrebbe essere letto come "{{ {0} }}" o "\{ {0} \}".L'interno {0} è il campo effettivo di sostituire con il primo argomento, l'esterno {{ e }} sono una notazione speciale per ottenere un'unica {}