Can maximum number of characters be defined in C# format strings like in C printf?

不羁岁月 提交于 2019-12-01 02:41:37

What you want is not "natively" supported by C# string formatting, as the String.ToString methods of the string object just return the string itself.

When you call

string.Format("{0:xxx}",someobject);

if someobject implements the IFormattable interface, the overload ToString(string format,IFormatProvider formatProvider) method gets called, with "xxx" as format parameter.

So, at most, this is not a flaw in the design of .NET string formatting, but just a lack of functionality in the string class.

If you really need this, you can use any of the suggested workarounds, or create your own class implementing IFormattable interface.

This is not an answer on how to use string.format, but another way of shortening a string using extension methods. This way enables you to add the max length to the string directly, even without string.format.

public static class ExtensionMethods
{
    /// <summary>
    ///  Shortens string to Max length
    /// </summary>
    /// <param name="input">String to shortent</param>
    /// <returns>shortened string</returns>
    public static string MaxLength(this string input, int length)
    {
        if (input == null) return null;
        return input.Substring(0, Math.Min(length, input.Length));
    }
}

sample usage:

string Test = "1234567890";
string.Format("Shortened String = {0}", Test.MaxLength(5));
string.Format("Shortened String = {0}", Test.MaxLength(50));

Output: 
Shortened String = 12345
Shortened String = 1234567890

I've written a custom formatter that implements an "L" format specifier used to set maximum width. This is useful when we need to control the size of our formatted output say when destined for a database column or Dynamics CRM field.

public class StringFormatEx : IFormatProvider, ICustomFormatter
{
    /// <summary>
    /// ICustomFormatter member
    /// </summary>
    public string Format(string format, object argument, IFormatProvider formatProvider)
    {
        #region func-y town
        Func<string, object, string> handleOtherFormats = (f, a) => 
        {
            var result = String.Empty;
            if (a is IFormattable) { result = ((IFormattable)a).ToString(f, CultureInfo.CurrentCulture); }
            else if (a != null) { result = a.ToString(); }
            return result;
        };
        #endregion

        //reality check.
        if (format == null || argument == null) { return argument as string; }

        //perform default formatting if arg is not a string.
        if (argument.GetType() != typeof(string)) { return handleOtherFormats(format, argument); }

        //get the format specifier.
        var specifier = format.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture);

        //perform extended formatting based on format specifier.
        switch(specifier)
        {
            case "L": 
                return LengthFormatter(format, argument);
            default:
                return handleOtherFormats(format, argument);
        }
    }

    /// <summary>
    /// IFormatProvider member
    /// </summary>
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
            return this;
        else
            return null;
    }

    /// <summary>
    /// Custom length formatter.
    /// </summary>
    private string LengthFormatter(string format, object argument)
    {
        //specifier requires length number.
        if (format.Length == 1)
        {
            throw new FormatException(String.Format("The format of '{0}' is invalid; length is in the form of Ln where n is the maximum length of the resultant string.", format));
        }

        //get the length from the format string.
        int length = int.MaxValue;
        int.TryParse(format.Substring(1, format.Length - 1), out length);

        //returned the argument with length applied.
        return argument.ToString().Substring(0, length);
    }
}

Usage is

var result = String.Format(
    new StringFormatEx(),
    "{0:L4} {1:L7}",
    "Stack",
    "Overflow");

Assert.AreEqual("Stac Overflo", result);

Can't you just apply length arguments using the parameter rather than the format?

String.Format("->{0}<-", toFormat.PadRight(10)); // ->Hello <-

Or write your own formatter to allow you to do this?

Why not just use Substr to limit the length of your string?

String s = "abcdefghijklmnopqrstuvwxyz";
String.Format("Character limited: {0}", s.Substr(0, 10));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!