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

Какова цель литья в "объектный" тип?

Я нашел код на веб-сайте, который выглядит следующим образом.

 string a = "xx";
 string b = "xx";
 string c = "x";
 string d = String.Intern(c + c);

 Console.WriteLine((object)a == (object)b); // True
 Console.WriteLine((object)a == (object)d); // True

Вот, какова цель повторного включения в тип объекта, так как a, b, d сами являются объектами строки?

4b9b3361

Ответ 1

Компилятор С# попытается получить все константные строки во время компиляции. Это называется интернирование строк. Поэтому после генерирования кода a и b ссылки в ту же строку, которая содержит "xx".

Вы можете проверить это, сравнив их ссылки (отбрасывая их на объект и выполняйте проверку равенства или используйте object.ReferenceEquals). Имейте в виду, что оператор == для строк сравнивает свои значения, а не их ссылки.

Еще одна вещь, которая стоит упомянуть в том, что строки неизменяемы в .NET.

string a = "xx";
string b = "x" + "x"; // String interning here
string c = string.Join("", new[] { "x", "x" }); // No interning here because it is evaluated at runtime

Console.WriteLine((object)a == (object)b); // True. Reference check
Console.WriteLine(a == b); // True. Value check

Console.WriteLine((object)a == c); //False. Reference check. Described below
Console.WriteLine(a == c); // True. Value check

Итак, почему Console.WriteLine((object)a == c); делает контрольную проверку? Поскольку компилятор выберет оператор == на объекте, который проверяет ссылочное равенство.


Таким образом, вся цель каста для объекта в вашем вопросе - проверить, работает ли интернирование строк или нет. Предполагая, что во время компиляции не происходит интернирование.

 string a = "xx";
 string b = "xx";
 string c = "x";
 string d = String.Intern(c + c);

Затем Console.WriteLine((object)a == (object)b); будет печатать "False", потому что a и b являются ссылками для двух различных строк в памяти, оба из которых выглядят как "хх".

Ответ 2

Добавление к предоставленному ответу: string (ссылка С#)

Класс System.String - это неизменный ссылочный тип, указанный в библиотеку классов .NET Framework. Этот класс создает новую строку объект внутри для любого действия манипуляции строкой. Содержание объекты этого типа не изменяются, хотя синтаксис делает это как будто содержимое может быть изменено. Кроме того, строка используется как хэш-таблица для вычисления значений хэша, чтобы избежать риска повреждение структуры хэш-данных.

Пример:

string a = "hello";
string b = "h";

// Append to contents of 'b'
b += "ello";
// When you set the variable b value to "hello", 
// this would result in changing the pointer
// to the object in the HEAP the variable "a" is already pointing to
// Result would be: (reference of a == reference of b) --> TRUE
// b = "hello"; 

Console.WriteLine(a == b);                       // value comparison
Console.WriteLine((object)a == (object)b);       // reference comparison
Console.WriteLine (object.ReferenceEquals(a,b)); // reference comparison without casting

Результат:

True
False
False

Объяснение

Это создаст новый объект:

string a = "hello";

Это создаст другой объект:

string b = "h"; 

Это создаст еще один объект:

b += "ello";

Следующее создаст ссылку на существующий объект, точнее, указывает на тот же объект, который переменная "a" указывает на → "Привет".

string c = "hello"; 
Console.WriteLine (object.ReferenceEquals(a,c)); // --> TRUE

Строки неизменяемы - содержимое строкового объекта не может быть изменено после создания объекта, хотя синтаксис делает это как будто вы можете это сделать. Например, когда вы пишете этот код, компилятор фактически создает новый строковый объект для хранения нового последовательность символов, а новый объект присваивается b. строка "h" затем имеет право на сбор мусора.

Ответ 3

В С# используется токен == для представления трех различных операторов: перегружаемый оператор проверки равенства (используемый для типов классов или типов значений, если существуют перегрузки для конкретных типов), неперегружаемая эталонная проверка подлинности (который требует, чтобы оба операнда были классами, и требует, чтобы типы не были взаимно исключающими) и оператор с нулевой проверкой (который можно использовать с любым типом класса, типом значения NULL или дженериками, которые могут быть одним из вышеперечисленных). Хотя большинство форм перегрузки определены единообразно на языках .NET, использование одного оператора для всех трех видов равенства не является. Другие языки, такие как VB.NET, используют другой токен для первой формы (например, в VB.NET, выражение (x = y) использует перегрузку проверки равенства, если оно определено, или генерирует синтаксическую ошибку, если нет; (x Is y) проверяет, x и y идентифицируют один и тот же экземпляр объекта без учета того, существует ли перегруженный оператор равенства).

Цель приведения к Object заключается в обеспечении того, чтобы токен == интерпретировался как представляющий оператор проверки ссылочной идентификации, а не перегружаемый оператор равенства; такие приведения нужны только из-за того, как C реализует оператор == и не понадобится на других языках, таких как VB.NET.

Ответ 4

Комментарий с кодом

Итак, если значения "xx" были установлены во время выполнения все с тем же значением "xx", тогда вы получили бы другой результат false, поскольку у компилятора не было возможности сделать оптимизацию во время выполнения, хотя это один и тот же код и входные значения в обоих случаях, разные результаты для предварительно скомпилированных версий vs.

private void button1_Click(object sender, EventArgs e)
{
    string a = "xx";
    string b = "xx";
    string c = "x";
    string d = String.Intern(c + c);

    Console.WriteLine((object)a == (object)b); // True
    Console.WriteLine((object)a == (object)d); // True
}

private void button2_Click(object sender, EventArgs e)
{
    string a = textBox1.Text; //type in xx at runtime
    string b = textBox2.Text; //type in xx at runtime
    string c = textBox3.Text; //type in just "x" at runtime
    string d = String.Intern(c + c);

    Console.WriteLine((object)a == (object)b); // False with runtime values that have the same value
    Console.WriteLine((object)a == (object)d); // False 
    Console.WriteLine(a == d); // True - the Equals Operator of the string works as expected still 
}