C # String.format metodo di estensione

6

Con l'aggiunta dei metodi di estensione a C # ne abbiamo visti molti nel nostro gruppo. Un dibattito ruota attorno ai metodi di estensione come questo:

public static class StringExt
{
    /// <summary>
    /// Shortcut for string.Format.
    /// </summary>
    /// <param name="str"></param>
    /// <param name="args"></param>
    /// <returns></returns>
    public static string Format(this string str, params object[] args)
    {
        if (str == null) return null;
        return string.Format(str, args);
    }
}

Questo metodo di estensione rompe qualsiasi best practice di programmazione che puoi nominare? Lo useresti comunque, se non perché? Se avessi rinominato la funzione in "F" ma avessi lasciato i commenti xml sarebbe stato epico fallire o solo un meraviglioso risparmio di battute?

    
posta P. Roe 22.06.2011 - 23:10
fonte

4 risposte

14

Sembra piuttosto inutile per me.

È più codice che devi mantenere - e tra un anno nessuno ricorderà i dibattiti che hai avuto e metà del tuo codice userà string.Format l'altra metà userà questo metodo.

Ti distrae anche dal reale compito di sviluppare software che risolva i problemi reali .

Probabilmente hai sprecato più soldi avendo queste discussioni che sarebbe costato all'azienda acquistare le licenze ReSharper per tutti.

    
risposta data 22.06.2011 - 23:45
fonte
6

FxCop si lamenta quando usa String.Format(...) senza IFormatProvider . Quindi ha senso avere metodi di estensione come% o FormatInvariant(...) o FormatLocal(...) perché salva i chiamanti dall'essere costretti a giocherellare con lo spazio dei nomi System.Globalization molte volte.

    
risposta data 23.06.2011 - 02:27
fonte
2

I metodi di estensione hanno uno svantaggio principale. Supponiamo che tu abbia un metodo di estensione come questo:

public static string ToRomanNumeral(this int number)
{
    // whatever whatever whatever
}

Lo fai in .NET 4. Poi in. NET 5 Microsoft risponde allo sfogo dell'amore romano tra gli sviluppatori aggiungendo un metodo a int :

public string ToRomanNumeral()
{
    // whatever whatever whatever
}

Quando ricompilate il codice contro .NET 5, all'improvviso e senza alcun errore o avvertimento, il codice numerico di Microsoft verrà eseguito al posto del vostro.

Questo è un esempio sciocco, ma può accadere in ogni caso in cui si utilizza un metodo di estensione, quindi in seguito aggiungere lo stesso metodo alla classe utilizzata dal metodo di estensione come parametro. In caso di conflitto, i metodi su una classe hanno sempre la precedenza sui metodi di estensione e non c'è assolutamente alcuna notifica del conflitto.

Quindi ... solo qualcosa da tenere a mente prima di diventare pazzo per l'estensione dei metodi.

    
risposta data 23.06.2011 - 01:53
fonte
1

Non mi piace il fatto che String.Format usi la cultura corrente . Ciò significa che l'output dipende dal sistema dell'utente. Ad esempio, se codice questo rapidamente senza pensare alle culture:

var now = DateTime.Now;
string json = String.Format("{{ 'Date': \"{0}\" }}", now);

Posso verificarlo e funziona perfettamente sul mio sistema.

{ 'Date': "9-11-2013 13:37:00" }

E dopo un po 'mi dimentico di questo piccolo frammento di codice e finisce nel mio prodotto. Poi un utente in Arabia Saudita usa il programma e tutto fallisce da quando ha prodotto:

{ 'Date': "06/01/35 01:37:00 ?" }

Per prevenire tali bug voglio String.Format usare la cultura invariante di default, e se voglio usare una cultura specifica posso specificare esplicitamente la cultura. Ciò impedirà tutti questi bug.

In C # 6 è possibile utilizzare interpolazione stringa per eseguire la formattazione delle stringhe. Tuttavia è ancora specifico per la cultura.

string json = $"{{ 'Date': \"{now}\" }}";

Fortunatamente esiste un modo per renderlo invariante alla cultura. Importa in modo statico lo spazio dei nomi System.FormattableString e utilizza il metodo Invariant , in questo modo:

using static System.FormattableString;

string json = Invariant($"{{ 'Date': \"{now}\" }}");

Per C # 5 e precedenti, mi sono scritto un insieme di metodi di estensione per farlo per me. Nel processo, fornisce anche una sintassi molto più bella.

public static string FormatInvariant(this string format, params object[] args)
{
    if (format == null) throw new NullReferenceException("format");
    if (args == null) throw new NullReferenceException("args");

    return FormatWith(format, CultureInfo.InvariantCulture, args);
}

public static string FormatCurrentCulture(this string format, params object[] args)
{
    if (format == null) throw new NullReferenceException("format");
    if (args == null) throw new NullReferenceException("args");

    return FormatWith(format, CultureInfo.CurrentCulture, args);
}

public static string FormatWith(this string format, IFormatProvider provider, params object[] args)
{
    if (format == null) throw new NullReferenceException("format");
    if (provider == null) throw new NullReferenceException("provider");
    if (args == null) throw new NullReferenceException("args");

    return String.Format(provider, format, args);
}

(Ottieni il codice sorgente completo con commenti e Contratti di codice.)

Esempio di utilizzo:

string json = "{{ 'Date': \"{0}\" }}".FormatInvariant(now);
    
risposta data 18.11.2013 - 19:06
fonte

Leggi altre domande sui tag