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

时间:2016-07-19 21:35:10

标签: c# pointers memory

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

例如,我可以这样做:

HashTable hash = new HashTable(oldHashPointer);

3 个答案:

答案 0 :(得分:3)

是和否。这在C#中是不可能的,就像你描述它一样。例如,以下代码:

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

基本上就是你要做的,没有显式指针用法。 HashTable b不是一个单独的实体,它是指向存储在HashTable a中的引用的指针,它指向内存中的HashTable对象。

This MSDN article详细说明了这一点。页面引用:

  

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

但是,如果您尝试在进程之间共享对象(在本例中为HashTable),则可以查看Memory Mapped Files。这些基本上允许您将序列化对象写入驻留在内存中的虚拟“文件”,也可以从其他进程访问。但是,这仅适用于.NET 4.0或更高版本。

答案 1 :(得分:0)

这是可能的。怎么做:

  1. 你的班级必须标有 [StructLayout(LayoutKind.Sequential)]或(LayoutKind.Explicit)
  2. 您应该在非托管内存中分配所需的字节数var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof运算(T)));
  3. 将您的对象复制到该指针Marshal.StructureToPtr(obj,ptr, 假);
  4. 创建newObj并将数据复制到该对象Marshal.PtrToStructure(ptr,newObj);
  5. 不要忘记释放未管理的内存,否则会导致内存泄漏 Marshal.FreeHGlobal(PTR);
  6. <强>更新

    Code

    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);
                }
            }
    
        }
    }
    

答案 2 :(得分:-1)

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

ext10已经为它提供了一个很好的例子。因此,在hasttable a中添加内容,然后它也可用于b。因为它们是同一个实例。