Expressions

Allocations

new and scope keywords are used for allocation (see Memory Management)

append

The append expression allocates memory immediately after an object’s allocated memory, and can only be used in a constructor. (See Memory Management)

An append allocation can be used in any way a new allocation can be used. (See new)

Assignment operations

See Assignment operators

Binary operations

See Binary operators

Bind expression =>

The => expression is used for method binding (see Method References)

box

The box expression allocates an object which wraps a value type. (See Memory Management (boxing))

case

case expressions can be used for pattern matching outside switches. (See Pattern Matching)

Cast expression

Conditional operator

Conditional variable declarations

Variable declarations can be use as boolean expressions in ‘if’ statements for nullable types. These can be used with certain types of binary operations in the cases where a ‘true’ overall ‘if’ result ensures that the conditional variable declaration was also evaluated and resulted in ‘true’.

/* Simple conditional variable declaration */
if (let name = GetName())
{

}

/* 'Complex' conditional variable declaration */
if ((let name = GetName()) && (isEnabled))
{

}

/* This is ILLEGAL since "force" can cause the block to be entered even if the conditional variable declaration fails */
if ((let name == GetName()) || (force))
{

}

default

Every type has a “default” value, which is always zero-initialization.

// Default can specify a type and results in a default-initialized value
var str = default(String);
// Default will use the "expected" type if there is no explicit default type specified
String str2 = default;

Expression blocks

Expression blocks end with an expression that is not terminated by a semicolon.

Console.WriteLine("Result={}",
    {
        GetByRef(let val);
        val
    });

Index expressions

Literals

new

The new expression allocates memory in the global allocator or in a custom allocator. (See Memory Management)

All new operations can also accept a custom allocator argument.

Null-conditional operators

Null-conditional operators val?.field and val?[index] will result in null if val is null. The null-conditional operators can be applied in a chain, which will short-circuit to null at the first instance of a null.

int? a = val?.intField;
int? nameLength = val?.name?.Length;

Parentheses expression

Adding parentheses around expressions can be used for changing order of operations for complex expressions.

int a = 1 + 2 * 3; // The multiply happens before the add here, resulting in 7
int b = (1 + 2) * 3; // The add happens before the multiply here, resulting in 9

Range expression

Ranges consist of a start and end integer value and are primarily used for loop iteration and range indexing. They can be created as inclusive or exclusive ranges. Index ranges may have one open side. (See Range operators)

let list = scope List<int>() { 5, 1, 0 };

/* Since we are iterating through a range, the list.Count getter will only be called once when the range is created */
/* Thus, the lists count is simply doubled instead of creating an infinite loop */
for (let i in 0 ..< list.Count)
    list.Add(list[i]);

// list is now: { 5, 1, 0, 5, 1, 0 }

for (let i in (0 ..< list.Count).Reversed)
    list.Add(list[i]);

// list is now: { 5, 1, 0, 5, 1, 0, 0, 1, 5, 0, 1, 5 }

var subset = list[...2]; // equivalent to 0...2, ..<3 and ...^10 (^ counts from the end, staring at Count)
subset = list[4...]; // equivalent to 4...11, 4...^1 and 4..<^0

scope

The scope expression allocates memory on the stack, in a scope contained in an executing method. (See Memory Management)

A scope allocation can be used in any way a new allocation can be used. (See new)

this

this is a special variable name, which represents the current instance in instance methods. If the defining type is a struct then this is a value type (not a pointer), which is mutable for “mut” methods and immutable otherwise.

Tuple expression

The tuple expression is a paranthesized expression containing multiple comma-seperated values, and optionally field names. (See Data Types (Tuples)))

Unary operations

See unary operators

Uninitialized ‘?’

When assigned to a variable or field, ? will cause the value to be treated as if it had an assignment but without (necessarily) any actual operation. This can be useful in cases such as with “buffer” type arrays that don’t need to be zero-initialized before use.

When used with out parameters, ? will act as a discard.

When used in constructors, uninitialized constructor calls this(...) : this(?) and this(...) : base(?) will discard the according initializers and constructors. See Initialization