Skip to main content

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.

The * token in C# is a context-dependent symbol that functions as a binary arithmetic multiplication operator, a unary pointer indirection (dereferencing) operator, a pointer type constructor, and a function pointer declarator. Its compilation behavior, precedence rules, and type-system role change strictly based on its syntactic placement and the presence of an unsafe context.

Binary Multiplication Operator

As a binary operator, * computes the product of two numeric operands. It is predefined for all standard numeric types (integer and floating-point).
int leftOperand = 5;
int rightOperand = 10;
int result = leftOperand * rightOperand;
  • Type Resolution: The compiler applies implicit numeric promotions to convert both operands to a common type before evaluating the expression. The return type is this common promoted type.
  • Overflow Mechanics: For integral types, behavior upon exceeding the maximum bounds of the return type depends on the execution context. In a checked context, it throws an OverflowException. In an unchecked context, the high-order bits of the result are discarded. For floating-point types, overflow of float and double results in PositiveInfinity or NegativeInfinity. Conversely, the decimal type always throws an OverflowException upon overflow, regardless of the checked or unchecked context.
  • Lifted Operators: The operator is lifted for nullable value types (T?). If either operand evaluates to null, the resulting expression evaluates to null.
  • Overloadability: Custom struct and class types can overload the binary multiplication operator using the operator keyword followed by the * symbol.

Unary Pointer Indirection Operator

In an unsafe context, the * token acts as a unary prefix operator to dereference a pointer. It obtains the underlying variable located at the memory address held by the pointer operand.
unsafe 
{
    int number = 42;
    int* pointerOperand = &number;
    int value = *pointerOperand;
    *pointerOperand = 100; // Mutation via l-value
}
  • Operand Constraints: The operand must be a pointer type (e.g., int*, char*). It cannot be applied to a pointer of type void*.
  • L-value Evaluation: The result of the indirection operator is an l-value, meaning it can be used on the left side of an assignment to mutate the data at the target memory address.

Pointer Type Constructor

When appended to a type name, the * token constructs a pointer type. This is a type-system construct used across various syntactic contexts, including variable declarations, cast expressions, typeof expressions, sizeof expressions, and method signatures.
unsafe
{
    int* pointerVar = null;
    var castedPointer = (byte*)pointerVar;
    Type pointerType = typeof(void*);
    int size = sizeof(int**);
}
  • Type Constraints: The base type preceding the * token must be either an unmanaged type (a type that is not a reference type and contains no reference type fields at any level of nesting) or the void keyword.
  • Composition: The * token can be appended to language keywords (int), fully qualified type names (System.Int32), or existing pointer types to create pointers-to-pointers (int**).
  • Declaration Syntax: When declaring multiple pointers in a single statement, the * is written only with the underlying type, not as a prefix to each identifier (e.g., int* p1, p2; declares two pointers to int).

Function Pointer Declarator

Introduced in C# 9, the * token is used in conjunction with the delegate keyword to declare a function pointer type (delegate*). This provides a lightweight, allocation-free alternative to managed delegates for invoking methods directly via their memory address.
unsafe
{
    // Declares a managed function pointer taking an int and returning a bool
    delegate*<int, bool> functionPointer;
    
    // Declares an unmanaged function pointer with a specific calling convention
    delegate* unmanaged[Cdecl]<void*, void> nativeCallback;
}
  • Context: Function pointers strictly require an unsafe context.
  • Calling Conventions: The declarator supports specifying calling conventions (e.g., managed, unmanaged, unmanaged[Stdcall]) immediately following the * token to dictate how arguments and return values are passed at the ABI level.

Operator Precedence and Associativity

The parser distinguishes between the unary and binary forms of * to determine evaluation order:
  1. Unary * (Indirection): Evaluates within the Unary operator precedence tier. This tier is strictly lower than the Primary operator tier (which includes member access ., method invocation (), and postfix increment/decrement x++/x--). The unary * shares precedence with other unary operators such as prefix increment/decrement (++x/--x), logical negation (!), and the address-of operator (&). It associates right-to-left.
  2. Binary * (Multiplication): Evaluates within the Multiplicative precedence tier, which is lower than both Primary and Unary tiers. It shares the same precedence level as division (/) and remainder (%). It associates strictly left-to-right.
Master C# with Deep Grasping Methodology!Learn More