How to validate format for string.Format method
Asked Answered
I

4

14

string.Format has following method signature

string.Format(format, params, .., .. , ..);

I want to pass custom format each time like

string custFormat = "Hi {0} ... {n} ";   // I only care about numbers here, and want avoid  {abdb}
string name = "Foo";

string message = ProcessMessage(custFormat, name);

public string ProcessMessage(custFormat, name)
{
   return string.Format(custFormat, name);
}

I want to validate the value in custFormat before passing to ProcessMessage to avoid exception.

Indefensible answered 24/8, 2012 at 15:16 Comment(8)
What language are you working in? C#?Jeanett
You should tag this question with the programming language you are looking for an answer in.Acinaciform
Why avoid the exception ? You might simply catch it.Procora
thats exactly me doin now... but do not like it...Indefensible
Unless I'm missing something, the method ProcessMessage is quite pointless in this context, as it's nothing more than a wrapper around a built in function which doesn't add any functionality. Also, why call a static String method, when you could just call name.ToString(custFormat);. As others have stated, catch the exception, job done.Abet
@Bryan, Try catch is not the best way, Otherwise I would not post it here. In above example I'm passing only onr param for explanation only but there are more args in actual implementation.Indefensible
Can you post your actual code then rather than similar 'sample' code? That will make everyone's life much easier trying to help you, and you will likely get better answers that focus on the actual issue you are having.Abet
I don't understand your aversion to try/catch, either. What about it exactly are you trying (har har) to avoid?Exciseman
E
26

Let's think about this API, if it exists. The goal is to pre-validate a format string, to make sure String.Format won't throw.

Note that any string which doesn't contain a valid format slot is a valid format string - if you don't try to insert any replacements.

-> So we would need to pass in the number or args we expect to replace

Note that there are tons of different specialty formatting patterns, each with a specific meaning for specific types: http://msdn.microsoft.com/en-us/library/system.string.format.aspx

Although it seems that String.Format won't throw if you pass a format string which doesn't match your argument type, the formatter becomes meaningless in such cases. e.g. String.Format("{0:0000}", "foo")

-> So such an API would be truly useful only if you passed the types of the args, as well.

If we already need to pass in our format string and an array of types (at least), then we are basically at the signature of String.Format, so why not just use that and handle the exception? It would be nice if something like String.TryFormat existed, but to my knowledge it doesn't.

Also, pre-validating via some API, then re-validating in String.Format itself is not ideal perf-wise.

I think the cleanest solution might be to define a wrapper:

public static bool TryFormat(string format, out string result, params Object[] args)
{
   try
   {
      result = String.Format(format, args);
      return true;
   }
   catch(FormatException)
   {
      return false;
   }
}
Exciseman answered 24/8, 2012 at 15:57 Comment(1)
Please note that throwing an exception has a immensly high performance cost compared to other validation. If you expect more than 1-2% of the cases to throw an exception and this is not a function used by one user once per day, you should implement a proper validation of your input values instead. See also other discussions about the performance of exceptions.Shifrah
K
0

As long as you're only passing in 1 argument, you can look search custFormat for {0}. If you don't find it, it's invalid.

Kayne answered 24/8, 2012 at 15:23 Comment(3)
one arg is just for to demonstrate here.Indefensible
{<number>} is not the only valid format pattern. There is a huge range of valid patterns. e.g. {0:0000}, {0:D}, etc.Exciseman
Good point, I was just using his very simple sample to provide a simple answer I suppose.Kayne
V
0

You can validate with try catch, if format throw exceptin you log information and stop treatment.

try 
{ 
   string.Format(custFormat, params, .., .. , ..);
}
catch(FormatException ex)  
{ 
  throw ex;
}

string message = ProcessMessage(custFormat, name);
Vicenta answered 24/8, 2012 at 15:23 Comment(0)
I
-1

You should use regular expressions for syntax checking and you may use some semantic checking as well.

Regular expression should be: (*{\d+}*)+

Iconoduly answered 24/8, 2012 at 15:23 Comment(1)
This is not even close. First, there is a huge range of different possible valid format patterns (msdn.microsoft.com/en-us/library/system.string.format.aspx) and this captures only very simplest. Second, it doesn't consider the number or arguments being replaced at all - e.g. String.Format("{0} {15}", "test") will pass this pattern but throw.Exciseman

© 2022 - 2024 — McMap. All rights reserved.