2013-07-12 21 views
6

ho:String.Format metodo di estensione

public static string Format(this string text, params object[] args) 
{ 
    return string.Format(text, args); 
} 

così posso fare:

"blablabla {0}".Format(variable1); 

Si tratta di un buono/cattivo? Può diventare ancora più breve? Voglio avere stringhe costruire senza soluzione di continuità, come scrivere il testo, senza preoccuparsi prima o dopo di parametri e roba:

// bad 
return "date: " + DateTime.Now.ToString("dd.MM.yyyy") + "\ntime: " + DateTime.Now.ToString("mm:HH:ss") + "\nuser: " + _user + " (" + _status + ")"; 

// better, but you have to deal with order of {0}...{n} and order of parameters 
return string.Format("date: {0}\ntime: {1}\user: {2} ({3})", ...); 

// ideal 
return "date: {DateTime.Now{dd:MM:yyyy}}\ntime: {...}\nuser: {_user} ({_status})"; 
+0

Trovo che l'uscita prevista di questa idea sia molto confusa. – Steve

+0

"È un buono/cattivo?": Stai chiedendo opinioni che sono fuori tema qui su [SO]. – Richard

+0

@Richard, è solo una delle tante domande che ho chiesto = P – Sinatr

risposta

3

Bene, una brutta cosa c'è che da solo avendo un singolo metodo params object[] si forza un extra allocazione di array per chiamata.

Si può notare che string.Format ha un intervallo di sovraccarichi per il basso numero di argomenti (questi sono molto comunemente utilizzati) - Suggerirei di duplicarli.

lo scenario "ideale" potrebbe essere fatto da ri-scrittura del metodo string.Format, ma avresti bisogno di passare nei valori, vale a dire

return "date: {date}\ntime: {...}\nuser: {_user} ({_status})" 
    .Format(new { date = DateTime.Now, _user, _status }); 

(e utilizzando il proprio metodo personalizzato Format, o one like this), ma nota che forza una nuova istanza di oggetto per chiamata.

In realtà, a un certo punto il compilatore mono aveva un flag sperimentale per abilitarlo direttamente. Non so se è mantenuto.

+0

Idea interessante di mettere in una stringa i miei identificatori e quindi sostituirli con i valori che mi servono. Grazie! – Sinatr

1

Dipende se si sta codificando da solo o si dispone di una squadra. In una squadra questa è una pessima idea dato che tutti dovranno imparare questo metodo.

Un altro problema è in formato con arg sulle stringhe che contiene accidentalmente parentesi con indice errato come {1} invece di {2}. In questo modo solo una brutta stringa rovinerà l'intera applicazione. Ho usato qualcosa di simile per la mia registrazione e ho dovuto usare try-catch per FormatExceptions.

+0

Se metto try/catch all'interno del metodo di estensione e fornisco un altro modo per segnalare errori di programmazione (ad esempio aggiungendo alla fine della stringa qualcosa come "omg, parametro {10} mancante"), il metodo di estensione è un grande vantaggio (quindi non devo duplicare try/catch per ogni formato). E ogni squadra ha il proprio "styling" o soluzioni comuni per casi comuni. Se dovessi essere confuso dalla sintassi, puoi vedere rapidamente cosa si trova direttamente in Visual Studio. Quindi non vedo un grosso problema qui. – Sinatr

2

Uso anche un metodo di estensione simile, e mi piace, specificando anche le informazioni sulla cultura nel metodo di estensione corretto per il sistema nel mio caso.

public static string Format(this string formatTemplate, params object[] args) 
{ 
    return string.Format(SysSettings.CultureInfo, formatTemplate, args); 
} 

Usi:

return "date: {0:dd.MM.yyyy}\ntime: {1:mm:HH:ss}\nuser: {2} ({3})".Format(DateTime.Now, DateTime.Now, _user, _status); 
+0

Fantastica idea con cultura, grazie. Sono stato spinto a usare la coltura neutra per il punto decimale quando si usa 'double' o' float' e mai quando si usa 'int', e con il metodo di estensione posso uccidere tutto in 1 ripresa! – Sinatr

+0

Questo darà un errore di compilazione se si tenta di passare 2 argomenti con il primo essere una stringa. '" {0} - {1} ". Formato (" esempio ", 1);' come corrisponderà alla firma statica String.Format invece dell'estensione – GP89

3

E 'non corrispondono del tutto il vostro ideale, ma qualcosa di simile potrebbe funzionare per voi:

public static class Extensions 
{ 
    public static string Format(this object data, string format) 
    { 
     var values = new List<object>(); 
     var type = data.GetType(); 
     format = Regex.Replace(format, @"(^|[^{])\{([^{}]+)\}([^}]|$)", x => 
     { 
      var keyValues = Regex.Split(x.Groups[2].Value, 
             "^([^:]+):?(.*)$") 
            .Where(y => !string.IsNullOrEmpty(y)); 

      var key = keyValues.ElementAt(0); 
      var valueFormat = keyValues.Count() > 1 ? 
           ":" + keyValues.ElementAt(1) : 
           string.Empty; 


      var value = GetValue(key, data, type); 

      values.Add(value); 
      return string.Format("{0}{{{1}{2}}}{3}", 
            x.Groups[1].Value, 
            values.Count - 1, 
            valueFormat, 
            x.Groups[3].Value); 
     }); 


     return string.Format(format, values.ToArray()); 
    } 

    private static object GetValue(string name, object data, Type type) 
    { 
     var info = type.GetProperty(name); 
     return info.GetValue(data, new object[0]); 
    } 
} 

Questo dovrebbe permettere di fare questo tipo di formattazione su qualsiasi oggetto:

new {Person = "Me", Location = "On holiday"} 
    .Format("{Person} is currently {Location}"); 

Ti consentirà anche di aggiungere un po 'di formattazione:

new {Person = "Me", Until = new DateTime(2013,8,1)} 
    .Format("{Person} is away until {Until:yyyy-MM-dd}); 

Come è questo per te? Sono sicuro che il codice potrebbe essere migliorato in termini di efficienza, ma funziona!

+0

L'idea è di generare array di args * prima * chiamando Format e mettere * nome * della variabile nella stringa di formato invece di '{0}', il che è fantastico, penso. Grazie. – Sinatr

+0

Sì, tranne che il metodo di estensione Format viene chiamato su un oggetto anziché su un array. Nei miei esempi questa è un'istanza di un tipo anonimo, ma in realtà potrebbe essere qualsiasi oggetto, come un oggetto di dominio: (ad es .: var person = new Person ("Aaron", "Janes"); person.Format ("{ LastName}, {FirstName} ");) –

+0

Attualmente il metodo di estensione I knocked up non supporta le proprietà indicizzate in modo tale: new {Items = new [] {" One "," Two "}} .Format (" First item: { articoli [0]} "); non funzionerà. Tuttavia dovrebbe essere relativamente banale aggiungere il supporto per gli indicizzatori. –