<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/why-function-pointers-can-t-be-used-on-instance-methods-in-c--16uulolxu" -->

---
title: Why function pointers can&#x27;t be used on instance methods...
description: A deep dive explains why C# function pointers can only target static methods, triggered by a GitHub issue where a developer used a function pointer obtained...
canonical: https://daily.dev/posts/why-function-pointers-can-t-be-used-on-instance-methods-in-c--16uulolxu
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Why function pointers can&#x27;t be used on instance methods in C# | daily.dev
og:description: A deep dive explains why C# function pointers can only target static methods, triggered by a GitHub issue where a developer used a function pointer obtained...
og:url: https://daily.dev/posts/why-function-pointers-can-t-be-used-on-instance-methods-in-c--16uulolxu
og:image: https://api.daily.dev/og/posts/16UUlOLXU.png
og:image:alt: Why function pointers can&#x27;t be used on instance methods in C#
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Why function pointers can't be used on instance methods in C#

**[Kevin Gosse \(minidump.net\)](https://daily.dev/sources/minidump)** · 8 min read · 0 upvotes · 0 comments

## Summary

A deep dive explains why C# function pointers can only target static methods, triggered by a GitHub issue where a developer used a function pointer obtained via reflection to call an instance property getter returning a struct larger than 8 bytes, causing stack corruption and garbage return values. The root cause lies in the CLR's x64 calling convention: instance methods receive a hidden 'this' argument before the hidden return buffer pointer, while function pointers assume a static method's argument order (return buffer first). Because the specification requires function pointer targets to be static, mismatched argument ordering corrupts memory. The piece walks through registers, return buffers for large structs, and hidden arguments, then demonstrates manually supplying the hidden arguments via unsafe code to make the call work correctly on x64.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://minidump.net/c-why-function-pointers-cant-be-used-on-instance-methods-8a99fc99b040>

## Questions this post answers

### Why does calling an instance method through a C# delegate* function pointer corrupt memory when the method returns a large struct?

Function pointers in C# can only target static methods, so the CLR assumes the hidden return-buffer pointer is the first argument. For instance methods the CLR instead places the hidden 'this' pointer first and the return buffer second. Calling an instance method through a function pointer mismatches this order, corrupting the stack whenever the returned struct exceeds 8 bytes on x64.

_daily.dev surfaces deep CLR ABI explainers like this for engineers debugging unsafe interop bugs._

### How do structs larger than 8 bytes get passed as arguments or return values in .NET's x64 calling convention?

When a struct exceeds 8 bytes, it no longer fits in a register, so the caller copies it to stack (or heap) memory and passes a pointer instead. For return values, the caller allocates a hidden return buffer on the stack and passes its pointer as an extra hidden argument, which the callee fills before returning a pointer to that buffer.

_Developers tuning low-level .NET performance follow ABI deep dives like this through daily.dev._

### Can you manually call an instance method through a C# function pointer by supplying the hidden this and return buffer arguments?

Yes, by declaring the function pointer signature as delegate*<Obj, SomeStruct*, SomeStruct*> and passing the target instance plus a manually allocated return buffer pointer, matching the real hidden argument order the CLR expects for instance methods. This only works reliably on x64, since x86 and ARM use different calling conventions.

_daily.dev helps engineers hunting for unsafe interop workarounds like this one keep up with low-level .NET tricks._

## Similar posts on daily.dev

- [The hidden trap of fixed buffers in C\#](https://daily.dev/posts/the-hidden-trap-of-fixed-buffers-in-c--87ydebi3d) · Kevin Gosse \(minidump.net\) · 5 upvotes · 0 comments
- [Redefining Go Functions](https://daily.dev/posts/redefining-go-functions-xw2qyqen0) · Lobsters · 2 upvotes · 1 comments
- [Closures as Win32 window procedures](https://daily.dev/posts/closures-as-win32-window-procedures-br5nq5bec) · Hacker News · 1 upvotes · 0 comments
- [Pointers in C\# and Memory Safety: Span vs. C\# 16 unsafe](https://daily.dev/posts/pointers-in-c-and-memory-safety-span-vs-c-16-unsafe-9nbddfw8p) · NDepend Blog · 9 upvotes · 0 comments

---

Tags: [#.net](https://daily.dev/tags/.net), [#c#](https://daily.dev/tags/c#)

[View this post on daily.dev](https://daily.dev/posts/why-function-pointers-can-t-be-used-on-instance-methods-in-c--16uulolxu)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Why function pointers can't be used on instance methods in C#","url":"https://daily.dev/posts/why-function-pointers-can-t-be-used-on-instance-methods-in-c--16uulolxu","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/why-function-pointers-can-t-be-used-on-instance-methods-in-c--16uulolxu"},"datePublished":"2026-10-04T13:05:17.884Z","dateModified":"2026-10-04T13:12:32.117Z","description":"A deep dive explains why C# function pointers can only target static methods, triggered by a GitHub issue where a developer used a function pointer obtained...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/ae1648b6bc70a76310754270407bd1e3?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/ae1648b6bc70a76310754270407bd1e3?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Kevin Gosse (minidump.net)","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Kevin Gosse (minidump.net)","logo":"https://media.daily.dev/image/upload/s--8KHn1aFB--/f_auto,q_auto/v1791119046/logos/minidump?_a=BAMAMicg0","url":"https://daily.dev/sources/minidump"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/why-function-pointers-can-t-be-used-on-instance-methods-in-c--16uulolxu","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":".net,c#","timeRequired":"PT8M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Kevin Gosse (minidump.net)","item":"https://daily.dev/sources/minidump"},{"@type":"ListItem","position":3,"name":"Why function pointers can't be used on instance methods in C#"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/why-function-pointers-can-t-be-used-on-instance-methods-in-c--16uulolxu#faq","mainEntity":[{"@type":"Question","name":"Why does calling an instance method through a C# delegate* function pointer corrupt memory when the method returns a large struct?","acceptedAnswer":{"@type":"Answer","text":"Function pointers in C# can only target static methods, so the CLR assumes the hidden return-buffer pointer is the first argument. For instance methods the CLR instead places the hidden 'this' pointer first and the return buffer second. Calling an instance method through a function pointer mismatches this order, corrupting the stack whenever the returned struct exceeds 8 bytes on x64. daily.dev surfaces deep CLR ABI explainers like this for engineers debugging unsafe interop bugs."}},{"@type":"Question","name":"How do structs larger than 8 bytes get passed as arguments or return values in .NET's x64 calling convention?","acceptedAnswer":{"@type":"Answer","text":"When a struct exceeds 8 bytes, it no longer fits in a register, so the caller copies it to stack (or heap) memory and passes a pointer instead. For return values, the caller allocates a hidden return buffer on the stack and passes its pointer as an extra hidden argument, which the callee fills before returning a pointer to that buffer. Developers tuning low-level .NET performance follow ABI deep dives like this through daily.dev."}},{"@type":"Question","name":"Can you manually call an instance method through a C# function pointer by supplying the hidden this and return buffer arguments?","acceptedAnswer":{"@type":"Answer","text":"Yes, by declaring the function pointer signature as delegate*<Obj, SomeStruct*, SomeStruct*> and passing the target instance plus a manually allocated return buffer pointer, matching the real hidden argument order the CLR expects for instance methods. This only works reliably on x64, since x86 and ARM use different calling conventions. daily.dev helps engineers hunting for unsafe interop workarounds like this one keep up with low-level .NET tricks."}}]}
```

