为了账号安全,请及时绑定邮箱和手机立即绑定

C#中对象的内存地址

C#中对象的内存地址

波斯汪 2019-10-18 10:14:01
我前段时间编写了一个函数(针对.NET 3.5),现在我已升级到4.0我无法正常工作。该函数是:public static class MemoryAddress{    public static string Get(object a)    {        GCHandle handle = GCHandle.Alloc(a, GCHandleType.Pinned);        IntPtr pointer = GCHandle.ToIntPtr(handle);        handle.Free();        return "0x" + pointer.ToString("X");    }}现在,当我调用它时-MemoryAddress.Get(new Car(“ blue”))public class Car{    public string Color;    public Car(string color)    {        Color = color;    }}我得到错误:对象包含非原始或不可复制的数据。为什么它不起作用了?现在如何获取被管理对象的内存地址?
查看完整描述

3 回答

?
皈依舞

TA贡献1851条经验 获得超3个赞

代替此代码,您应该调用GetHashCode(),它将为每个实例返回一个(希望的)唯一值。


您也可以使用ObjectIDGeneratorclass,它保证是唯一的。


查看完整回答
反对 回复 2019-10-18
?
月关宝盒

TA贡献1772条经验 获得超5个赞

如果您确实不需要内存地址,而是需要一些方法来唯一标识托管对象,则有更好的解决方案:


using System.Runtime.CompilerServices;


public static class Extensions

{

    private static readonly ConditionalWeakTable<object, RefId> _ids = new ConditionalWeakTable<object, RefId>();


    public static Guid GetRefId<T>(this T obj) where T: class

    {

        if (obj == null)

            return default(Guid);


        return _ids.GetOrCreateValue(obj).Id;

    }


    private class RefId

    {

        public Guid Id { get; } = Guid.NewGuid();

    }

}

这是线程安全的,并且在内部使用弱引用,因此不会有内存泄漏。


您可以使用任何您喜欢的密钥生成方式。我在Guid.NewGuid()这里使用它是因为它简单且线程安全。


更新资料

我继续创建了一个Nuget包Overby.Extensions.Attachments,其中包含一些用于将对象附加到其他对象的扩展方法。有一个扩展名为GetReferenceId(),可以有效地执行此答案中的代码显示的内容。


查看完整回答
反对 回复 2019-10-18
  • 3 回答
  • 0 关注
  • 1401 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信