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

# C# Function Pointer

A function pointer in C# is a lightweight, strongly-typed, unmanaged pointer to a memory address containing executable code. Introduced in C# 9.0, function pointers provide a mechanism to invoke methods directly via the Intermediate Language (IL) `calli` instruction, bypassing the heap allocation, object instantiation, and virtual dispatch overhead associated with traditional `System.Delegate` types.

Because they deal directly with memory addresses, function pointers can only be declared and used within an `unsafe` context.

## Syntax and Declaration

Function pointers are declared using the `delegate*` keyword, followed by type parameters enclosed in angle brackets. The type parameters specify the method signature, where the **final type parameter always represents the return type**.

```csharp theme={"dark"}
// Syntax: delegate*<[ParameterTypes...], [ReturnType]>

// A pointer to a method that takes an int and a string, and returns a bool
delegate*<int, string, bool> managedPointer;

// A pointer to a method that takes no parameters and returns void
delegate*<void> voidPointer;
```

## Assignment and Invocation

To assign a method to a function pointer, you use the address-of operator (`&`) followed by the method name. Function pointers can point to both `static` and instance methods.

While function pointers do not capture state (closures) or maintain an object reference like delegates, an instance method can be targeted by including the instance's type as the first parameter in the function pointer's signature. This explicitly represents the hidden `this` pointer required by instance methods.

```csharp theme={"dark"}
public unsafe class FunctionPointerDemonstration
{
    private static int Add(int x, int y) => x + y;
    private int Multiply(int x, int y) => x * y;

    public void Execute()
    {
        // 1. Static method assignment and invocation
        delegate*<int, int, int> staticPtr = &Add;
        int sum = staticPtr(10, 20); 

        // 2. Instance method assignment and invocation
        // The first type parameter represents the instance ('this')
        delegate*<FunctionPointerDemonstration, int, int, int> instancePtr = &FunctionPointerDemonstration.Multiply;
        int product = instancePtr(this, 10, 20);
    }
}
```

## Managed vs. Unmanaged Function Pointers

Function pointers are categorized by their calling convention, which dictates how arguments are passed to the function and how the stack is cleaned up.

**1. Managed Function Pointers**
By default, a `delegate*` uses the standard .NET managed calling convention. It can only point to managed C# methods.

**2. Unmanaged Function Pointers**
To point to unmanaged code (e.g., native C/C++ libraries), you must specify the `unmanaged` keyword. You can optionally define the specific unmanaged calling convention using a bracketed syntax. If the brackets are omitted, the runtime uses the default platform calling convention.

Mutually exclusive calling conventions (like `Cdecl` and `Stdcall`) cannot be combined. Multiple types within the bracket syntax are strictly reserved for combining a single calling convention with specific compiler modifiers.

When using the bracket syntax, the C# compiler automatically prepends the `CallConv` prefix to the identifiers you specify. Therefore, while the underlying type in the `System.Runtime.CompilerServices` namespace might be named `CallConvSuppressGCTransition`, the `CallConv` prefix must be strictly omitted in the C# language syntax to avoid compiler errors (e.g., CS8892).

```csharp theme={"dark"}
using System.Runtime.CompilerServices;

// Unmanaged pointer using the default platform calling convention
delegate* unmanaged<int, void> defaultUnmanagedPtr;

// Unmanaged pointer explicitly specifying the Cdecl calling convention
delegate* unmanaged[Cdecl]<int, void> cdeclPtr;

// Unmanaged pointer explicitly specifying the Stdcall calling convention
delegate* unmanaged[Stdcall]<int, void> stdcallPtr;

// Unmanaged pointer combining a calling convention with a GC transition modifier.
// Note the omission of the "CallConv" prefix for SuppressGCTransition.
delegate* unmanaged[Stdcall, SuppressGCTransition]<int, void> optimizedPtr;
```

## Architectural Differences from Delegates

To understand function pointers technically, it is necessary to contrast them with `System.Delegate`:

* **Memory Allocation:** A `Delegate` is a reference type that requires heap allocation. A `delegate*` is a raw memory address (an unmanaged pointer type), requiring zero heap allocation.
* **Invocation Mechanism:** Invoking a `Delegate` requires a virtual method call (`callvirt`) to the delegate's `Invoke` method, which then resolves the target. Invoking a `delegate*` emits the `calli` (Call Indirect) IL instruction, jumping directly to the memory address.
* **State:** A `Delegate` maintains an invocation list and an object reference (`Target`) for instance methods. A `delegate*` holds no state, no closure, and no object reference.
* **Type System:** `delegate*` types are not derived from `System.Object`. They cannot be boxed, cannot be used as generic type arguments (e.g., `List<delegate*<void>>` is invalid), and cannot be used in reflection without specialized metadata handling.

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor C# Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
