




Я думаю, это потому, что это метод создателя (не уверен, что есть лучшее название). Все, что он делает, это берет то, что вы ему даете, и возвращает единственный строковый объект. Он не работает с существующим объектом. Если бы он был нестатическим, вам для начала понадобится строка.
Потому что метод Format не имеет ничего общего с текущим значением строки. Значение строки не используется. Он берет строку и возвращает ее.
Я не вижу ничего плохого в том, что это статично ...
Мне кажется, что семантика статического метода имеет больше смысла. Возможно, это потому, что он примитивен. Там, где примитивы используются часто, вы хотите сделать код утилиты для работы с ними как можно более легким ... Кроме того, я думаю, что семантика намного лучше с String.Format по сравнению с "MyString BLAH BLAH {0}". Формат ...
Методы экземпляра хороши, когда у вас есть объект, который поддерживает некоторое состояние; процесс форматирования строки не влияет на строку, с которой вы работаете (читайте: не изменяет ее состояние), он создает новую строку.
С помощью методов расширения теперь вы можете съесть свой торт и съесть его (т.е. вы можете использовать последний синтаксис, если он помогает вам лучше спать по ночам).
Я еще не пробовал, но вы можете создать метод расширения для того, что хотите. Я бы не стал этого делать, но думаю, что это сработает.
Также я считаю, что String.Format() больше соответствует другим шаблонным статическим методам, таким как Int32.Parse(), long.TryParse() и т. д.
Вы также можете использовать StringBuilder в облаке, если хотите нестатический формат.
StringBuilder.AppendFormat()
String.Format принимает хотя бы одну строку и возвращает другую строку. Нет необходимости изменять строку формата, чтобы вернуть другую строку, поэтому это не имеет смысла (игнорируя ваше форматирование). С другой стороны, было бы не так уж сложно сделать String.Format функцией-членом, за исключением того, что я не думаю, что C# допускает константные функции-члены, как это делает C++. [Пожалуйста, исправьте меня и этот пост, если это так.]
Я думаю, что в целом лучше использовать String.Format, но я мог видеть смысл в желании иметь нестатическую функцию, когда у вас уже есть строка, сохраненная в переменной, которую вы хотите «отформатировать».
Кстати, все функции строкового класса не работают со строкой, а возвращают новый строковый объект, потому что строки неизменяемы.
Но наличие статического String.Format, в то время как другие методы, такие как Trim и PadLeft, не являются несовместимыми.
Because the Format method has nothing to do with a string's current value.
Это верно для строковых методов все, потому что строки .NET неизменяемы.
If it was non-static, you would need a string to begin with.
Это делает: строка формата.
Я считаю, что это всего лишь еще один пример многих недостатков дизайна в платформе .NET (и я не имею в виду это как пламя; я по-прежнему считаю, что платформа .NET превосходит большинство других платформ).
почему это не принятый ответ?
@tim: потому что я думаю, что ответ Эндрюса лучше. :-)
На самом деле я тоже предпочитаю принятый ответ, поскольку он отлично отвечает на вопрос. Мой собственный ответ больше похож на комментарий к некоторым предположениям о конструкции статических функций.
Отражение дает "неизменному" новый синоним: изменчивый ...: P
String.Format должен быть статическим методом, потому что строки неизменяемы. Создание метода экземпляра подразумевает, что вы можете использовать его для «форматирования» или изменения значения существующей строки. Вы не можете этого сделать, и делать его методом экземпляра, возвращающим новую строку, не имеет смысла. Следовательно, это статический метод.
Чем формат отличается от замены или подстроки? Фактические строки не меняются, возвращаются новые. Формат мог последовать его примеру.
Верно, но подумайте об этом так: если бы Format был методом экземпляра, вам нужно было бы объявить свою строку, а затем вызвать для нее Format. Это всегда будет двухэтапный процесс. Например. 1) строка strTemp; 2) strTemp.Format ("{0}", "Hello World"); Очиститель, чтобы сделать его статичным.
И семантически говоря, Replace и Substring имеют смысл как методы экземпляра. Форматирование могло быть любым, но использование более чистое, если оно статично.
Что ж, я думаю, вы должны быть довольно разборчивы в этом, но, как люди говорят, для String.Format имеет больше смысла быть статическим из-за подразумеваемой семантики. Учитывать:
"Hello {0}".Format("World"); // this makes it sound like Format *modifies*
// the string, which is not possible as
// strings are immutable.
string[] parts = "Hello World".Split(' '); // this however sounds right,
// because it implies that you
// split an existing string into
// two *new* strings.
Ваш второй пример действительно не подходит для таких вещей, как "a b c".Replace("a", "kitty"), IMO.
Может быть, дизайнеры .NET сделали это, потому что JAVA сделала это так ...
Обними и простирайся. :)
См .: http://discuss.techinterview.org/default.asp?joel.3.349728.40
AFAIK метод .NET старше, чем метод Java (Java получил его только в версии 5).
Хм? Java 1.5: java.sun.com/j2se/1.5.0/docs/api/java/lang/…
@jm: По странным маркетинговым причинам, наиболее известным Sun, Java 1.5 и Java 5 - одно и то же.
Первое, что я сделал при обновлении до VS2008 и C# 3, - это сделал
public static string F( this string format, params object[] args )
{
return String.Format(format, args);
}
Теперь я могу изменить свой код с
String.Format("Hello {0}", Name);
к
"Hello {0}".F(Name);
который я предпочел в то время. В настоящее время (2014 г.) я не беспокоюсь, потому что это просто еще одна проблема - постоянно добавлять это в каждый случайный проект, который я создаю, или связывать в какой-нибудь библиотеке с утилитами.
А почему дизайнеры .NET выбрали его? Кто знает. Это кажется полностью субъективным. Мои деньги либо на
На самом деле нет других уважительных причин, которые я могу найти
Я не думаю, что метод расширения - правильный путь. Я создаю интересный момент для читателя. Я считаю, что в C# мы застряли на статической версии.
Это субъективно, @Jakub. Для меня - я сразу понимаю, что это правильно, когда вижу скрученные брекеты.
Я не уверен, что такое «момент wft», но чем он отличается от любого другого использования методов расширения?
Я делаю это и помещаю его в пространство имен System, где находится String.
Строки .NET неизменяемы
Поэтому наличие метода экземпляра не имеет абсолютно никакого смысла.
String foo = new String();
foo.Format("test {0}",1); // Makes it look like foo should be modified by the Format method.
string newFoo = String.Format(foo, 1); // Indicates that a new string will be returned, and foo will be unaltered.
Это несовместимо с другими операциями String, которые являются методами экземпляра и возвращают новые строки. Insert, Normalize, PadLeft и т. д. Все работают точно так, как описано. Если Format является статическим, потому что строки неизменяемы, тогда все они также должны быть статическими, а это не так.
Неперегруженные, ненаследуемые статические методы (например, Class.b (a, c)), которые принимают экземпляр в качестве первой переменной, семантически эквивалентны вызову метода (например, ab (c)), поэтому команда разработчиков платформы сделала произвольный, эстетический выбор. (Предполагая, что он компилируется в тот же CIL, что и должен.) Единственный способ узнать это - спросить их, почему.
Возможно, они сделали это для того, чтобы две строки были близки друг к другу лексиграфически, т.е.
String.Format("Foo {0}", "Bar");
вместо
"Foo {0}".Format("bar");
Вы хотите знать, на что отображаются индексы; возможно, они думали, что часть ".Format" просто добавляет шума в середине.
Интересно, что метод ToString (по крайней мере, для чисел) противоположен: number.ToString («000») со строкой формата справа.
.NET Strings are Immutable
Therefore having an instance method makes absolutely no sense.
По этой логике у строкового класса не должно быть методов экземпляра, возвращающих измененные копии объекта, но при этом у него есть множество (Trim, ToUpper и т. д.). Более того, это делают и многие другие объекты фреймворка.
Я согласен с тем, что, если бы они сделали его методом экземпляра, Format, похоже, был бы плохим именем, но это не значит, что функциональность не должна быть методом экземпляра.
Почему не это? Это соответствует остальная частьплатформа .NET
"Hello {0}".ToString("Orion");
@ Джаред:
Non-overloaded, non-inherited static methods (like Class.b(a,c)) that take an instance as the first variable are semantically equivalent to a method call (like a.b(c))
Нет, это не так.
(Assuming it compiles to the same CIL, which it should.)
Это твоя ошибка. CIL производится иначе. Различие в том, что методы-члены не могут быть вызваны для значений null, поэтому CIL вставляет проверку значений null. Очевидно, что в статическом варианте этого не происходит.
Однако String.Format не разрешает нет значений null, поэтому разработчикам пришлось вставлять проверку вручную. С этой точки зрения вариант метода члена будет технически лучше.
Я думаю, это была очень полезная парадигма, когда кто-то (Python) сказал мне думать о функциях-членах как о статических функциях с явным объектом this в качестве первого элемента. Спасибо за вдумчивый отзыв о нулях! Кстати, перегрузка добавляет больше сложностей к эквивалентности статического / членского метода.
На самом деле я не знаю ответа, но подозреваю, что это как-то связано с аспектом прямого вызова методов для строковых литералов.
Если я правильно помню (я на самом деле не проверял это, потому что у меня нет под рукой старой IDE), в ранних версиях C# IDE были проблемы с обнаружением вызовов методов для строковых литералов в IntelliSense, и это сильно влияло на обнаруживаемость API. Если бы это было так, ввод следующего кода не помог бы вам:
"{0}".Format(12);
Если бы вас заставили ввести
new String("{0}").Format(12);
Было бы ясно, что не было преимуществ в том, чтобы сделать метод Format методом экземпляра, а не статическим методом.
Библиотеки .NET были разработаны множеством тех же людей, которые дали нам MFC, и, в частности, класс String очень похож на класс CString в MFC. MFC действительно имеет метод форматирования экземпляра (который использует коды форматирования стиля printf, а не стиль фигурных скобок .NET), что болезненно, потому что не существует такой вещи, как литерал CString. Итак, в кодовой базе MFC, над которой я работал, я много чего вижу:
CString csTemp = "";
csTemp.Format("Some string: %s", szFoo);
что болезненно. (Я не говорю, что приведенный выше код - отличный способ делать что-то даже в MFC, но похоже, что именно так большинство разработчиков проекта научились использовать CString :: Format). Исходя из этого наследия, я могу представить, что разработчики API снова пытались избежать подобной ситуации.
... Значит, он так спроектирован из-за некомпетентности дизайна IDE?
Тогда почему бы им не добавить форму "".Format позже, когда IDE стала лучше? Насколько я знаю, он ничего не ломает.
Это сделано во избежание путаницы с методами .ToString().
Например:
double test = 1.54d;
//string.Format pattern
string.Format("This is a test: {0:F1}", test );
//ToString pattern
"This is a test: " + test.ToString("F1");
Если Format был методом экземпляра для строки, это могло вызвать путаницу, поскольку шаблоны отличаются.
String.Format () - служебный метод для преобразования нескольких объектов в форматированную строку.
Метод экземпляра строки что-то делает с этой строкой.
Конечно, вы могли:
public static string FormatInsert( this string input, params object[] args) {
return string.Format( input, args );
}
"Hello {0}, I have {1} things.".FormatInsert( "world", 3);
Не знаю, зачем они это сделали, но это уже не имеет значения:
public static class StringExtension
{
public static string FormatWith(this string format, params object[] args)
{
return String.Format(format, args);
}
}
public class SomeClass
{
public string SomeMethod(string name)
{
return "Hello, {0}".FormatWith(name);
}
}
Это намного проще, ИМХО.
Другая причина для String.Format - это сходство с функцией printf из C. Предполагалось, что разработчикам на C будет проще переключать языки.
Большой целью разработки C# было сделать переход от C / C++ к нему как можно проще. Использование точечного синтаксиса в строковом литерале может показаться очень странным для кого-то, имеющего только опыт работы на C / C++, а форматирование строк - это то, что разработчик, вероятно, сделает в первый же день работы с языком. Поэтому я считаю, что они сделали его статичным, чтобы приблизить его к знакомой территории.
Я думаю, это потому, что Format принимает не строку как таковую, а «строку формата». Большинство строк эквивалентны таким вещам, как «Bob Smith» или «1010 Main St» или что у вас есть, а не «Hello {0}», обычно вы вставляете эти строки формата только тогда, когда пытаетесь использовать шаблон для создания другого string, как фабричный метод, и поэтому предоставляет себя статическому методу.
На данный момент это кажется лучшим ответом. Однако, если он должен быть `отличным от строки ', тогда зачем вообще помещать его в класс String ...
Нет ничего плохого в том, что он статичен; Причина, по которой я задумался об этом, заключалась в том, что он увеличивает длину по сравнению с
"my {0} string".Format(args)и усложняет переключение строкового литерала на форматированную строку. Не очень, но достаточно, чтобы использовать метод экземпляра.