Подтвердить что ты не робот

Почему String.Format статичен?

Сравнение

String.Format("Hello {0}", "World");

с

"Hello {0}".Format("World");

Почему дизайнеры .Net выбрали статический метод над методом экземпляра? Как вы думаете?

4b9b3361

Ответ 1

Я действительно не знаю ответа, но я подозреваю, что он имеет какое-то отношение к аспекту вызова методов в строковых литералах напрямую.

Если я правильно помню (я действительно не проверял это, потому что у меня нет старой среды IDE), ранние версии С# IDE имели проблемы с обнаружением вызовов методов против строковых литералов в IntelliSense, и это имеет большое влияние о возможности обнаружения API. Если это так, введите следующее, не окажет вам никакой помощи:

"{0}".Format(12);

Если вы были вынуждены ввести

new String("{0}").Format(12);

Было бы ясно, что не было никакого преимущества для того, чтобы метод Format использовал метод экземпляра, а не статический метод.

Библиотеки .NET были разработаны многими теми же людьми, которые дали нам MFC, и, в частности, класс String имеет сильное сходство с классом CString в MFC. У MFC есть метод форматирования экземпляра (который использует коды форматирования стиля печати, а не стиль фигурной скобки .NET), что является болезненным, потому что нет такой вещи, как литерал CString. Поэтому в кодовой базе MFC, над которой я работал, я вижу много всего:

CString csTemp = "";
csTemp.Format("Some string: %s", szFoo);

что является болезненным. (Я не говорю, что вышеприведенный код - отличный способ сделать что-то даже в MFC, но похоже, что большинство разработчиков проекта узнали, как использовать CString:: Format). Исходя из этого наследия, я могу представить, что дизайнеры API пытались избежать такой ситуации снова.

Ответ 2

Поскольку метод Format не имеет ничего общего с текущим значением строки.

Это верно для всех строковых методов, потому что строки .NET неизменяемы.

Если он был нестационарным, для начала вам понадобится строка.

Это: строка формата.

Я считаю, что это всего лишь еще один пример многих недостатков дизайна на платформе .NET(и я не имею в виду это как пламя, я по-прежнему считаю, что платформа .NET превосходит большинство других фреймворков).

Ответ 3

Ну, я думаю, вы должны быть довольно особенными в этом вопросе, но, как говорят люди, для 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.

Ответ 4

Первое, что я сделал, когда мне нужно было перейти на VS2008 и С# 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 выбрали его? Кто знает. Это кажется полностью субъективным. Мои деньги находятся на

  • Копирование Java
  • Парень, который писал его в то время, субъективно любил его больше.

На самом деле нет других веских причин, по которым я могу найти

Ответ 5

Я думаю, что это потому, что Format не берет строку как таковую, а "строку формата". Большинство строк равны таким вещам, как "Bob Smith" или "1010 Main St", или что у вас есть, а не "Hello {0}", как правило, вы помещаете эти строки только в том случае, когда вы пытаетесь использовать шаблон для создания другого string, как метод factory, и поэтому он сам придает статическому методу.

Ответ 6

Я думаю, это потому, что это метод создателя (не уверен, есть ли лучшее имя). Все, что он делает, это взять то, что вы ему даете, и вернуть один строковый объект. Он не работает с существующим объектом. Если он был нестационарным, для начала вам понадобится строка.

Ответ 7

Поскольку метод Format не имеет ничего общего с текущим значением строки. Значение строки не используется. Он берет строку и возвращает ее.

Ответ 9

Строки .NET неизменяемы
Поэтому наличие метода экземпляра абсолютно не имеет смысла.

В этой логике класс string не должен иметь методов экземпляра, которые возвращают измененные копии объекта, но у него много (Trim, ToUpper и т.д.). Кроме того, многие другие объекты в рамках делают это тоже.

Я согласен, что если они должны были сделать его методом экземпляра, Format кажется, что это будет плохое имя, но это не значит, что функциональность не должна быть методом экземпляра.

Почему не это? Это согласуется с остальные .NET framework

"Hello {0}".ToString("Orion");

Ответ 10

Методы экземпляра хороши, если у вас есть объект, который поддерживает какое-либо состояние; процесс форматирования строки не влияет на строку, в которой вы работаете (read: не изменяет ее состояние), она создает новую строку.

С помощью методов расширения вы можете теперь использовать свой торт и съесть его (т.е. вы можете использовать последний синтаксис, если он поможет вам лучше спать ночью).

Ответ 11

Мне кажется, что лучше использовать String.Format, но я мог видеть, что нужно иметь нестационарную функцию, когда у вас уже есть строка, хранящаяся в переменной, которую вы хотите "форматировать".

В стороне все функции класса string не действуют на строку, но возвращают новый строковый объект, потому что строки неизменяемы.

Ответ 12

@Jared:

Неперегруженные, не наследуемые статические методы (например, Class.b(a, c)), которые принимают экземпляр в качестве первой переменной, семантически эквивалентны вызову метода (например, a.b(c))

Нет, это не так.

(Предположим, что он скомпилирован с тем же CIL, что и должен.)

Это твоя ошибка. Выпуск CIL отличается. Различие заключается в том, что методы-члены не могут быть вызваны значениями null, поэтому CIL вставляет проверку с значениями null. Это явно не делается в статическом варианте.

Однако String.Format не позволяет использовать значения null, поэтому разработчикам необходимо вручную вставить проверку. С этой точки зрения вариант метода участника был бы технически превосходным.

Ответ 13

Это во избежание путаницы с методами .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");

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

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);

Ответ 14

Я не знаю, почему они это сделали, но это уже не имеет значения:

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);
    }
}

Это намного проще, ИМХО.

Ответ 15

Еще одна причина для String.Format - это сходство с функцией printf от C. Предполагалось, что разработчики C имеют более легкие языки переключения времени.

Ответ 16

Большая цель дизайна для С# заключалась в том, чтобы сделать переход от C/С++ к нему максимально простым. Использование точечного синтаксиса в строковом литерале было бы очень странным для кого-то, у которого есть только фон C/С++, а форматирование строк - это то, что разработчик, вероятно, сделает в первый день с языком. Поэтому я считаю, что они сделали его статичным, чтобы приблизить его к привычной территории.

Ответ 17

Я не вижу ничего плохого в том, что он статичен.

Семантика статического метода, похоже, имеет для меня гораздо больше смысла. Возможно, это потому, что это примитив. Когда примитивы используются часто, вы хотите сделать код утилиты для работы с ними как можно более легким. Кроме того, я думаю, что семантика намного лучше с String.Format над "MyString BLAH BLAH {0}". Формат...

Ответ 18

Я еще не пробовал, но вы можете сделать метод расширения для того, что хотите. Я бы этого не сделал, но я думаю, что это сработает.

Также я нахожу String.Format() больше в соответствии с другими статическими статическими методами, такими как Int32.Parse(), long.TryParse() и т.д.

Вы облака также просто используете StringBuilder, если хотите нестатический формат. StringBuilder.AppendFormat()

Ответ 19

String.Format должен быть статическим методом, потому что строки являются неизменяемыми. Создание метода экземпляра подразумевает, что вы можете использовать его для "форматирования" или изменения значения существующей строки. Этого вы не можете сделать, и создание метода экземпляра, возвращающего новую строку, не имеет смысла. Следовательно, это статический метод.

Ответ 20

Неперегруженные, не наследуемые статические методы (например, Class.b(a, c)), которые принимают экземпляр в качестве первой переменной, семантически эквивалентны вызову метода (например, ab (c)), поэтому команда платформы сделала произвольный, эстетический выбор. (Предполагая, что он скомпилируется с тем же CIL, каким он должен.) Единственный способ узнать, будет ли это спрашивать, почему.

Возможно, они сделали это, чтобы обе строки были близки друг к другу лексиграфически, то есть

String.Format("Foo {0}", "Bar");

вместо

"Foo {0}".Format("bar");

Вы хотите знать, к каким индексам сопоставляются; возможно, они думали, что часть ".Format" просто добавляет шум посередине.

Интересно, что метод ToString (по крайней мере для чисел) является противоположным: number.ToString( "000" ) с строкой формата справа.

Ответ 21

String.Format принимает по крайней мере одну строку и возвращает другую строку. Нет необходимости изменять строку формата, чтобы возвращать другую строку, поэтому делать это не имеет смысла (игнорируя ее форматирование). С другой стороны, было бы не так много, чтобы сделать String.Format функцией-членом, за исключением того, что я не думаю, что С# допускает функции const-члена, такие как С++. [Пожалуйста, исправьте меня и этот пост, если это произойдет.]

Ответ 22

Строки .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.