3
public class Test
{
    int m_iInt1; // 0x0
    int m_iInt2; // 0x4
}

Is this possible in C# to access a field like this:

var inst = new Test();
unsafe 
{
    var reference = __makeref(inst);
    int int1 = *(int*)(reference + 0x0);
}

How can I accomplish this?

MethodMan
  • 18,625
  • 6
  • 34
  • 52
Konrad
  • 6,385
  • 12
  • 53
  • 96
  • 5
    You can't do that. What problem are you trying to solve? – SLaks Dec 01 '17 at 17:24
  • I want to access the value by it's offset after it is JITted and I believe it's possible. I need a pointer to unmanaged memory of the instance. I just looked for a way to avoid using reflection. Motivation for this is performance. – Konrad Dec 01 '17 at 17:25
  • 1
    Why do you want to do that? In general you shouldn't muck around with private fields but reflection would be the way to go if you absolutely have to. – juharr Dec 01 '17 at 17:27
  • @juharr I just wonder if it's possible. In C++ it's possible. It's more like a hack I'm trying to do from managed code. – Konrad Dec 01 '17 at 17:28
  • 5
    That's the type of shortcut in C++ that would get people into hard to debug problems and one of the things that C# tries to avoid with it's design. – juharr Dec 01 '17 at 17:32
  • @juharr I want to access memory this way without having access to the code that is internal or private - third party assembly I can't modify. Theoretically I can but I don't want. Cached reflection is one solution but I was looking for more direct access known from native C++. – Konrad Dec 01 '17 at 17:34
  • 1
    Have you considered other alternatives to reflection? There might be something here that could be useful https://stackoverflow.com/questions/1027980/improving-performance-reflection-what-alternatives-should-i-consider – Kerri Brown Dec 01 '17 at 18:06
  • @MoonMoo yes there are libraries like Fasterflect and Fastmember, that use the method described in link you've posted. They're good but still I were looking for alternatives. Like what if I cached all offsets and wrote my own reflection like class that does it more transparently, maybe not so safe but whatever. That's how I use to do it in C++ all the time if you know what I use it for. That could be as fast as direct access... – Konrad Dec 01 '17 at 18:14
  • @i'myourhuckleberry Ok.Unless this question is purely academic, I would look at your choice of language then. If you really need that type of performance, say for example you are writing software for a real-time system, then I think maybe C# isn't the way to go. – Kerri Brown Dec 01 '17 at 18:37
  • @MoonMoo If you ever modded, hacked games that are made in C# then you might know what this could be for. I see nothing wrong in accessing unmanaged memory from managed code in such specific cases. I use many languages and I don't have to choose one. Of course I won't get native performance with C# but I can get better performance and it's simply faster to code in C#. – Konrad Dec 01 '17 at 18:38

2 Answers2

5

You can't do that.

I can

var inst = new Test();
unsafe
{
    var reference = __makeref(inst); // could also be retrieved with GCHandle.Alloc
    IntPtr ptr = **(IntPtr**)(&reference);
    int* x = (int*)ptr;
    Console.WriteLine(x[1]); // prints m_iInt1
    Console.WriteLine(x[2]); // prints m_iInt2
    Console.WriteLine(*(int*)((int)ptr + 0x4)); // same as above
    Console.WriteLine(*(int*)((int)ptr + 0x8));
}

I suppose the *(int*)((int)ptr + 0x0) is method table pointer as described here: http://blogs.microsoft.co.il/sasha/2012/03/15/virtual-method-dispatch-and-object-layout-changes-in-clr-40/ and http://yonifedaeli.blogspot.com/2017/03/sync-block-index-sbi-object-header-word.html

This is simply for educational purpose and I know such things are not used in normal kind of software. This can be used for many things I won't go into details here.

Konrad
  • 6,385
  • 12
  • 53
  • 96
-1

Assuming your scenario:

var fields = typeof(Test).GetFields();
int i = fields[0].GetValue(inst);

this would work

if you give us more insight over your usecase, one might can help you more :)

X39
  • 789
  • 6
  • 22
  • I know how to do it using reflection. I just want to avoid reflection and access it directly knowing the offset of the field. – Konrad Dec 01 '17 at 17:29
  • You have to pass an instance of `Test` to `GetValue`. – juharr Dec 01 '17 at 17:30
  • saw that after i posted this answer :) you probably want to look into https://stackoverflow.com/a/2120418/2684203 – X39 Dec 01 '17 at 17:30