Почему каждый статический "<...> w980>" Is... "имеет перегрузку строки, например. IsWhiteSpace (строка, Int32)?

http://msdn.microsoft.com/en-us/library/1x308yk8.aspx

Это позволяет мне сделать это:

var str = "string ";
Char.IsWhiteSpace(str, 6);

Вместо

Char.IsWhiteSpace(str[6]);

Кажется необычным, поэтому я посмотрел на отражение:

[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public static bool IsWhiteSpace(char c)
{
    if (char.IsLatin1(c))
    {
        return char.IsWhiteSpaceLatin1(c);
    }
    return CharUnicodeInfo.IsWhiteSpace(c);
}

[SecuritySafeCritical]
public static bool IsWhiteSpace(string s, int index)
{
    if (s == null)
    {
        throw new ArgumentNullException("s");
    }
    if (index >= s.Length)
    {
        throw new ArgumentOutOfRangeException("index");
    }
    if (char.IsLatin1(s[index]))
    {
        return char.IsWhiteSpaceLatin1(s[index]);
    }
    return CharUnicodeInfo.IsWhiteSpace(s, index);
}

Три вещи поразили меня:

  • Почему это делается, чтобы сделать проверку предела только на верхней границе? Выбрасывание ArgumentOutOfRangeException, тогда как индекс ниже 0 дал бы стандартную строку IndexOutOfRangeException
  • Уровень SecuritySafeCriticalAttribute, о котором я прочитал общий blerb, но все еще неясно, что он здесь делает, и если это связанный с проверкой верхней границы.
  • TargetedPatchingOptOutAttribute отсутствует в других методах Is...(char). Пример IsLetter, IsNumber и т.д.

Ответы

Ответ 1

Потому что не каждый символ подходит для C# char. Например, "𠀀" занимает 2 С# chars, и вы не можете получить информацию об этом символе только с перегрузкой char. С помощью String и индекса методы могут видеть, является ли символ с индексом i высоким суррогатом char, а затем читать нижний суррогат char при следующем индексе, добавить их в соответствии с алгоритмом и получить информацию о кодовой точке U+20000.

Вот как UTF-16 может кодировать 1 миллион различных кодовых точек, это кодирование с переменной шириной. Для кодирования символа требуется 1-2 байта или 1-2 символа С#.

Ответ 2

Почему это делается, чтобы сделать проверку предела только на верхней границе?

Это не так. Он выполняет сравнение без знака, поэтому каждое отрицательное число будет сравниваться больше длины и вызывать соответствующее исключение. Это происходит, чтобы не получить декомпиляцию точно.