Example #1
0
        // Determines whether two Strings match.
        public static bool Equals(string?a, string?b)
        {
            // Transform 'str == ""' to 'str != null && str.Length == 0' if either a or b are jit-time
            // constants. Otherwise, these two blocks are eliminated
            if (RuntimeHelpers.IsKnownConstant(a) && a != null && a.Length == 0)
            {
                return(b != null && b.Length == 0);
            }

            if (RuntimeHelpers.IsKnownConstant(b) && b != null && b.Length == 0)
            {
                return(a != null && a.Length == 0);
            }

            if (object.ReferenceEquals(a, b))
            {
                return(true);
            }

            if (a is null || b is null || a.Length != b.Length)
            {
                return(false);
            }

            return(EqualsHelper(a, b));
        }
Example #2
0
        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<char>.
            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);
        }