Can maximum number of characters be defined in C# format strings like in C printf?
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);