Statements

break/continue

We can stop executing a “for”, “while”, or “do” statement by using “break”. We can skip to the next iteration of a “for” loop with “continue”; By default, these statements refer apply to the most-deeply nested applicable statement in the current scope, but we can use labels to refer to statements further out. This can be useful in situations such as breaking out of nested loops.

Y: for (int y < height)
    for (int x < width)
        if (Check(x, y))
            break Y;

defer

Defer statements can be used to defer execution of method calls or of code blocks until a given scope is exited. When the deferred statement is a method call, the arguments (including this) are evaluated immediately.

/* The following will print "End:2 B:1 A:0". Note that the execution order is the opposite of the deferred order. */
{
    int i = 0;
    defer Console.WriteLine("A:{}", i);
    i++;
    defer Console.WriteLine("B:{}", i);
    i++;
    Console.WriteLine("End:{}", i);
}

/* The following will print "End:2 B:2 A:2". There were no arguments to evaluate at the defer location, so the 'i' value used in WriteLine is just the current value at the end of the scope. */
{
    int i = 0;
    defer
    {
        Console.WriteLine("A:{}", i);
    }
    i++;
    defer
    {
        Console.WriteLine("B:{}", i);
    }
    i++;
    Console.WriteLine("End:{}", i);
}

/* The defer statement allows a scope target to be specified. The following will print numbers 9 through 0 when exiting from the containing method. */
{
    for (int i < 10)
    {
        defer:: Console.WriteLine("i={}", i);
    }
}

delete

The delete statement releases allocated memory. (see Memory Management)

When x is an object, calls the destructor.

do

Allows for a non-looping block which can be broken out of, which can reduce ‘if nesting’ in some code patterns.

do
{
    c = NextChar();
    if (c == 0)
        break;
    op = NextChar();
    if (c != '+')
        break;
    c2 = NextChar();
}

for

For loops are generally used to iterate through a collection or a number series. There are several forms available.

/* The classic C-style loop, with an initializer, a condition, and iterator */
for (int i = 0; i < count; i++)
{
}

/* A shorthand for the above */
for (int i < count)
{
}

/* Iterate through elements in a List<int> */
for (let val in intList)
{
    if (val == 0)
        @val.Remove();
}

/* The above is equivalent to */
var enumerator = intList.GetEnumerator();
while (enumerator.GetNext() case .Ok(let val))
{
    if (val == 0)
        enumerator.Remove();
}
enumerator.Dispose();

/* We can also iterate by refrence instead of by value */
for (var valRef in ref intList)
    valRef += 100;


/* Common Mistake: This will NOT change the values in intList, just the value returned by enumerator.GetNext() */
for (var val in intList)
    val += 100;

if

if (i > 0)
    Use(i);
else if (i == 0)
    Use(1);
else
    break;

/* Some variable declarations can be used as a condition */

/* Use 'not null' as a condition */
if (var str = obj as String)
    Console.WriteLine(str);

/* Unwrap a Result<int> */
if (int i = intResult)
    Use(i);

/* Unwrap an int? */
if ((int i = intNullable) && (i != 0))
    Use(i);

return

Returns a value from a method.

int GetSize()
{
    return mSize;
}

repeat while

Executes a statement once and repeats execution as long as the condition is true.

bool wantsMore;
repeat
{
    wantsMore = Write();
}
while (wantsMore);

switch

/* Note that 'break' is not required after a case */
switch (c)
{
case ' ', '\t':
    Space();
case '\n'
    NewLine();
default:
    Other();  
}

switch (c)
{
/* Cases can contain additional 'when' conditions */
case '\n' when isLastChar:
    SendCommand();
case 'A':
    WasA();
    /* 'fallthrough' continues into the next case block*/
    fallthrough;
case 'E', 'I', 'O', 'U':
    WasVowel();
}

switch (shape)
{
/* Pattern match, with '?' discard */
case .Circle(0, 0, ?):
    HandleOriginCircle();
case .Circle(let x, let y, let radius):
    HandleCircle(x, y, radius);
default:
}

Switches can be used for pattern matching (see for further examples) for enums and tuples.

/* Note that switches over enums that do not handle every case and have no 'default' case will give a "not exhaustive" compile error. Thus, if we added a new entry to the Shape definition, we would ensure that all switches will make modifications to handle it */
switch (shape)
{
case Square(let x, let y, let width, let height):
    DrawSquare(x, y, width, height);
case Circle:
    IgnoreShape();
}

Switches can operate on non-integral types, as well.

switch (str)
{
case "TEST":
    PerformTest();
case "EXIT":
    Exit();
default:
    Fail();
}

using

The using statement expresses scoped usage of values.

using (g.Open("Header"))
{
    g.Write("Hello");
}

/* These are equivalent */
{
    var res = g.Open("Header");
    g.Write("Hello");
    res.Dispose();
}

/* Or */
{
    defer g.Open("Header").Dispose();
    g.Write("Hello");
}

Variable declarations

// Define mutable variable with an explicit type and without an assignment
int val;
// Define multiple variables with an explicit type
int a, b;
// Define mutable variable with an explicit type and an initializer
int val2 = 123;
// Define mutable variable with an implicit type and an initializer
var val3 = 1.2f;
// Define immutable variable with an implicit type and an initializer
let val4 = 2.3;

while

Repeatedly executes a statement as long as the condition is true.

while (i >= 0)
{
    i--;
}