Ecco due possibili soluzioni:un LINQ one-liner che elabora l'input da sinistra a destra e un tradizionale for
-loop che elabora l'input da destra a sinistra. Quale direzione di elaborazione è più veloce dipende dalla lunghezza della stringa, dalla lunghezza dei byte consentita e dal numero e dalla distribuzione dei caratteri multibyte ed è difficile dare un suggerimento generale. La decisione tra LINQ e codice tradizionale è probabilmente una questione di gusti (o forse di velocità).
Se la velocità conta, si potrebbe pensare di accumulare semplicemente la lunghezza in byte di ogni carattere fino a raggiungere la lunghezza massima invece di calcolare la lunghezza in byte dell'intera stringa in ogni iterazione. Ma non sono sicuro che funzionerà perché non conosco abbastanza bene la codifica UTF-8. In teoria potrei immaginare che la lunghezza in byte di una stringa non sia uguale alla somma delle lunghezze in byte di tutti i caratteri.
public static String LimitByteLength(String input, Int32 maxLength)
{
return new String(input
.TakeWhile((c, i) =>
Encoding.UTF8.GetByteCount(input.Substring(0, i + 1)) <= maxLength)
.ToArray());
}
public static String LimitByteLength2(String input, Int32 maxLength)
{
for (Int32 i = input.Length - 1; i >= 0; i--)
{
if (Encoding.UTF8.GetByteCount(input.Substring(0, i + 1)) <= maxLength)
{
return input.Substring(0, i + 1);
}
}
return String.Empty;
}