2013-10-14 2 views
1

Простите меня, я не очень хорошо объясняю вопросы. я могу лучше объяснить мой вопрос по следующему примеру:Как я могу отличить два одинаковых объекта в C#?

string first = "hello"; 
string second = "Bye"; 
first = second; 

В приведенном выше примере, рассмотрим третью строку first=second.
Здесь я назначил объект вторым. Поскольку строки в C# неизменяемы i.e Каждый раз, когда вы назначаете новое значение для существующего строкового объекта, создается новый объект, и CLR стареет объект. (я прочитал это отсюда 1). Так просто это означает, что объект first в первой строке отличается от объекта first в третьей строке.
Итак, мой вопрос: как я могу доказать, что оба они разные?
i.e если он (строка) возможен в C, тогда я могу распечатать адрес обоих объектов до и после третьего оператора, чтобы доказать это.
Есть ли какой-либо метод доступа к этим адресам или другим альтернативам?

+1

Другими словами, вы хотите узнать адрес памяти 'first' (до и после). Мне это никогда не нужно, но, возможно, посмотрите http://stackoverflow.com/questions/588817/c-sharp-memory-address-and-variable? –

+0

«Каждый раз, когда вы назначаете новое значение существующему строковому объекту ...» - вы не назначаете существующий строковый объект. Вы назначаете * переменную *. Вам нужно различать переменные и объекты. –

ответ

5

Если вы хотели бы видеть физическое местоположение в памяти, вы можете использовать следующий (небезопасный) код.

private static void Main(string[] args) 
{ 
    unsafe 
    { 
    string first = "hello"; 

    fixed (char* p = first) 
    { 
     Console.WriteLine("Address of first: {0}", ((int)p).ToString()); 
    } 

    string second = "Bye"; 

    fixed (char* p = second) 
    { 
     Console.WriteLine("Address of second: {0}", ((int)p).ToString()); 
    } 

    first = second; 

    fixed (char* p = first) 
    { 
     Console.WriteLine("Address of first: {0}", ((int)p).ToString()); 
    } 
    } 
} 

Пример вывода на моей машине:

Address of first: 41793976 
Address of second: 41794056 
Address of first: 41794056 

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

Смотрите также:

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

Источник:String.Intern (MSDN)

1

* вы можете использовать .Equals() метод или метод HashCode() для сравнения *

+1

Я не думаю, что это означает OP. –

+0

спасибо, @ Mahmoud hashim, но я не могу использовать .Equals(), потому что один из них (т.е. объект в первой строке) был освобожден. И я не знаю, как использовать HashCode()? Можете ли вы PLZ дать какой-либо пример ? –

+1

@ Х.-код A.s.Bhullar не даст вам ничего другого, кроме того, что вы уже знаете (а именно: '' second "! =" First "') –

3

Я считаю, что вы хотите метод ReferenceEquals. Его можно использовать для проверки того, являются ли два экземпляра объекта одинаковыми, т. Е. Ссылаются на один и тот же объект.

1

Если вы должны сравнить основные памяти-адреса, следующий небезопасный код может помочь вам (непроверенный):

string first = "hello"; 


GCHandle handle = GCHandle.Alloc(first, GCHandleType.Pinned); 
IntPtr address = handle.AddrOfPinnedObject(); 


string second = "Bye"; 
first = second; 


GCHandle handle = GCHandle.Alloc(first, GCHandleType.Pinned); 
IntPtr address2 = handle.AddrOfPinnedObject(); 

if (address != address2) 
{ 
    // memory addresses are different afterwards 
} 
1

Вы поняли, что вы читали. Да, строки неизменны. Это означает, что вы не можете изменить существующую строку.Это не работы:

string x = "Hello"; 
x[3] = 'q'; 

Когда вы конкатенации строк, вы получите новый:

string a = "a"; 
string b = "b"; 
string c = a+b; // You get a new string and a and b are unchanged. 

Даже если вы самостоятельно конкатенации, вы получаете новую строку:

string a = "a"; 
a += "b"; // The same as a = a + "b" and yields a new string. 

Но присваивание переменной (или переходя к функции или возврата из функции, и т.д.) не создает новую строку.

Строки являются «ссылочными типами». Это означает, что эта переменная:

string a = "Hello"; 

Это просто ссылка на строку. Делать это:

string b = a; 

Просто присваивает ссылку к переменной. Он не изменяет строку.

Или, если положить его в терминах C: ссылочные переменные указатели к объектам. Рассмотрим:

string a = "Hello"; // a now points to the string object 
string b = a; // b now points to the same object. 

Что неизменность означает, что вы не можете изменить память о том, что указатель указывает на (сама строка объекта). Но переменная указателя столь же изменчива, как и всегда. Вы можете присвоить ему другой адрес.

Чтобы вернуться к исходному примеру:

string first = "hello"; // Allocates memory for "hello" and points first to it. 
string second = "Bye"; // Allocates memory for "Bye" and points second to it. 
first = second;   // Assigns the address of second to first. 

В конце концов, как first и second указывают на тот же адрес, который является адресом строки Bye. Память строки hello теперь не найдена (нет указателей на нее, она недоступна). Сборщик мусора вернет его через некоторое время.

Добавлено: Еще одна аналогия с С. строковые переменные .NET несколько, как это:

const char* str; 

Это указатель на константу. Вы можете изменить указатель, но вы не можете изменить материал, на который он указывает.

Добавлено 2: Вы должны прочитать о типах значений и типах ссылок в .NET. Вкратце, типы значений - все типы struct, а ссылочные типы - все типы class. Типы значений копируются при назначении (или когда они передаются/возвращаются из функции); ссылочные типы - указатели.

Обратите внимание, что здесь есть одна неинтуитивная деталь. Класс object, который является базовым классом типов ALL, является ссылочным типом. Однако типы значений наследуются от него, и вы можете присвоить тип значения переменной типа object. Если вы это сделаете, это вызовет что-то, называемое boxing, и оно включает в себя создание копии значения, поэтому это немного дорогая операция.

1

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

для получения адрес строки следуют за этим link

может это поможет вам

Смежные вопросы