C#相当于Python';s id()?

C#相当于Python';s id()?,c#,python,mutability,C#,Python,Mutability,有没有一个C#等价于Python的?如果没有,如何测试对象是否已更改?例如,在Python中,不可变对象: >>> s = "abc" >>> id(s) 11172320 >>> s += "d" >>> id(s) 18632928 一个可变的: >>> a = [1, 2, 3] >>> id(a) 11259656 >>> a += [4] >>&g

有没有一个C#等价于Python的?如果没有,如何测试对象是否已更改?例如,在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作为答案。

您可以使用以下函数:

确定指定的对象实例是否为同一实例

借用一下Python示例:

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

bool equal = object.ReferenceEquals(listA, listB);
List listA=新列表{1,2,3};
List listB=listA;
增加(4);
bool equal=object.ReferenceEquals(listA,listB);

equal
将是
true

你可以用它来测试对象身份。

我想你问错问题了。我的回答相当详细,但这里有一个简短的总结:

  • C#中没有直接等价于
    id
  • 您可以使用指针在C#中获取对象的地址,但不应使用此来解决问题
  • 该方法执行的操作与您尝试执行的操作类似
  • 您试图解决的问题在C语言中并不存在,就像在Python中一样
  • 您使用
    id
    的方式也不能解决Python中的问题

首先,我会在网上发帖,因为大多数人似乎都没有读过。请阅读这篇文章,因为我的其余答案只有在您知道
id
的作用时才有意义(不,它不会创建散列码):

返回对象的“标识”。这是一个整数(或长整数),保证该对象在其生存期内唯一且不变。两个生命周期不重叠的对象可能具有相同的id()值

CPython实现细节:这是对象的地址

C#没有与
id
等效的id,但可以通过在不安全模式下获取指向对象的指针来获取对象的地址

unsafe
{
     IntPtr x = (IntPtr)(&v);
     Console.WriteLine(x);
}
然而,你不应该在C#中这样做。您很少需要在C#中使用不安全的代码,如果您这样做,它很容易传播,因为调用您的代码的代码也变得不安全。还有其他不需要不安全代码的方法来解决您的问题。此外,在.NET中(与Python不同),垃圾收集器可以在内存中移动对象,因此,如果您希望在对象的整个生命周期中保持单个标识不变,那么内存地址对您没有任何用处。您应该创建一个只读属性,例如名为
Id


在C#中,不使用不安全代码的另一种方法是使用测试函数测试两个变量是否具有相同的引用。然而,你可能也不应该这样做。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
是一个非常糟糕的主意

摘要


不要这样做。

对象。GetHashcode()
可能值得一试。

wes,您的问题的正确答案,即。。与id()类似的函数是

object.GetHashCode()


根据设计,这通常会被覆盖,这样它将在相同的值上返回相同的值,这会忽略该点。强制调用已被重写的基方法无法干净地完成。您只需通过反射调用
InternalGetHashCode
即可非常轻松地获取对象的基本hashcode:
MethodInfo dynMethod=(typeof(object)).GetMethod(“InternalGetHashCode”,BindingFlags.NonPublic | BindingFlags.Static);int myHashCode=(int)dynMethod.Invoke(null,新对象[]{myObject})。也就是说,不同的对象可能有相同的哈希代码,所以这不是一个好主意。@wes:我认为您在示例中使用了不可变和可变反转。@calavera:为什么?可变对象可以就地修改,不可变对象需要一个新对象来表示修改。@wes:我不太懂python。我认为id()函数是一个散列函数,而不是一个对象引用/id/key。因此,如果示例(a)是不可变的,则哈希值不会改变,反之亦然。很明显,我是在错误的背景下思考的:)@wes:你的编辑让它更清晰了。这正是让我困惑的地方,我以为您关心的是相同内存中对象的值是否发生了变化,而不是是否创建了新对象。我很好奇您的Python id()用例。你为什么需要它?谢谢你为这个回复付出了这么多的努力。