11

String formatting in C#;

Can I use it? Yes.

Can I implement custom formatting? No.

I need to write something where I can pass a set of custom formatting options to string.Format, which will have some effect on the particular item.

at the moment I have something like this:

string.Format("{0}", item);

but I want to be able to do things with that item:

string.Format("{0:lcase}", item); // lowercases the item
string.Format("{0:ucase}", item); // uppercases the item
string.Format("{0:nospace}", item); // removes spaces

I know I can do things like .ToUpper(), .ToLower() etc. but I need to do it with string formatting.

I've been looking into things like IFormatProvider and IFormattable but I don't really know if they are the things I should be using, or, how to implement them.

Can anyone explain how I can solve this problem?

Rationale (just in case you want to know...)

I have a small program, where I can enter a comma delimited set of values, and a template. The items are passed into string.Format, along with the template which creates an output. I want to provide template formatting options, so that the user can control how they want items to be output.

Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
  • 1
    What type can `item` have? See [String.Format - how it works and how to implement custom formatstrings](http://stackoverflow.com/questions/10512349/string-format-how-it-works-and-how-to-implement-custom-formatstrings). – CodeCaster Feb 23 '16 at 12:01
  • @CodeCaster item is a string (see rationale) – Matthew Layton Feb 23 '16 at 12:02
  • How about [ICustomFormatter](https://msdn.microsoft.com/en-us/library/system.icustomformatter(v=vs.110).aspx) – Ivan Stoev Feb 23 '16 at 12:05

1 Answers1

15

You can make a custom formatter, something like:

public class MyFormatter : IFormatProvider, ICustomFormatter
{
   public object GetFormat(Type formatType)
   {
      if (formatType == typeof(ICustomFormatter))
         return this;
      else
         return null;
   }

   public string Format(string fmt, object arg, IFormatProvider formatProvider) 
   {
       if(arg == null) return string.Empty;

       if(fmt == "lcase")
           return arg.ToString().ToLower();
       else if(fmt == "ucase")
           return arg.ToString().ToUpper();
       else if(fmt == "nospace")
           return arg.ToString().Replace(" ", "");
       // Use this if you want to handle default formatting also
       else if (arg is IFormattable) 
           return ((IFormattable)arg).ToString(fmt, CultureInfo.CurrentCulture);
       return arg.ToString();
   }
}

Then use it like:

 string.Format(new MyFormatter(),
            "{0:lcase}, {0:ucase}, {0:nospace}", 
            "My Test String")

This should return:

my test string, MY TEST STRING, MyTestString

Jcl
  • 27,696
  • 5
  • 61
  • 92
  • Shouldn't you be passing the `formatProvider` in the `IFormattable` `ToString`? And shouldn't you check if `arg` is `IFormattable` first and then do the additional custom formatting? – juharr Feb 23 '16 at 12:29
  • @juharr No to both questions: the passed `formatProvider` in this example would be our same object, so it'd loop indefinitely: we are passing a default formatter (`CurrentCulture`) to handle default formatting. The fact that is `IFormattable` only differs from `object` in that we can actually pass an `IFormatProvider` to `ToString()`, so if we are not doing so in the rest of `ToString()` calls, there's no need for it to be `IFormattable`. One could extend this `ICustomFormatter` to accept a "chained" `IFormatProvider` and then we'd do as you say, but in this case, it is not necessary. – Jcl Feb 23 '16 at 12:35
  • @juharr of course, this is a very simple implementation just addressed to answer the question :-) – Jcl Feb 23 '16 at 12:41
  • i have delete my answer as the un reasonable down vote discourage me to give solutions... :( – Sathik Khan Feb 23 '16 at 13:38
  • 1
    @SathikKhan for the record, I hadn't downvoted you (so I'm not sure why you write that on a comment to my answer), but since your answer was, a) very little informative ("use XSLT" and basically that's all there was to it), and b) incorrect (since XSLT is for transforming XML files, and nowhere in the question does it say he's using XML), I guess the downvotes were kinda correct – Jcl Feb 23 '16 at 15:52
  • Sorry @Jcl, it doesn't mean to you. First, don't encourage people to use hardcode the conditions inside. Find an answer for these a) Why MS offering you to convert the dataset as XML? b) Did you tried to solve this problem using xslt? By doing b and thinking more a you will get to know few parsing will give you the best solution. NOTE: I never down vote anyones solution because no solution is INCORRECT. – Sathik Khan Feb 23 '16 at 18:46
  • @SathikKhan the problem is that you are assuming a `DataSet` here, and `XML`, where the OP hasn't mentioned neither at all. Yes, of course, XSLT can be used, but it would mean a rather convoluted and unperformant solution (transform whatever text you are using to an XML document, then make the XSLT transform, then parse the XML document back?) to a very specific problem. Add to that, that your answer was basically just a hint without any *specific* solution, and I can see where the downvotes were coming. Again, I didn't downvote it, but I can see where they came from – Jcl Feb 23 '16 at 18:49
  • @SathikKhan and I think there *are* incorrect solutions, but Stack Overflow comments are not the best place to debate around that. You can always ask for oppinions at http://meta.stackoverflow.com – Jcl Feb 23 '16 at 18:50
  • @Jcl, not indent to take this as a debate but just wanna share my view. Thanks. – Sathik Khan Feb 24 '16 at 08:25