web-dev-qa-db-fra.com

Existe-t-il un "String.Format" pouvant accepter des paramètres d'entrée nommés au lieu d'espaces réservés d'index?

C'est ce que je sais

str = String.Format("Her name is {0} and she's {1} years old", "Lisa", "10");

Mais je veux quelque chose comme

str = String("Her name is @name and she's @age years old");
str.addParameter(@name, "Lisa");
str.addParameter(@age, 10);
86

En C # 6, vous pouvez utiliser interpolation de chaîne :

string name = "Lisa";
int age = 20;
string str = $"Her name is {name} and she's {age} years old";

Comme Doug Clutter mentionné dans son commentaire , l'interpolation de chaîne prend également en charge chaîne de format . Il est possible de changer le format en le spécifiant après deux points. L'exemple suivant générera un nombre avec une virgule et 2 décimales:

var str = $"Your account balance is {balance:N2}"

Comme Bas mentionné dans sa réponse , l'interpolation de chaîne ne prend pas en charge la chaîne de modèle. En fait, il n’a pas de support intégré pour cela. Heureusement, il existe dans certaines grandes bibliothèques.


SmartFormat.NET prend en charge, par exemple, l'espace réservé nommé:

Smart.Format("{Name} from {Address.City}, {Address.State}", user)

// The user object should at least be like that 

public class User
{
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public string City { get; set; }
    public string State { get; set; }
}

Il est disponible sur NuGet .


Moustache est également une excellente solution. Bas a bien décrit ses avantages dans sa réponse .

136
Fabien PERRONNET

Si vous êtes en mesure d'affecter une variable locale contenant les données que vous utilisez pour remplacer les paramètres du modèle, vous pouvez utiliser le C # 6.0 fonction d'interpolation de chaîne .

Le principe de base est que vous pouvez effectuer une logique de remplacement de chaîne assez avancée en fonction des données d'entrée.

Exemple simple:

string name = "John";
string message = $"Hello, my name is {name}."

Exemple complexe:

List<string> strings = ...
string summary = $"There are {strings.Count} strings. " 
  + $"The average length is {strings.Select(s => s.Length).Average()}"

Désavantages:

  • Aucune prise en charge des modèles dynamiques (par exemple, à partir d'un fichier de ressources)

Avantages (majeurs):

  • Il applique les contrôles de temps de compilation sur le remplacement de votre modèle.

Une belle solution open source qui a presque la même syntaxe, est Moustache . Il a deux implémentations C # disponibles de ce que j'ai pu trouver - moustache-sharp et Nustache .

J'ai travaillé avec mustache-sharp et a constaté qu'il n'a pas la même puissance que l'interpolation de chaîne, mais qu'il s'en rapproche. Par exemple. vous pouvez faire ce qui suit (volé de sa page github).

Hello, {{Customer.Name}}
{{#newline}}
{{#newline}}
{{#with Order}}
{{#if LineItems}}
Here is a summary of your previous order:
{{#newline}}
{{#newline}}
{{#each LineItems}}
    {{ProductName}}: {{UnitPrice:C}} x {{Quantity}}
    {{#newline}}
{{/each}}
{{#newline}}
Your total was {{Total:C}}.
{{#else}}
You do not have any recent purchases.
{{/if}}
{{/with}}
29
Bas

Si vous n'avez pas de C # 6 disponible dans votre projet, vous pouvez utiliser .Aggregate () de Linq:

    var str = "Her name is @name and she's @age years old";

    var parameters = new Dictionary<string, object>();
    parameters.Add("@name", "Lisa");
    parameters.Add("@age", 10);

    str = parameters.Aggregate(str, (current, parameter)=> current.Replace(parameter.Key, parameter.Value.ToString()));

Si vous voulez quelque chose qui corresponde à la syntaxe spécifique dans la question, vous pouvez créer une classe assez simple basée sur Aggregate:

public class StringFormatter{

    public string Str {get;set;}

    public Dictionary<string, object> Parameters {get;set;}

    public StringFormatter(string p_str){
        Str = p_str;
        Parameters = new Dictionary<string, object>();
    }

    public void Add(string key, object val){
        Parameters.Add(key, val);
    }

    public override string ToString(){
        return Parameters.Aggregate(Str, (current, parameter)=> current.Replace(parameter.Key, parameter.Value.ToString()));
    }

}

Utilisable comme:

var str = new StringFormatter("Her name is @name and she's @age years old");
str.Add("@name", "Lisa");
str.Add("@age", 10);

Console.WriteLine(str);

Notez qu'il s'agit d'un code épuré, conçu pour être plus compréhensible que la performance.

25
Chakrava

Avec C # 6, vous pouvez utiliser String Interpolation pour ajouter directement des variables dans une chaîne.

Par exemple:

string name = "List";
int age = 10;

var str = $"Her name is {name} and she's {age} years old";

Notez, l'utilisation du signe dollar ($) avant le format de chaîne.

18
Steve

Alors pourquoi ne pas simplement remplacer?

string str = "Her name is @name and she's @age years old";
str = str.Replace("@name", "Lisa");
str = str.Replace("@age", "10");
14
Artem

Il n’existe pas de méthode intégrée pour le faire, mais vous pouvez écrire une classe qui le fera pour vous.
Quelque chose comme ça peut vous aider à démarrer:

public class ParameterizedString
{
    private string _BaseString;
    private Dictionary<string, string> _Parameters;

    public ParameterizedString(string baseString)
    {
        _BaseString = baseString;
        _Parameters = new Dictionary<string, string>();
    }

    public bool AddParameter(string name, string value)
    {
        if(_Parameters.ContainsKey(name))
        {
            return false;
        }
        _Parameters.Add(name, value);
        return true;
    }

    public override string ToString()
    {
        var sb = new StringBuilder(_BaseString);
        foreach (var key in _Parameters.Keys)
        {
            sb.Replace(key, _Parameters[key]);
        }
        return sb.ToString();
    }
}

Notez que cet exemple ne force aucune convention de nom de paramètre. Cela signifie que vous devez être très prudent dans le choix de vos noms de paramètres, sinon vous risquez de remplacer des parties de la chaîne que vous n'aviez pas l'intention de faire.

7
Zohar Peled

l’interpolation de chaîne est une bonne solution, mais elle nécessite du C # 6.

Dans ce cas, j'utilise StringBuilder

var sb = new StringBuilder();

sb.AppendFormat("Her name is {0} ", "Lisa");
sb.AppendFormat("and she's {0} years old", "10");
// You can add more lines

string result = sb.ToString();
5
ehh

Vous pouvez également utiliser des expressions avec l'interpolation de chaîne de C # 6:

string name = "Lisa";
int age = 20;
string str = $"Her name is {name} and she's {age} year{(age == 1 ? "" : "s")} old";
3
Sean McLarty
    string name = "Lisa";
    int age = 20;
    string str = $"Her name is {name} and she's {age} years old";

C'est ce qu'on appelle chaîne interpolée , qui est essentiellement une chaîne de modèle contenant des expressions à l'intérieur de celle-ci.

2
Matt.Mull