-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add common helper methods to the String class (Contains(StringComparison), Replace(StringComparison), Left, Truncate, TrimPrefix) #14831
Comments
Most of these have very well-known idiomatic solutions, that people learn very early on in programming generally. This isn't to say they wouldn't be useful, but does reduce how useful. 1 Is definitely an example of this. 2 I think would certainly be useful if done well (catching the trickier edge-cases around e.g. 3, 4, 5 are again common idioms. 6 is a common idiom with regular expressions. 7 has some semantic nicety IMO but little else. I'd note that many people don't like accepting 8 Text files that use U+000D as a line-ending aren't unheard of, though much rarer since Mac OS 9 stopped being current. Text files using U+2028 and U+2029 to distinguish lines and paragraphs will likely become more common. If you were to do something like this, you should probably break on all mandatory-break sequences in UAX 14, which would be U+000A, U+000B, U+000C, U+000D when followed by anything other than U+000A, U+0085, U+2028 and U+2029. |
Regarding idioms: The idiom should not be Note, that in this expression I have referenced (2) This is true, I'm impressed :) The problem is that the match length is not necessarily (6) should not require regex, for reasons of performance and simplicity. The string to search must be escaped. I'm also not sure whether this will behave correctly in all cases (for example what about CurrentcultureIgnoreCase semantics or Unicode surrogate pairs?). This should just work. (7) Agreed. I only propose taking this as null for this extremely high frequency use case. (8) My best idea would be to define that this method behaves exactly identical to StreamReader (whatever that is). Good feedback, thanks. |
FYI, 6 has already been proposed: #14386. |
@JonHanna, may want to check out @ https://github.com/dotnet/corefx/issues/1244 |
We need formal API proposal. Please include also usage info with justification why it is useful to add (should be widely needed/used). BTW: There is overlap with #14504. |
What more details are needed? |
Formal API proposal: see example, or general API review process |
This issue hasn't been touched in 3+ years. Some of the shipping APIs ( Is there still interest in addressing the remainder of the proposal? |
I have personally written // inspired by Ruby https://apidock.com/rails/String/truncate
public static string Truncate(this string subject, int length, string omission = "...") |
If there's interest in a |
I have created an issue for I would suggest that the team goes over the list in this issue and decides which ones are worth pursuing further. Without this decision, this issue might keep lingering with no action taken. I'm willing to open issues for those that are deemed worthy in the style of the one that I just opened. I'm unlikely to make the code contribution but I can cleanly write up the APIs. |
The
String
class is missing some helper methods for string manipulation that are commonly needed. Of course it is possible for developers to add extension methods but that should not be required. here, I'll propose a list of methods that I think can be easily understood and are commonly required. The ordering of this list starts with the least controversial in my mind.bool Contains(this string str, string value, StringComparison comparisonType)
. We have no Contains version that takes a StringComparison. The workaround withIndexOf
is awkward and feels like magic.Replace(..., StringComparison)
. Right now,Replace
always usesOrdinal
.string Left(this string str, int count)
as well asRight
.Left
is equivalent tostr.Substring(0, count)
but right isstr.Substring(str.Length - count, count)
.Truncate(int maxLength)
. This is not equivalent to Substring(maxLength) because Substring throws if the string is short.bool IsValidIndex(this string str, int index)
tests whether the argument can be used to obtain a character from the indexer. That sometimes comes in handy. Alsobool IsValidRange(this string str, int index, int count)
. Both can be useful forDebug.Assert
assertions.string TrimPrefix(this string str, string prefix)
as well asTrimPostfix
. It turns out that when working with externally generated strings (ETL processes) it is very common to need to remove a prefix. For example to get a JIRA issue number as an int you doint.Parse("PROJ-2317".TrimPrefix("PROJ-"))
.Replace(..., "PROJ-", "")
is not equivalent and semantically wrong. TheTrimStart
method cannot be used here. Further helper methods would beEnsurePrefix/Postfix
.SplitLines()
. Returns the string split into lines. Need to define how to deal with OS-specific line endings. Probably, this should just bestr.Replace("\r", "").Split('\n')
which seems to work for everything.I can see some issues with some of these proposals. They are not perfect but I want to get the discussion going. I feel the BCL has a blind spot here. The list certainly starts out with a few no-brainers.
The text was updated successfully, but these errors were encountered: