Похоже, это противоречит всем руководящим принципам дизайна. Статический метод, который принимает единственный аргумент типа T, обычно должен быть просто методом-членом.
Это так странно, что мне пришлось опубликовать StackOverflow вопрос, чтобы понять, что IsUpper существует (поскольку он не отображался в автозаполнении)
Редактировать
Я понимаю, что мое предыдущее заявление требует небольшого пояснения. Пример хорошего дизайна - String.ToLower (). Вместо того, чтобы прототипировать его как static void ToLower (String foo), это метод-член. Совершенно очевидно (по крайней мере, для меня), что то же самое должно происходить и с char.IsLower ().





См. Также вопрос это.
Краткая версия - в исходной среде IDE возникли проблемы с появлением intellisense при вызове из строкового литерала (и я предполагаю, что литералы char тоже). Поэтому дизайнеры сделали методы статическими, чтобы обойти эту проблему.
РЕДАКТИРОВАНИЕ: Здесь я немного разглагольствовал о дизайнерах .NET, поддавшихся давлению со стороны дизайнеров IDE. Но, увидев ответ Попа на этот вопрос, я менее уверен в этом.
EDIT2: Тим в комментариях спросил, знаем ли мы, что это правда, или это просто предположение. Мне не удалось найти точную ссылку на эту проблему, но я нашел статью 2002 года, в которой говорилось об ошибке intellisense в строковом литерале. Это примерно на полпути вниз по странице это.
В этом объяснении гораздо больше смысла, чем в объяснении Тима.
Методы класса String и методы stuctures / primiteves не имеют ничего общего. Причина не в этом. Причина в безопасности потоков. Сделать метод статическим - это простой способ сделать его потокобезопасным, поскольку он получает копию структуры.
@Pop единственное, что у них общего, - это язык, определяющий для них литералы, с которыми у IDE были проблемы. В этом смысле строка и символы (а также целые числа, числа с плавающей запятой, десятичные дроби и т. д.) Одинаковы.
Есть еще много тонких различий: структуры выделяются в стеке, область строк выделяется в куче, структура может быть изменена на месте (путем переопределения области памяти, в которой она находится), а строка не может.
Методы экземпляра в строках получают ссылку this, которую нельзя изменить. Методы экземпляра примитивов и структур получают указатель на структуру, и этот указатель указывает на энергозависимую память.
Я тоже отказываюсь от этого. Это тоже имеет смысл. Это вполне могло быть одной из причин, по которой он стал статичным.
На мой взгляд, это имеет смысл.
Есть много статических методов, которые принимают один аргумент. Было бы не так хорошо вычислять квадратный корень, используя что-то вроде этого:
double d = 100.0;
Console.WriteLine("Square root of d is " + d.Sqrt());
Это уменьшило бы «Сплоченность» в плане ОО-дизайна, что не является хорошей практикой. Было бы лучше разделить эту ответственность на класс Math.
double d = 100.0;
Console.WriteLine("Square root of d is " + Math.Sqrt(d));
Методы экземпляра в структурах не являются потокобезопасными. Статические методы, напротив, находятся.
Статические методы получают копию структуры, методы экземпляра - управляемый указатель. Доступ к данным через указатель не является безопасной операцией и может легко привести к состояниям гонки.
Вот почему большинство методов структур / примитивов являются статическими, а не экземплярами.
Смотри здесь похожий вопрос.
Почему IsNan - это статический метод класса Double, а не свойство экземпляра?
В данном случае это не имеет значения. IsLower не изменяет значение, с которым работает.
Нет, но он использует значение, чтобы что-то определить (в данном случае). Если IsLower не является потокобезопасным, то многопоточный код может привести к тому, что IsLower вернет неправильный ответ.
IsLower этого не делает, но кто-то может изменить его из другого потока, и, поскольку метод экземпляра получает доступ к значениям, считанным указателем, он сначала читает значение, а затем другое при втором чтении. Следуйте моей ссылке, там есть пример, показывающий, что методы экземпляра не являются потокобезопасными.
Я прокомментировал этот ответ - я не думаю, что это доказывает, что методы экземпляра для неизменяемых типов значений не являются потокобезопасными. Это доказывает, что если переменная, содержащая неизменяемый тип значения, используется совместно между потоками, каждый из них может присвоить ей значение. Это было бы плохо как для статики, так и для методов экземпляра.
Еще раз проверьте пример, метод экземпляра считывает значение дважды и получает разные его значения. Статический метод всегда будет получать одно и то же значение, потому что он получил копию, которую нельзя изменить одновременно.
Да, но что, если бы значение в течение было изменено копией? Для нетривиальной структуры это возможно. А для ToLower он считывает значение только один раз, поэтому это не имеет никакого значения.
@Jay Bazuzi: если вы перейдете по ссылке, вы увидите пример того, как даже неизменяемые структуры не могут иметь потокобезопасные методы экземпляра. Если структура может быть скопирована (даже если она неизменна) и доступна через указатель (как это делает метод экземпляра), то это «не потокобезопасный».
@Earwicker, если значение было изменено во время копирования, то состояние гонки находится вне метода, а не внутри него. Условия конкуренции внутри методов инфраструктуры могут иметь различные разветвления, такие как нарушения безопасности и неопределенное поведение во время выполнения. Гонки в вашем коде могут привести только к ошибкам.
Этого не происходит - ошибочное значение во время входа в метод приведет к тому, что метод будет смотреть на случайно ошибочное значение. Это не лучше. Настоящая проблема заключается в случайном совместном использовании места хранения между потоками без надлежащей блокировки.
@Earwicker: поскольку статический метод не заменяет правильную синхронизацию, но имеет то преимущество, что он может безопасно предполагать, что переданное ему значение не изменится от точки входа до точки выхода. Я никогда не говорил, что статические методы заменяют синхронизацию, просто они защищены от состояния гонки.
Я имею в виду, что никакие условия гонки не могут повлиять на данные, над которыми они работают, с момента передачи им значений.
Я могу согласиться с этим, если это оговорено: пока копирование типа значения является атомарным в архитектуре машины. Таким образом, для составных типов значений это по-прежнему небезопасно, потому что значение может быть изменено во время операции копирования при вводе метода, в результате чего метод будет иметь поврежденное значение.
Для примитивного значения, достаточно маленького, чтобы его можно было атомарно копировать, это нормально, но результат вызова все равно будет непредсказуемым, поскольку он будет случайным образом зависеть от того, было ли значение изменено до или после начала вызова.
Кроме того, метод экземпляра для типа значения может точно имитировать поведение статического элемента, просто создавая копию this в начале. Тогда он ведет себя как статический метод. Так что переходить на статику все равно не нужно. Сложите все это вместе, и я не понимаю, в чем проблема.
@Earwicker: Когда метод экземпляра копирует значение, можете ли вы гарантировать, что значение, которое он копирует, является значением до или после изменения значения в другом потоке?
Нет - и то же самое верно, когда статический метод копирует значение.
это большое предположение. Знаем ли мы на самом деле? Можем ли мы это подтвердить, или это всего лишь предположение?