Avatar ·

В чем разница между String и string в C#? Это разные типы?

Всем привет! Начал изучать C# недавно, и меня смущает один момент. В разных примерах кода я вижу, что строки объявляются по-разному: кто-то пишет `string name = "John";`, а кто-то `String name = "John";`. И то, и другое работает, IntelliSense не ругается. Но ведь это же разные названия? Может быть, `String` — это класс из .NET, а `string` — какой-то примитивный тип? Или это одно и то же? Я попробовал написать такой код: ```csharp string a = "Hello"; String b = "World"; Console.WriteLine(a.GetType()); // System.String Console.WriteLine(b.GetType()); // System.String Console.WriteLine(a == b); // True ``` Оба раза выводится `System.String`, и сравнение работает. Но если это одно и то же, зачем тогда два названия? Может быть, есть какая-то разница в производительности или в том, как они работают с памятью? Или это просто вопрос стиля? Буду благодарен за подробное объяснение, а то я боюсь написать что-то неправильно в реальном проекте. <<>>

Краткий ответ: это одно и то же. string — это просто псевдоним (alias) для System.String.

В C# нет никакой разницы между string и String. Это два имени для одного и того же типа — System.String. Ключевое слово string — это просто удобный псевдоним, который вводится языком C#, чтобы сделать код более читаемым и похожим на другие C-подобные языки.

Точно так же работают и другие встроенные псевдонимы:

  • int = System.Int32
  • long = System.Int64
  • bool = System.Boolean
  • double = System.Double

Это легко проверить. Следующий код скомпилируется и будет работать идеально:

using System;

class Program
{
    static void Main()
    {
        // Оба объявления идентичны
        string s1 = "Hello";
        String s2 = "World";

        // Проверяем типы
        Console.WriteLine(s1.GetType() == typeof(string));  // True
        Console.WriteLine(s2.GetType() == typeof(String));  // True
        Console.WriteLine(s1.GetType() == typeof(String));  // True
        Console.WriteLine(s2.GetType() == typeof(string));  // True

        // Сравнение значений
        Console.WriteLine(s1.Equals(s2)); // False (разные строки)

        // Но можно даже смешивать:
        String result = s1 + " " + s2;
        Console.WriteLine(result); // Hello World
    }
}

Когда использовать string, а когда String?

На практике существуют негласные правила (соглашения), которых придерживается большинство C#-разработчиков:

  • Для объявления переменных, параметров и полей используйте string (строчными буквами). Это стандарт, принятый в сообществе и в официальных руководствах Microsoft.
  • Для вызова статических методов класса String используйте String (с заглавной буквы). Например: String.Format(), String.Join(), String.IsNullOrEmpty(). Хотя технически можно писать и string.Format(), это выглядит необычно.

Пример правильного стиля:

string name = "Анна";
string greeting = String.Format("Привет, {0}!", name);

if (String.IsNullOrEmpty(name))
{
    Console.WriteLine("Имя не указано");
}

Почему так сделано?

Это дизайнерское решение языка C#. Ключевые слова вроде string, int, bool были введены, чтобы:

  • Сделать синтаксис более лаконичным (сравните string x и System.String x).
  • Обеспечить единообразие с языками C/C++/Java, где также есть string (хотя там это не псевдоним, а отдельный тип).
  • Избавить разработчика от необходимости писать using System; для использования базовых типов.

Важно: string — это ссылочный тип (как и System.String), а не значимый. Несмотря на то, что строки ведут себя как значимые типы при сравнении (по значению, а не по ссылке), они хранятся в куче и являются неизменяемыми (immutable).

Итог: используйте string для переменных и String для статических методов. Но если вы перепутаете — компилятор не накажет. Главное — соблюдать единообразие в рамках одного проекта.

<<>>

Дополнение: как это работает под капотом?

Когда вы пишете string s = "test";, компилятор C# на этапе компиляции преобразует string в System.String. В IL-коде (промежуточном языке) вы никогда не увидите string — только System.String. Это чисто синтаксический сахар.

Аналогия: в C# есть ключевое слово var, которое тоже заменяется на конкретный тип на этапе компиляции. Но в отличие от var, string — это не вывод типа, а жестко заданный псевдоним.

Есть один нюанс, о котором стоит знать: если вы работаете в среде, где нет using System; (например, в некоторых старых версиях Unity или в очень минималистичных проектах), то String без указания пространства имен не скомпилируется, а string будет работать всегда, так как ключевые слова языка не требуют импорта пространств имен.

Пример:

// Этот код НЕ скомпилируется без using System;
// String s = "test";

// А этот скомпилируется всегда
string s = "test";

Поэтому использование string считается более безопасным и переносимым. Но на практике в современных проектах вы почти всегда имеете using System; в начале файла, так что оба варианта равнозначны.