508 votes

Comment tronquer une chaîne de caractères .NET ?

Je voudrais tronquer une chaîne de caractères de sorte que sa longueur ne dépasse pas une valeur donnée. J'écris dans une table de base de données et je veux m'assurer que les valeurs que j'écris respectent la contrainte du type de données de la colonne.

Par exemple, ce serait bien si je pouvais écrire ce qui suit :

string NormalizeLength(string value, int maxLength)
{
    return value.Substring(0, maxLength);
}

Malheureusement, cela soulève une exception car maxLength dépasse généralement les limites de la chaîne value . Bien sûr, je pourrais écrire une fonction comme la suivante, mais j'espérais que quelque chose de ce genre existe déjà.

string NormalizeLength(string value, int maxLength)
{
    return value.Length <= maxLength ? value : value.Substring(0, maxLength);
} 

Où se trouve l'insaisissable API qui effectue cette tâche ? Y en a-t-il une ?

29 votes

Pour mémoire, les chaînes de caractères sont immuables ; vous ne pouvez pas les tronquer ; vous pouvez seulement en renvoyer une copie tronquée. C'est un peu délicat, je sais.

3 votes

@John Weldon : C'est probablement la raison pour laquelle la fonction membre n'existe pas -- elle ne suit pas la sémantique du type de données. A propos, StringBuilder vous permet de tronquer en raccourcissant la longueur, mais vous devez toujours effectuer la vérification de la longueur pour éviter d'élargir la chaîne.

1 votes

Quelle que soit la solution retenue, veillez à ajouter une vérification de l'absence de chaîne nulle avant d'appeler Substring ou d'accéder à la propriété Length.

802voto

LBushkin Points 60611

Il n'y a pas de Truncate() sur une chaîne de caractères, malheureusement. Vous devez écrire ce genre de logique vous-même. Ce que vous pouvez faire, cependant, c'est l'intégrer dans une méthode d'extension afin de ne pas avoir à la dupliquer partout :

public static class StringExt
{
    public static string Truncate(this string value, int maxLength)
    {
        if (string.IsNullOrEmpty(value)) return value;
        return value.Length <= maxLength ? value : value.Substring(0, maxLength); 
    }
}

Maintenant, nous pouvons écrire :

var someString = "...";
someString = someString.Truncate(2);
2021-09-17 Alternative avec les types de référence suffixe et nullable c#8.
public static class StringExt
{
    public static string? Truncate(this string? value, int maxLength, string truncationSuffix = "…")
    {
        return value?.Length > maxLength
            ? value.Substring(0, maxLength) + truncationSuffix
            : value;
    }
}

Pour écrire :

"abc".Truncate(2);          // "ab…"
"abc".Truncate(3);          // "abc"
((string)null).Truncate(3); // null

8 votes

Excellente solution, mais n'oubliez pas que cela ne fonctionne qu'avec NET 3.5 et plus. Ne l'essayez pas en NET2.0.

8 votes

Tant que vous êtes dans VS 2008, et probablement VS 2010, vous pouvez toujours le faire même si vous ciblez .Net 2.0. danielmoth.com/Blog/

4 votes

Cela échouera si maxLength est une valeur négative.

172voto

CaffGeek Points 10925

Ou au lieu de l'opérateur ternaire, vous pourriez utiliser Math.min

public static class StringExt
{
    public static string Truncate( this string value, int maxLength )
    {
        if (string.IsNullOrEmpty(value)) { return value; }

        return value.Substring(0, Math.Min(value.Length, maxLength));
    }
}

11 votes

Intelligent ! Et l'expression suivante est optimisée pour retourner une référence à la chaîne originale : value.Substring(0, value.Length) .

5 votes

Malheureusement, elle n'est pas optimisée pour les cas où value.Length est inférieur à MaxLength, ce qui peut être un cas courant dans certaines données. De plus, la propriété Length sur une chaîne de caractères doit être mise en majuscule.

1 votes

Cela échouera si maxLength est une valeur négative.

50voto

jpierson Points 3871

Je me suis dit que j'allais présenter mon implémentation car je pense qu'elle couvre tous les cas qui ont été abordés par les autres et qu'elle le fait de manière concise tout en restant lisible.

public static string Truncate(this string value, int maxLength)
{
    if (!string.IsNullOrEmpty(value) && value.Length > maxLength)
    {
        return value.Substring(0, maxLength);
    }

    return value;
}

Cette solution s'appuie principalement sur le La solution de Ray et ouvre la méthode à l'utilisation en tant que méthode d'extension en utilisant l'option este mot-clé tout comme LBushkin fait dans sa solution.

0 votes

Cela échouera si maxLength est une valeur négative.

16 votes

@Bernard - Je recommanderais de ne pas passer une valeur négative pour l'argument maxLength car c'est une valeur inattendue. La méthode Substring adopte la même approche, il n'y a donc aucune raison d'améliorer l'exception qu'elle lève.

0 votes

Je ne pense pas que la vérification de IsNullOrEmpty soit nécessaire ? (1) Si la valeur est nulle, il ne devrait pas être possible d'appeler cette méthode d'extension sur elle. (2) Si value est une chaîne vide, la vérification de value.Length > maxLength échouera.

49voto

Dylan Nicholson Points 148

Dans .NET 4.0, vous pouvez utiliser la fonction Take méthode :

string.Concat(myString.Take(maxLength));

Non testé pour l'efficacité !

32voto

tames Points 176

Vous pourriez utiliser LINQ... il élimine le besoin de vérifier la longueur des chaînes. Certes, ce n'est peut-être pas le plus efficace, mais c'est amusant.

string result = string.Join("", value.Take(maxLength)); // .NET 4 Join

ou

string result = new string(value.Take(maxLength).ToArray());

4 votes

Pourquoi n'est-ce pas la réponse acceptée ? Qu'est-ce qui est le plus simple, écrire votre propre méthode d'extension que vous devez maintenir/documenter, ou utiliser quelque chose d'INTEGRE comme .Take ?

11 votes

@mmcrae Linq est peut-être plus direct, mais il est aussi beaucoup plus lent. Mon benchmark indique ~400ms pour Linq et seulement ~24ms pour Substring pour 1 million d'itérations.

2 votes

Cette solution ne devrait jamais être utilisée. Comme indiqué dans les deux commentaires ci-dessus, il y a toujours une allocation de mémoire, même lorsque la chaîne existante n'est pas plus grande que la longueur maximale. C'est aussi très lent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X