Reputation: 5534
Suppose I have a class that has a few references to other classes:
class Bar {
}
class Baz {
}
class Foo {
Bar bar;
Baz baz;
}
Then I'm calling GCHandle.Alloc
on an instance of that class:
var foo = new Foo() { bar = new Bar(), baz = new Baz() };
var handle = GCHandle.Alloc(foo, GCHandleType.Normal);
Then I'm passing the handle
to native code which passes it back to C# in a callback function.
C# code will access both bar
and baz
members.
Will pinning foo
also guarantee that bar
and baz
are also pinned or should I pin them explicitly?
Follow up question assuming that I need to pin bar
and baz
explicitly:
Suppose I'd like to pin an object which I'm not the author of its class (also assume that the object has a few private members). How can I pin that object so it remains in usable (meaning, non of its members were collected by the GC)
Upvotes: 1
Views: 419
Reputation: 101533
Note that you are not pinning foo
. To pin it you'd have to use GCHandleType.Pinned
. This would prevent GC to move the pinned object in memory and will allow to reach object directly using a handle (so handle will basically represent pointer to that object in memory). But it's not necessary in this case because native code does not use the handle - it passes it back to managed code. So you correctly using Normal
handle (which again does not pin the object). Also as correctly mentioned in comments - you won't be able to pin foo
anyway, because only objects with only blittable members can be pinned.
So only thing this Normal
handle does is it prevents object from garbage collection, and allows you to refer to this object inderectly using handle from managed code (in this case from your callback function). So handle itself is not a pointer to managed object, but can be used to reach that object from managed code (using handle.Target
).
As such, because Foo
cannot be collected, then bar
and baz
cannot be collected either, so you don't need to do anything about them.
Upvotes: 1