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
作为答案。
答案 0 :(得分:5)
您可以使用Object.ReferenceEquals
测试对象标识。
答案 1 :(得分:4)
好吧,您可以使用Object.ReferenceEquals()
功能:
确定指定的Object实例是否是同一个实例。
稍微借用一下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
。
答案 2 :(得分:4)
我认为你问的是错误的问题。我的答案非常详细,但这里有一个简短的总结:
id
。object.ReferenceEquals
与您尝试的方法类似。id
的方式也无法解决Python中的问题。首先,我会从documentation for id发帖,因为大多数人似乎都没有读过它。请执行阅读本文,因为只有当您知道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
是一个非常糟糕的主意。
<强>摘要强>
不要这样做。
答案 3 :(得分:3)
object.GetHashcode()
可能值得一试。
答案 4 :(得分:0)
wes,你的问题的正确答案,即......与id()的类似函数是
object.GetHashCode()