给定一个内存地址,是否可以从中创建一个对象

本文关键字:是否 一个对象 创建 地址 内存 一个 | 更新日期: 2023-09-27 17:57:40

在C#中,如果我创建了一个哈希表并获得了它存储的内存地址,我可以在程序的其他部分使用该内存地址来重新创建哈希表吗?

例如,我可以做一些类似的事情吗:

HashTable hash = new HashTable(oldHashPointer);

给定一个内存地址,是否可以从中创建一个对象

是和否。这在C#中是不可能的。例如以下代码:

HashTable a = new HashTable();
HashTable b = a;

本质上就是您要做的,而不使用显式指针。HashTable b不是一个单独的实体,它是指向存储在HashTable a中的引用的指针,指向内存中的HashTable对象。

MSDN的这篇文章对此进行了详细阐述。页面上的一句话:

指针类型不从对象继承,也不存在转换指针类型和对象之间。此外,装箱和拆箱不支持指针。

但是,如果您试图在进程之间共享对象(在本例中为HashTable),则可以查看内存映射文件。这些基本上允许您将序列化对象写入驻留在内存中的虚拟"文件"中,其他进程也可以访问该文件。但是,这仅在.NET 4.0或更新版本中可用。

这是可能的。如何做到:

  1. 你的课必须用[StructLayout(LayoutKind.Sequential)]或(LayoutKind.Explicit)
  2. 您应该在非托管内存中分配所需的字节量var ptr=Marshal.AllocHGlobal(Marshal.SizeOf(类型为(T)))
  3. 将对象复制到指针Marshal.StructureToPtr(obj,ptr,false)
  4. 创建newObj并将数据复制到该对象Marshal.PtrToStructure(ptr,newObj)
  5. 不要忘记释放非托管内存,否则会导致内存泄漏元帅.自由全球(ptr)

更新:

代码:

namespace MarhsalExampe
{
    using System;
    using System.Runtime.InteropServices;
    public class Program
    {
        [StructLayout(LayoutKind.Sequential)]
        public class SomeClass
        {
            public int IntProp { get; private set; }
            public string StrProp { get; private set; }
            public double DoubleProp { get; private set; }
            public bool BoolProp { get; private set; }
            public SomeClass() { }
            public SomeClass(int i, string s, double d, bool b)
            {
                IntProp = i;
                StrProp = s;
                DoubleProp = d;
                BoolProp = b;
            }
            public override string ToString()
            {
                return string.Format("HashCode: {0}, IntProp: {1}, StrProp: {2}, DoubleProp: {3}, BoolProp: {4}",
                    GetHashCode(), IntProp, StrProp, DoubleProp, BoolProp);
            }
        }
        public static void Main()
        {
            var obj = new SomeClass(42, "42", 42.0, true);
            Console.WriteLine("Obj is: {0}", obj);
            IntPtr ptr = IntPtr.Zero;
            try
            {
                // Allocate memory in unmanaged memory
                ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SomeClass)));
                // Copy data to ptr
                Marshal.StructureToPtr(obj, ptr, false);
                Console.WriteLine("Pointer: 0x{0:X}", ptr.ToInt64());
                // Create new object
                var newObj = new SomeClass();
                Console.WriteLine("newObj before updating from pointer: {0}", newObj);
                // Copy data to new object
                Marshal.PtrToStructure(ptr, newObj);
                Console.WriteLine("newObj after updating: {0}", newObj);
            }
            finally
            {
                if (ptr != IntPtr.Zero)
                    Marshal.FreeHGlobal(ptr);
            }
        }
    }
}

C#是基于引用的,这意味着您可以创建指向同一实例的多个变量。

ext10已经给出了一个很好的例子。所以在hasttable a中添加一些东西,那么它也可以用于b。因为他们是同一个例子。

相关文章: