简体   繁体   中英

How to know the memory adress of elements in list c#

I have:

        List<double> w = new List<double>();
        w.Add(1);
        w.Add(2);
        w.Add(1);
        w.Add(4);
        w.Add(5);
        w.Add(1);
        foreach (double num in w)
        {
           Console.WriteLine(num);
        }

Which writes

1 2 1 4 5 1

How do I print the memory location of each number, I tried &num, but get error.

There is now way to get a memory location in c#. Memory addresses are tabu in the .NET Framework, because the garbage collector may rearrange the stuff on the heap.

All you can use in your case is the list index. You could reformulate your loop like:

for (i = 0; i < w.Count; i++) {
    Console.WriteLine(w[i]);
}

If you would like to reference an item directly, then use a reference type like:

class MyDouble
{
    Public double Num { get; set; }
}

And then declare:

var w = new List<MyDouble>();
w.Add(new MyDouble{Num = 1});
var referenced = new MyDouble{Num = 2};
w.Add(referenced);
a.Add(...);
Console.WriteLine(referenced.Num);
referenced.Num = 7;

There is yet another reason why not to use a memory location. If you add items to the list, the internal array used to store the list items might be resized, ie a new array having the double size of the previous one will be created and the items will be copied into the new array. The reference trick shown in my last post, however, would still work.

If you're using P/Invoke and you want to pass a list of elements to a C function, you can use attributes in most cases to have the work done for you. Eg.

[DllImport("x.dll")]
extern void PassDoubleArray([MarshalAs(UnmanagedType.LPArray)]Double[] array);

If you have something a bit more complex and need to do it manually, the Marshal class has most of what you need to get it done.

First, allocate some unmanaged memory - enough to store your object or array, using Marshal.AllocHGlobal , which will give you an IntPtr . You can copy .NET primitives to and from the unmanaged memory by using Marshal.Copy. For non primitives, create structs and use Marshal.StructureToPtr to get an IntPtr for it. When you're done with the unmanaged memory, make a call to Marshal.FreeHGlobal to free it up.

eg, this will do the equivalent of the above attribute, but more long-winded.

[DllImport("x.dll")]
extern void PassDoubleArray(IntPtr array);

List<Double> vals = new List<Double>() { ... }
IntPtr unmanaged = Marshal.AllocHGlobal(vals.Length * sizeof(Double));
Marshal.Copy(vals.ToArray(), 0, unmanaged, vals.Length);
PassDoubleArray(unmanaged);
Marshal.FreeHGlobal(unmanaged);

You'll have to use unsafe code in order for this to work. See here for more details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM