C # эквивалент идентификатора Python ()? - PullRequest
4 голосов
/ 09 декабря 2010

Есть ли C # эквивалентный Python id () ? Если нет, как я могу проверить, изменился ли объект? Например, в Python неизменный объект:

>>> s = "abc"
>>> id(s)
11172320
>>> s += "d"
>>> id(s)
18632928

и изменчивый:

>>> a = [1, 2, 3]
>>> id(a)
11259656
>>> a += [4]
>>> id(a)
11259656

Редактировать - большинство ответов на данный момент о функциях / операторах сравнения , но меня больше интересуют сравниваемые значения. Изначально я не был уверен в этом, и я принимаю Object.ReferenceEquals в качестве ответа.

Ответы [ 5 ]

5 голосов
/ 09 декабря 2010

Вы можете проверить идентичность объекта с помощью Object.ReferenceEquals.

4 голосов
/ 09 декабря 2010

Я думаю, вы задаете не тот вопрос. Мой ответ довольно подробный, но вот краткое резюме:

  • В C # нет прямого эквивалента id.
  • Вы можете получить адрес объекта в C # с помощью указателей, но вы не должны использовать это для решения вашей проблемы.
  • Метод object.ReferenceEquals делает нечто похожее на то, что вы пытаетесь сделать.
  • Проблема, которую вы пытаетесь решить, на самом деле не существует в C # так же, как в Python.
  • То, как вы используете id, также не решает проблему в Python.

Во-первых, я отправлю из документации для идентификатора , так как большинство людей, кажется, не читали его. Пожалуйста do прочитайте это, потому что остальная часть моего ответа имеет смысл, только если вы знаете, что делает id (и нет, он не создает хеш-код):

Возвращает «идентичность» объекта. Это целое число (или длинное целое), которое гарантированно будет уникальным и постоянным для этого объекта в течение его жизни. Два объекта с неперекрывающимися временами жизни могут иметь одинаковое значение id ().

Сведения о реализации CPython: это адрес объекта.

C # не имеет эквивалента id, но можно получить адрес объекта, получив указатель на объект в небезопасном режиме.

unsafe
{
     IntPtr x = (IntPtr)(&v);
     Console.WriteLine(x);
}

Однако вы не должны делать это в C #. Вам очень редко нужно использовать небезопасный код в C #, и если вы это сделаете, он может легко распространяться, так как код, который вызывает ваш код, также становится небезопасным. Есть и другие способы решения вашей проблемы, которые не требуют небезопасного кода. Кроме того, в .NET (в отличие от Python) объекты могут перемещаться в памяти сборщиком мусора, поэтому, если вы хотите, чтобы один идентификатор оставался постоянным в течение всего времени существования объекта, адрес памяти вам не нужен. Вместо этого вы должны создать свойство только для чтения, которое называется, например, Id.


Альтернативный подход, который возможен в C # без использования небезопасного кода, состоит в проверке, имеют ли две переменные одинаковые ссылки, используя Object.ReferenceEquals. Однако вы, вероятно, не должны этого делать. C # не имеет такой же двусмысленности, как в Python. Чтобы установить переменную, указывающую на новый объект, вы используете оператор =. Вызов метода почти всегда не изменит ссылку, поэтому вам не следует об этом беспокоиться. В C # x += y; оператор (почти) эквивалентен x = x + y, и вы не можете изменить это, как в Python.


Кроме того, как уже упоминалось в документации, ваш пример Python имеет недостатки - id нельзя надежно использовать для проверки того, изменился ли объект. Пример:

>>> s='abc'
>>> id(s)
37822208
>>> s+='d'
>>> id(s)
61711680    # Changes
>>> s+='e'
>>> id(s)
61711680    # Oops... doesn't change even though the value changed.

В Python, если вам нужно сравнить два объекта, чтобы увидеть, являются ли они одним и тем же объектом (и вы, вероятно, не должны делать этого), тогда используйте is, что эквивалентно Python object.ReferenceEquals. id гарантированно будет постоянным только на протяжении всего срока службы объекта. Как показано выше, id равно , а не гарантированно будет различным для разных объектов. В частности, если один из объектов больше не существует, вы можете (и иногда будете) получать тот же id из-за повторного использования той же памяти. Таким образом, использование id действительно плохая идея.

Резюме

Не делай этого.

4 голосов
/ 09 декабря 2010

Ну, вы можете использовать функцию Object.ReferenceEquals():

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

Немного заимствуя пример Python:

List<int> listA = new List<int> { 1, 2, 3 };
List<int> listB = listA;
listA.Add(4);

bool equal = object.ReferenceEquals(listA, listB);

equal будет true.

3 голосов
/ 09 декабря 2010

object.GetHashcode() может стоить выстрел.

0 голосов
/ 09 декабря 2010

wes, правильный ответ на ваш вопрос, т. Е. Аналогичная функция для id ():

Object.GetHashCode ()

...