我想截断一个字符串,使其长度不超过给定值。我正在向数据库表写入数据,并希望确保写入的值满足列数据类型的约束。

例如,如果我能写以下内容,那就太好了:

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

不幸的是,这会引发异常,因为maxLength通常超过字符串值的边界。当然,我可以写一个像下面这样的函数,但我希望这样的东西已经存在了。

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

执行此任务的难以捉摸的API在哪里?有吗?


当前回答

c# 6的Null传播运算符的类似变体

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

请注意,我们实际上是在检查value是否为null两次。

其他回答

我知道这里已经有大量的答案,但这是一个我已经去了,它处理空字符串和传递的长度为负的情况:

public static string Truncate(this string s, int length)
{
    return string.IsNullOrEmpty(s) || s.Length <= length ? s 
        : length <= 0 ? string.Empty 
        : s.Substring(0, length);
}

或者,您可以使用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));
    }
}

您可以创建一个Truncate扩展方法,它将最大长度与字符串长度进行比较,并在需要时调用Substring。

如果您想要与Substring类似的空处理行为,则不要包含空检查。这样,就像str. substring(0,10)在str为空时抛出NullReferenceException一样,str. truncate(10)也会抛出NullReferenceException。

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

        return new string(value.Take(maxLength).ToArray());// use LINQ and be happy
    }

所有其他答案都没有考虑到Span的性能,它比。net中字符串类型的Substring的性能更好

如果你还不知道有一个版本的系统。内存(为以下情况提供了Span, ReadOnlySpan, Memory和ReadOnlyMemory:

这样的简单实现可以如下所示:

public static string Truncate(this string value, int maxLength)
{
    if (!string.IsNullOrEmpty(value) && value.Length > maxLength)
    {
        return value.AsSpan(0, maxLength).ToString(); /* Note the use of AsSpan instead of Substring. */
    }

    return value;
}

该方法理论上可以返回Span<char>,以避免使用Span<T>的ToString()成员分配新字符串。

The BCL itself internally uses Span's, ReadOnlySpan's, Memory's, and ReadOnlyMemory's where possible to avoid issues and to help optimize the code, especially when you compile arrays that are known at compile time and so using an property that returns that new'd up array as an ReadOnlySpan<byte> actually optimizes the code at runtime as then the JIT would not call memcpy on the data and instead uses it since it just returns a Span and as such is a window to the data that is already allocated ahead of time resulting in:

更少的分配。 更少的分配时间。 使代码总体上更快地使用。