The with statement has been extended over standard Pascal syntax to require a variable name to be explicitly specified, such as:
with p := PersonArray[i] do begin ... p.Name := 'Klaus'; ... end;
The above is actually a shortcut for:
with p: Person := PersonArray[i] do begin ... p.Name := 'Klaus'; ... end;
where the type is automatically inferred from the assigned value.
Use of variable names makes nested 'with's' to be used without losing clarity. For example:
with b: Button := new Button do with c: Color := b.BackColor do begin ... b.Text := 'Hello World'; self.Text := c.ToString; ... end; end;
Oxygene also supports WITH on record types and changes the original member right on the record. When it's not possible to do this, for example if the 'with' is on the result of a method call, the compiler will return a warning when something is changed.
To provide backward compatibility with the classic pascal syntax, a compiler option "Allow legacy with" is provided that allows the use of old-style "with" statements that do not use an explicit variable. This compiler switch can be specified inline or project-wide, but is turned OFF by default:
with PersonArray[i] do begin ... Name := 'Klaus'; ... end;
A common requirement is to process an object instance only if it has been initialized, e.g.:
with p: MyClass := MyClass(getSomeValue()) do if p <> nil then SomeRoutine
Using the matching keyword, this simplifies to:
with matching p: MyClass := MyClass(getSomeValue()) do SomeRoutine
Query Operator: with
With can be used in Query Expressions to introduce a new variable into the Linq query.
var customersWithOrders := from c in Customers with o := (from od in CustomerOrders where od.Customer = c.Id select od) select new class (Customer := c, Orders := o);
the with keyword here defines a new variable that can be used in the rest of the Linq query without having to repeat the value of o inline, reducing the complexity of the query.
Using a 'with' variable, that might potentially hide another local variable will yield a compilation error.
var a := 1; with a := 2 do begin end;
If a happened to be a field of this class, it would only yield a PW12 warning (name clash).