C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
It matches punctuation characters that are found in Unicode. These are not used in some programs. We look closely at this method and re-implement it.
Example. To start I developed a program that loops through all the range of ASCII characters. This range includes 0 through 127. It generates a case statement for each character that is considered a punctuation character.
Then: We use this case statement to create an optimized method. Some characters, such as the backslash, will need to be escaped.
C# program that tests char.IsPunctuation using System; class Program { static void Main() { for (int i = 0; i < 128; i++) { if (char.IsPunctuation((char)i)) { Console.WriteLine("case '{0}':", (char)i); } } } } Output case '!': case '"': case '#': case '%': case '&': case ''': case '(': case ')': case '*': case ',': case '-': case '.': case '/': case ':': case ';': case '?': case '@': case '[': case '\': case ']': case '_': case '{': case '}':
It is important to realize that char.IsPunctuation matches many characters in Unicode, which are at the higher range of char values. These cannot even be printed to the Console. Some are control characters.
Example 2. Next we see the new, re-implemented version of char.IsPunctuation. This method is precisely equivalent for inputs within ASCII. In the range of characters beyond ASCII, it will have different results.
Also: We benchmark the new implementation. In programs this method could be added as an extension method, using the this-argument syntax.
C# program that benchmarks punctuation testing using System; using System.Diagnostics; class Program { static bool Punctuation(char value) { switch (value) { case '!': case '"': case '#': case '%': case '&': case '\'': case '(': case ')': case '*': case ',': case '-': case '.': case '/': case ':': case ';': case '?': case '@': case '[': case '\\': case ']': case '_': case '{': case '}': return true; default: return false; } } const int _max = 100000000; static void Main() { var s1 = Stopwatch.StartNew(); bool b = false; for (int i = 0; i < _max; i++) { b = Punctuation('#') && Punctuation('?') && Punctuation('.'); } s1.Stop(); var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { b = char.IsPunctuation('#') && char.IsPunctuation('?') && char.IsPunctuation('.'); } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.Read(); } } Output 7.65 ns [new version] 8.29 ns [char.IsPunctuation]
The results indicate that the custom implementation, which was generated from the results of char.IsPunctuation, is slightly faster. This makes sense because it does less. It does not need to handle any Unicode characters.
Note: The method that handles only ASCII may be more useful. Some programs may not expect Unicode punctuation characters.
And: They would act in unexpected ways if those characters were considered punctuation.
Discussion. Re-implementing the char.IsPunctuation method is perhaps not the best use of a programmer's time. But it does better inform us of the exact behavior of char.IsPunctuation. And the faster implementation is essentially free.
Tip: It does not require a lot of brainpower to develop. Brainpower is often in short supply.
Also: By following the technique used to generate the custom method, we are assured that it is precisely equivalent.
Summary. We explored the char.IsPunctuation method in the C# language and .NET Framework. This method handles a wide range of punctuation characters. But within ASCII, it handles only well-known and recognized punctuation.