строки в .net меняются?? есть какой-то баг?

Я написал функцию Reverse, чтобы перевернуть строку в .net, используя указатели в небезопасном контексте. Мне это нравится.

Я придаю «приветствую» и «х» одинаковое значение. Я наоборот приветствую, к моему удивлению, x тоже переворачивается.

using System;

class Test{

    private unsafe static void Reverse(string text){
        fixed(char* pStr = text){
            char* pBegin = pStr;
            char* pEnd = pStr + text.Length - 1;
            while(pBegin < pEnd){
                char t = *pBegin;
                *pBegin++ = *pEnd;
                *pEnd-- = t; 
            }
        }
    }

    public static void Main(){
        string greet = "Hello World";
        string x = "Hello World";
        Reverse(greet);
        Console.WriteLine(greet);
        Console.WriteLine(x);
    }
}

person Pritesh    schedule 19.04.2012    source источник
comment
Надеюсь, у вас действительно есть веская причина использовать указатели в C#...   -  person jrummell    schedule 19.04.2012
comment
@jrummell пытался добиться максимальной производительности...   -  person Pritesh    schedule 19.04.2012
comment
Если вы не протестировали свое приложение и не подтвердили, что этот фрагмент кода работает медленно, не беспокойтесь об оптимизации такого рода.   -  person jrummell    schedule 19.04.2012
comment
@jrummell в крайнем случае, надеюсь, не требуется!   -  person Pritesh    schedule 19.04.2012


Ответы (1)


В этом нет ничего странного. Вы видите интернирование. Если вы пишете:

Console.WriteLine(object.ReferenceEquals(greet, x));

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

Из спецификации С# 4, раздел 2.4.4.5:

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

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

person Jon Skeet    schedule 19.04.2012
comment
но я создал 2 экземпляра.. странно. - person Pritesh; 19.04.2012
comment
@Pritesh: Нет, ты этого не сделал. Вы объявили две переменные и использовали один и тот же строковый литерал для обеих, что означает, что у вас есть две переменные, которые ссылаются на один и тот же строковый объект. - person Jon Skeet; 19.04.2012
comment
@Pritesh: Нет, я показал, что это заданное поведение. Ошибка заключается в том, что вы изменяете строковые объекты, которые обычно считаются неизменяемыми. - person Jon Skeet; 19.04.2012
comment
пытался придумать наш собственный класс stringbuilder. Кажется, нужно подумать о решении в безопасном контексте... Мне было интересно, являются ли строки неизменяемыми, как компилятор .net/время выполнения позволил мне изменить его ??? - person Pritesh; 19.04.2012