diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index ed4c5630b1e05..9b708c4c35f96 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -2079,7 +2079,7 @@ private static void FilterHelper( listType = MemberListType.CaseSensitive; } - if (allowPrefixLookup && name.EndsWith("*", StringComparison.Ordinal)) + if (allowPrefixLookup && name.EndsWith('*')) { // We set prefixLookup to true if name ends with a "*". // We will also set listType to All so that all members are included in diff --git a/src/libraries/Common/src/System/Net/CookieParser.cs b/src/libraries/Common/src/System/Net/CookieParser.cs index e50a3742d4d6e..1e0ee2734feb4 100644 --- a/src/libraries/Common/src/System/Net/CookieParser.cs +++ b/src/libraries/Common/src/System/Net/CookieParser.cs @@ -855,10 +855,9 @@ private static FieldInfo IsQuotedVersionField internal static string CheckQuoted(string value) { - if (value.Length < 2 || value[0] != '\"' || value[value.Length - 1] != '\"') - return value; - - return value.Length == 2 ? string.Empty : value.Substring(1, value.Length - 2); + return (value.Length >= 2 && value.StartsWith('\"') && value.EndsWith('\"')) + ? value.Substring(1, value.Length - 2) + : value; } internal bool EndofHeader() diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs index cefced3080152..165c9787c6875 100644 --- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs +++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Unix.cs @@ -202,7 +202,7 @@ internal static string GetPipePath(string serverName, string pipeName) // cross-platform with Windows (which has only '\' as an invalid char). if (Path.IsPathRooted(pipeName)) { - if (pipeName.IndexOfAny(s_invalidPathNameChars) >= 0 || pipeName[pipeName.Length - 1] == Path.DirectorySeparatorChar) + if (pipeName.IndexOfAny(s_invalidPathNameChars) >= 0 || pipeName.EndsWith(Path.DirectorySeparatorChar)) throw new PlatformNotSupportedException(SR.PlatformNotSupported_InvalidPipeNameChars); // Caller is in full control of file location. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs index 8eacd11d6691d..a40b6b9d089e0 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs @@ -537,7 +537,7 @@ private static bool TrySetOptionalTokenList(NameValueHeaderValue nameValue, ref // We need the string to be at least 3 chars long: 2x quotes and at least 1 character. Also make sure we // have a quoted string. Note that NameValueHeaderValue will never have leading/trailing whitespace. string valueString = nameValue.Value; - if ((valueString.Length < 3) || (valueString[0] != '\"') || (valueString[valueString.Length - 1] != '\"')) + if ((valueString.Length < 3) || !valueString.StartsWith('\"') || !valueString.EndsWith('\"')) { return false; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs index 9ddbd0d2e8cc4..9084597b1f90c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs @@ -358,7 +358,7 @@ private static void CheckValueFormat(string? value) } // Trailing/leading space are not allowed - if (value[0] == ' ' || value[0] == '\t' || value[^1] == ' ' || value[^1] == '\t') + if (value.StartsWith(' ') || value.StartsWith('\t') || value.EndsWith(' ') || value.EndsWith('\t')) { ThrowFormatException(value); } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpContent.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpContent.cs index 9b1b9445a6deb..8e508e8f4c1f8 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpContent.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpContent.cs @@ -192,8 +192,8 @@ internal static string ReadBufferAsString(ArraySegment buffer, HttpContent { // Remove at most a single set of quotes. if (charset.Length > 2 && - charset[0] == '\"' && - charset[charset.Length - 1] == '\"') + charset.StartsWith('\"') && + charset.EndsWith('\"')) { encoding = Encoding.GetEncoding(charset.Substring(1, charset.Length - 2)); } diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/HttpListener.cs b/src/libraries/System.Net.HttpListener/src/System/Net/HttpListener.cs index 4cb267978cc50..a8f2a687a6959 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/HttpListener.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/HttpListener.cs @@ -146,7 +146,7 @@ internal void AddPrefix(string uriPrefix) { throw new ArgumentException(SR.net_listener_host, nameof(uriPrefix)); } - if (uriPrefix[uriPrefix.Length - 1] != '/') + if (!uriPrefix.EndsWith('/')) { throw new ArgumentException(SR.net_listener_slash, nameof(uriPrefix)); } diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerRequest.cs b/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerRequest.cs index 5bfecb4453ef0..b44dc6d003123 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerRequest.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerRequest.cs @@ -537,8 +537,8 @@ internal string GetString() internal static void FillFromString(NameValueCollection nvc, string s, bool urlencoded, Encoding encoding) { + int i = s.StartsWith('?') ? 1 : 0; int l = s.Length; - int i = (l > 0 && s[0] == '?') ? 1 : 0; while (i < l) { diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs b/src/libraries/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs index 351ad0c881050..6753f34565b66 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/Managed/HttpEndPointListener.cs @@ -178,7 +178,7 @@ public static void UnbindContext(HttpListenerContext context) string host = uri.Host; int port = uri.Port; string path = WebUtility.UrlDecode(uri.AbsolutePath); - string pathSlash = path[path.Length - 1] == '/' ? path : path + "/"; + string pathSlash = path.EndsWith('/') ? path : path + "/"; HttpListener? bestMatch = null; int bestLength = -1; diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs index aa8430f9b8fa1..ab7c7098ef200 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs @@ -204,7 +204,7 @@ public string ContentId ContentId = cid; return cid; } - if (cid.Length >= 2 && cid[0] == '<' && cid[cid.Length - 1] == '>') + if (cid.StartsWith('<') && cid.EndsWith('>')) { return cid.Substring(1, cid.Length - 2); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs index beb6d5208fa39..2af110aa86e69 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs @@ -141,9 +141,9 @@ private static bool TryParse(string address, string? displayName, Encoding? disp return false; } - if (displayName.Length >= 2 && displayName[0] == '\"' && displayName[^1] == '\"') + if (displayName.Length >= 2 && displayName.StartsWith('\"') && displayName.EndsWith('\"')) { - // Peal bounding quotes, they'll get re-added later. + // Peel bounding quotes, they'll get re-added later. displayName = displayName.Substring(1, displayName.Length - 2); } } diff --git a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs index 01e82b6286a8d..ece5a17973407 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs @@ -235,7 +235,11 @@ public string Name } internal bool InternalSetName(string? value) { - if (string.IsNullOrEmpty(value) || value[0] == '$' || value.IndexOfAny(ReservedToName) != -1 || value[0] == ' ' || value[value.Length - 1] == ' ') + if (string.IsNullOrEmpty(value) + || value.StartsWith('$') + || value.StartsWith(' ') + || value.EndsWith(' ') + || value.IndexOfAny(ReservedToName) >= 0) { m_name = string.Empty; return false; @@ -339,7 +343,11 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma } // Check the name - if (string.IsNullOrEmpty(m_name) || m_name[0] == '$' || m_name.IndexOfAny(ReservedToName) != -1 || m_name[0] == ' ' || m_name[m_name.Length - 1] == ' ') + if (string.IsNullOrEmpty(m_name) || + m_name.StartsWith('$') || + m_name.StartsWith(' ') || + m_name.EndsWith(' ') || + m_name.IndexOfAny(ReservedToName) >= 0) { if (shouldThrow) { @@ -350,7 +358,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // Check the value if (m_value == null || - (!(m_value.Length > 2 && m_value[0] == '\"' && m_value[m_value.Length - 1] == '\"') && m_value.IndexOfAny(ReservedToValue) != -1)) + (!(m_value.Length > 2 && m_value.StartsWith('\"') && m_value.EndsWith('\"')) && m_value.IndexOfAny(ReservedToValue) >= 0)) { if (shouldThrow) { @@ -360,8 +368,8 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma } // Check Comment syntax - if (Comment != null && !(Comment.Length > 2 && Comment[0] == '\"' && Comment[Comment.Length - 1] == '\"') - && (Comment.IndexOfAny(ReservedToValue) != -1)) + if (Comment != null && !(Comment.Length > 2 && Comment.StartsWith('\"') && Comment.EndsWith('\"')) + && (Comment.IndexOfAny(ReservedToValue) >= 0)) { if (shouldThrow) { @@ -371,8 +379,8 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma } // Check Path syntax - if (Path != null && !(Path.Length > 2 && Path[0] == '\"' && Path[Path.Length - 1] == '\"') - && (Path.IndexOfAny(ReservedToValue) != -1)) + if (Path != null && !(Path.Length > 2 && Path.StartsWith('\"') && Path.EndsWith('\"')) + && (Path.IndexOfAny(ReservedToValue) >= 0)) { if (shouldThrow) { @@ -498,7 +506,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // Note: Normally Uri.AbsolutePath contains at least one "/" after parsing, // but it's possible construct Uri with an empty path using a custom UriParser int lastSlash; - if (path.Length == 0 || path[0] != '/' || (lastSlash = path.LastIndexOf('/')) == 0) + if (!path.StartsWith('/') || (lastSlash = path.LastIndexOf('/')) == 0) { m_path = "/"; break; @@ -587,35 +595,29 @@ public string Port else { // Parse port list - if (value[0] != '\"' || value[value.Length - 1] != '\"') + if (!value.StartsWith('\"') || !value.EndsWith('\"')) { throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value)); } - string[] ports = value.Split(PortSplitDelimiters); - - List portList = new List(); - int port; + string[] ports = value.Split(PortSplitDelimiters, StringSplitOptions.RemoveEmptyEntries); + int[] parsedPorts = new int[ports.Length]; for (int i = 0; i < ports.Length; ++i) { - // Skip spaces - if (ports[i] != string.Empty) + if (!int.TryParse(ports[i], out int port)) { - if (!int.TryParse(ports[i], out port)) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value)); - } - - // valid values for port 0 - 0xFFFF - if ((port < 0) || (port > 0xFFFF)) - { - throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value)); - } + throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value)); + } - portList.Add(port); + // valid values for port 0 - 0xFFFF + if ((port < 0) || (port > 0xFFFF)) + { + throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value)); } + + parsedPorts[i] = port; } - m_port_list = portList.ToArray(); + m_port_list = parsedPorts; m_port = value; m_version = MaxSupportedVersion; m_cookieVariant = CookieVariant.Rfc2965; diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs b/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs index 3825092e21c2b..86187da361d4e 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs @@ -927,7 +927,7 @@ private static bool PathMatch(string requestPath, string cookiePath) if (!requestPath.StartsWith(cookiePath, StringComparison.Ordinal)) return false; return requestPath.Length == cookiePath.Length || - cookiePath.Length > 0 && cookiePath[^1] == '/' || + cookiePath.EndsWith('/') || requestPath[cookiePath.Length] == '/'; } diff --git a/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs b/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs index 5ff4ba798d8c1..a093ef49c98e8 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs @@ -602,8 +602,7 @@ protected override PipelineEntry[] BuildCommandsList(WebRequest req) commandList.Add(new PipelineEntry(FormatFtpCommand("RNFR", baseDir + requestFilename), flags)); string renameTo; - if (!string.IsNullOrEmpty(request.RenameTo) - && request.RenameTo.StartsWith("/", StringComparison.OrdinalIgnoreCase)) + if (request.RenameTo is not null && request.RenameTo.StartsWith('/')) { renameTo = request.RenameTo; // Absolute path } @@ -774,7 +773,7 @@ private static void GetPathInfo(GetPathOption pathOption, } // strip off trailing '/' on directory if present - if (directory.Length > 1 && directory[directory.Length - 1] == '/') + if (directory.Length > 1 && directory.EndsWith('/')) directory = directory.Substring(0, directory.Length - 1); } @@ -954,11 +953,11 @@ private void TryUpdateResponseUri(string str, FtpWebRequest request) escapedFilename = escapedFilename.Replace("#", "%23"); // help us out if the user forgot to add a slash to the directory name - string orginalPath = baseUri.AbsolutePath; - if (orginalPath.Length > 0 && orginalPath[orginalPath.Length - 1] != '/') + string originalPath = baseUri.AbsolutePath; + if (originalPath.Length > 0 && !originalPath.EndsWith('/')) { UriBuilder uriBuilder = new UriBuilder(baseUri); - uriBuilder.Path = orginalPath + "/"; + uriBuilder.Path = originalPath + "/"; baseUri = uriBuilder.Uri; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.GetFolderPathCore.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.GetFolderPathCore.Unix.cs index 27dbc327aec73..7990febb5a11b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.GetFolderPathCore.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.GetFolderPathCore.Unix.cs @@ -93,7 +93,7 @@ private static string GetFolderPathCoreWithoutValidation(SpecialFolder folder) // "$XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored." // "If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used." string? data = GetEnvironmentVariable("XDG_DATA_HOME"); - if (string.IsNullOrEmpty(data) || data[0] != '/') + if (data is null || !data.StartsWith('/')) { data = Path.Combine(home, ".local", "share"); } @@ -137,7 +137,7 @@ private static string GetXdgConfig(string home) // "$XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored." // "If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used." string? config = GetEnvironmentVariable("XDG_CONFIG_HOME"); - if (string.IsNullOrEmpty(config) || config[0] != '/') + if (config is null || !config.StartsWith('/')) { config = Path.Combine(home, ".config"); } @@ -151,7 +151,7 @@ private static string ReadXdgDirectory(string homeDir, string key, string fallba Debug.Assert(!string.IsNullOrEmpty(fallback), $"Expected non-empty fallback"); string? envPath = GetEnvironmentVariable(key); - if (!string.IsNullOrEmpty(envPath) && envPath[0] == '/') + if (envPath is not null && envPath.StartsWith('/')) { return envPath; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs index 9614d2289cc7a..496eb6597ee44 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs @@ -290,14 +290,14 @@ private static int[] ConvertWin32GroupString(string win32Str) return new int[] { 3 }; } - if (win32Str[0] == '0') + if (win32Str.StartsWith('0')) { return new int[] { 0 }; } // Since its in n;n;n;n;n format, we can always get the length quickly int[] values; - if (win32Str[^1] == '0') + if (win32Str.EndsWith('0')) { // Trailing 0 gets dropped. 1;0 -> 1 values = new int[win32Str.Length / 2]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs index dd5e58becae9f..8212deead438c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs @@ -999,7 +999,7 @@ internal string EnglishName // Our existing names mostly look like: // "English" + "United States" -> "English (United States)" // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)" - if (EnglishLanguageName[^1] == ')') + if (EnglishLanguageName.EndsWith(')')) { // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)" englishDisplayName = string.Concat( diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfoScanner.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfoScanner.cs index 463a5da4aadb8..34ba2a9125962 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfoScanner.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfoScanner.cs @@ -228,7 +228,7 @@ internal void AddDateWordOrPostfix(string? formatPostfix, string str) m_dateWords.Add(str); } - if (str[^1] == '.') + if (str.EndsWith('.')) { // Old version ignore the trailing dot in the date words. Support this as well. string strWithoutDot = str[0..^1]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs index 08b077c1dd92f..e3fe7fa4dde66 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs @@ -182,7 +182,7 @@ private static bool FilterTypeNameImpl(Type cls, object filterCriteria, StringCo throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString); } // Check to see if this is a prefix or exact match requirement - if (str.Length > 0 && str[^1] == '*') + if (str.EndsWith('*')) { ReadOnlySpan slice = str.AsSpan(0, str.Length - 1); return cls.Name.AsSpan().StartsWith(slice, comparison); diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs index c70e9e52734e8..76d8ac6ed61c8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs @@ -594,6 +594,20 @@ public bool EndsWith(string value, bool ignoreCase, CultureInfo? culture) public bool EndsWith(char value) { + // If the string is empty, *(&_firstChar + length - 1) will deref within + // the _stringLength field, which will be all-zero. We must forbid '\0' + // from going down the optimized code path because otherwise empty strings + // would appear to end with '\0', which is incorrect. + // n.b. This optimization relies on the layout of string and is not valid + // for other data types like char[] or Span. + if (RuntimeHelpers.IsKnownConstant(value) && value != '\0') + { + // deref Length now to front-load the null check; also take this time to zero-extend + // n.b. (localLength - 1) could be negative! + nuint localLength = (uint)Length; + return Unsafe.Add(ref _firstChar, (nint)localLength - 1) == value; + } + int lastPos = Length - 1; return ((uint)lastPos < (uint)Length) && this[lastPos] == value; } @@ -1004,10 +1018,16 @@ public bool StartsWith(string value, bool ignoreCase, CultureInfo? culture) public bool StartsWith(char value) { + // If the string is empty, _firstChar will contain the null terminator. + // We forbid '\0' from going down the optimized code path because otherwise + // empty strings would appear to begin with '\0', which is incorrect. + // n.b. This optimization relies on the layout of string and is not valid + // for other data types like char[] or Span. if (RuntimeHelpers.IsKnownConstant(value) && value != '\0') { return _firstChar == value; } + return Length != 0 && _firstChar == value; } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBaseWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBaseWriter.cs index 8ae28963eb92a..3d9e7c918fc54 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBaseWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/XmlBaseWriter.cs @@ -442,7 +442,7 @@ public override void WriteComment(string? text) { text = string.Empty; } - else if (text.IndexOf("--", StringComparison.Ordinal) != -1 || (text.Length > 0 && text[text.Length - 1] == '-')) + else if (text.Contains("--") || text.StartsWith('-')) { throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.XmlInvalidCommentChars, nameof(text))); } diff --git a/src/libraries/System.Private.Uri/src/System/Uri.cs b/src/libraries/System.Private.Uri/src/System/Uri.cs index 655da9b833076..ad283039b324b 100644 --- a/src/libraries/System.Private.Uri/src/System/Uri.cs +++ b/src/libraries/System.Private.Uri/src/System/Uri.cs @@ -1279,7 +1279,7 @@ public static UriHostNameType CheckHostName(string? name) { fixed (char* fixedName = name) { - if (name[0] == '[' && name[name.Length - 1] == ']') + if (name.StartsWith('[') && name.EndsWith(']')) { // we require that _entire_ name is recognized as ipv6 address if (IPv6AddressHelper.IsValid(fixedName, 1, ref end) && end == name.Length) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs index 08ec978d67116..6a6a623a73ba3 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextWriter.cs @@ -763,7 +763,7 @@ public override void WriteComment(string? text) { try { - if (null != text && (text.Contains("--") || (text.Length != 0 && text[text.Length - 1] == '-'))) + if (null != text && (text.Contains("--") || text.StartsWith('-'))) { throw new ArgumentException(SR.Xml_InvalidCommentChars); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs index b62d6c6225a37..5a44dde1304f5 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWellFormedWriter.cs @@ -1795,7 +1795,7 @@ private bool PushNamespaceExplicit(string prefix, string ns) { throw new ArgumentException(SR.Format(SR.Xml_NamespaceDeclXmlXmlns, prefix)); } - if (prefix.Length > 0 && prefix[0] == 'x') + if (prefix.StartsWith('x')) { if (prefix == "xml") { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlEntityReference.cs b/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlEntityReference.cs index d4b0bb64cc79e..c88f12f0bf349 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlEntityReference.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Dom/XmlEntityReference.cs @@ -36,7 +36,7 @@ protected internal XmlEntityReference(string name, XmlDocument doc) : base(doc) { if (!doc.IsLoading) { - if (name.Length > 0 && name[0] == '#') + if (name.StartsWith('#')) { throw new ArgumentException(SR.Xdom_InvalidCharacter_EntityReference); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReader.cs index a578730cb56a5..11480e17868bf 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReader.cs @@ -3940,12 +3940,12 @@ private void WriteMemberBegin(Member[] members) else { bool useReflection = typeDesc.UseReflection; - if (member.Source[member.Source.Length - 1] == '(' || member.Source[member.Source.Length - 1] == '{') + if (member.Source.EndsWith('(') || member.Source.EndsWith('{')) { WriteCreateInstance(typeDescFullName, a, useReflection, typeDesc.CannotNew); Writer.Write(member.Source); Writer.Write(a); - if (member.Source[member.Source.Length - 1] == '{') + if (member.Source.EndsWith('{')) Writer.WriteLine("});"); else Writer.WriteLine(");"); @@ -4511,7 +4511,7 @@ private void WriteSourceBeginTyped(string source, TypeDesc? typeDesc) private void WriteSourceBegin(string source) { Writer.Write(source); - if (source[source.Length - 1] != '(' && source[source.Length - 1] != '{') + if (!source.EndsWith('(') && !source.EndsWith('{')) Writer.Write(" = "); } @@ -4519,9 +4519,9 @@ private void WriteSourceEnd(string source) { // source could be of the form "var", "arrayVar[i]", // "collection.Add(" or "methodInfo.Invoke(collection, new object[] {" - if (source[source.Length - 1] == '(') + if (source.EndsWith('(')) Writer.Write(")"); - else if (source[source.Length - 1] == '{') + else if (source.EndsWith('{')) Writer.Write("})"); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReaderILGen.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReaderILGen.cs index 79363391c6f80..d2cca45b10da8 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReaderILGen.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReaderILGen.cs @@ -2186,7 +2186,7 @@ private void WriteMemberBegin(Member[] members) } else { - if (member.Source[member.Source.Length - 1] == '(' || member.Source[member.Source.Length - 1] == '{') + if (member.Source.EndsWith('(') || member.Source.EndsWith('{')) { WriteCreateInstance(a, typeDesc.CannotNew, typeDesc.Type!); WriteSourceBegin(member.Source); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/ValidateNames.cs b/src/libraries/System.Private.Xml/src/System/Xml/ValidateNames.cs index 2e73ecbe25f86..007d236e66fab 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/ValidateNames.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/ValidateNames.cs @@ -306,7 +306,7 @@ internal static void ParseNameTestThrow(string s, out string? prefix, out string { int len, lenLocal, offset; - if (s.Length != 0 && s[0] == '*') + if (s.StartsWith('*')) { // '*' as a NameTest prefix = localName = null; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs index 68e658f7284ee..6b51af6d3b625 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs @@ -429,7 +429,10 @@ internal static string VerifyNCName(string name, ExceptionType exceptionType) return token; } - if (token[0] == ' ' || token[token.Length - 1] == ' ' || token.IndexOfAny(crt) != -1 || token.IndexOf(" ", StringComparison.Ordinal) != -1) + if (token.StartsWith(' ') || + token.EndsWith(' ') || + token.IndexOfAny(crt) >= 0 || + token.Contains(" ")) { throw new XmlException(SR.Sch_NotTokenString, token); } @@ -438,12 +441,15 @@ internal static string VerifyNCName(string name, ExceptionType exceptionType) internal static Exception? TryVerifyTOKEN(string token) { - if (token == null || token.Length == 0) + if (string.IsNullOrEmpty(token)) { return null; } - if (token[0] == ' ' || token[token.Length - 1] == ' ' || token.IndexOfAny(crt) != -1 || token.IndexOf(" ", StringComparison.Ordinal) != -1) + if (token.StartsWith(' ') || + token.EndsWith(' ') || + token.IndexOfAny(crt) >= 0 || + token.Contains(" ")) { return new XmlException(SR.Sch_NotTokenString, token); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs index 906f1edb8eb84..ecb780864377c 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs @@ -817,7 +817,7 @@ private static string UrlPathAppend(string baseUri, ReadOnlyMemory resourc int count = baseUri.Length + resource.Length; - if (baseUri[baseUri.Length - 1] == '/') + if (baseUri.EndsWith('/')) { return string.Create( count, diff --git a/src/libraries/System.Web.HttpUtility/src/System/Web/HttpUtility.cs b/src/libraries/System.Web.HttpUtility/src/System/Web/HttpUtility.cs index ddb3a33ebc50f..0d8cc4a83dcd4 100644 --- a/src/libraries/System.Web.HttpUtility/src/System/Web/HttpUtility.cs +++ b/src/libraries/System.Web.HttpUtility/src/System/Web/HttpUtility.cs @@ -87,7 +87,7 @@ public static NameValueCollection ParseQueryString(string query, Encoding encodi HttpQSCollection result = new HttpQSCollection(); int queryLength = query.Length; - int namePos = queryLength > 0 && query[0] == '?' ? 1 : 0; + int namePos = query.StartsWith('?') ? 1 : 0; if (queryLength == namePos) { return result; diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs index aecc48b994709..d0c0284e82a35 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs @@ -176,7 +176,7 @@ private static string FormatConsoleAPICalled(JObject args) } else { - if (output.Length > 0 && output[^1] == '\n') + if (output.EndsWith('\n')) output = output[..^1]; }