Почему тип строки ведет себя как тип значения? - PullRequest
0 голосов
/ 05 октября 2018

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

Моя проблема:

Я скопировал строковую переменную в другую, и я изменил значение первой, однако вторая имеет то же значение.Я не понял эту проблему.Даже если тип строки является ссылочным типом, второй тип не изменяется.Также я попробовал метод бокса, но не смог получить результат.

Я читал эту статью Почему в C # тип String является ссылочным типом, который ведет себя как тип значения? , однако я все еще получаю искаженную информацию.

И это мой код:

        string my_text1 = "My text 1";
        string my_text2 = my_text1;

        my_text1 = "My text 2";
        Console.WriteLine("First text --> " + my_text1); // It prints My text 2
        Console.WriteLine("Second text -->" + my_text2); // It prints My text 1(I want it prints "My text 2" too)

        string text_1 = "Example 1";
        object text_2 = text_1;

        text_1 = "Example 2";
        Console.WriteLine("First example --> " + text_1); // It prints Example 2
        Console.WriteLine("Second example -->" + text_2);// It prints Example 1

Ответы [ 3 ]

0 голосов
/ 05 октября 2018

Поскольку строки являются неизменяемым ссылочным типом.

Неизменяемый тип - это тип объекта, данные которого нельзя изменить после его создания.Есть много преимуществ неизменяемых строк.Это повышает эффективность и безопасность во время выполнения (процесс не может изменить строку, введя что-то).Вы можете прочитать для подробного объяснения.

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

Вы можете использовать изменяемый StringBuilder.

StringBuilder my_text1 = new StringBuilder("My text 1");
StringBuilder my_text2 = new StringBuilder("My text 2");

my_text1 = my_text2;
Console.WriteLine("First text --> " + my_text1); 
Console.WriteLine("Second text -->" + my_text2);

В этом примере выше вы получите «Мой текст 2» для обоих выражений.

0 голосов
/ 05 октября 2018

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

Таким образом, при присвоении переменнойвы изменяете содержимое этой переменной 1 .Само по себе это не будет иметь видимых эффектов для любой другой переменной.

Когда вы часто будете замечать разницу между типами значений и ссылочными типами, это когда вы мутируете данные .Здесь разница заметна, потому что, когда вы изменяете данные типа значения, вы делаете это через определенную переменную, и вы изменяете копию этой переменной данных .Принимая во внимание, что, когда вы изменяете данные для ссылочного типа, вы изменяете данные и все переменные, которые ссылаются на ту же копию данных , будут иметь видимое изменение для них.

Но, так как string не имеет никаких (без уловок отражения или небезопасного кода) изменяемых полей или методов мутации, вы никогда не сможете наблюдать такие мутации с string переменными.


1 Здесь я имею в виду локальные переменные и поля.Другие формы присваивания (например, свойствам) могут запускать произвольный код, и, конечно, они могут иметь другие видимые побочные эффекты.

0 голосов
/ 05 октября 2018

, как указывал Damien_The_Unbeliever, назначение всегда изменяет эту переменную и не влияет на предыдущие переменные.

Рассмотрим следующий пример с классами

class Program
{
    static void Main(string[] args)
    {
        Foo my_text1 = new Foo("My text 1");
        Foo my_text2 = my_text1;

        my_text1 = new Foo("My text 2");
        Console.WriteLine("First text --> " + my_text1); // It prints My text 2
        Console.WriteLine("Second text -->" + my_text2); // It prints My text 1

        Foo text_1 = new Foo("Example 1");
        object text_2 = text_1;

        text_1 = new Foo("Example 2");
        Console.WriteLine("First example --> " + text_1); // It prints Example 2
        Console.WriteLine("Second example -->" + text_2);// It prints Example 1
    }
}

class Foo
{
    private readonly string _name;

    public Foo(string name)
    {
        _name = name;
    }

    public override string ToString()
    {
        return _name;
    }
}

, строка не совсем работает в этомкстати, но это дает вам представление о том, что имел в виду Damien_The_Unbeliever

Если вы хотите, чтобы переменная действовала как ссылка, вы должны добавить ключевое слово ref

string my_text1 = "My text 1";
ref string my_text2 = ref my_text1;

my_text1 = "My text 2";
Console.WriteLine("First text --> " + my_text1); // It prints My text 2
Console.WriteLine("Second text -->" + my_text2); // It prints My text 2
...