Show/Hide Toolbars

XSharp

 

Below is a list of some of the most visible new language features in the Core language of X#, compared to Visual Objects and Vulcan.

As you can see many new keywords were introduced, but these are positional: they will also be recognized as Identifiers on other places, so there is very little chance that you will have to make changes to avoid naming conflicts.

 

FEATURE

Description

DEFINE <id> := <Expression>

The VO Define is back again in X#. It will be compiled into a constant of the Globals class, the same class in which all Functions and Methods are implemented. The biggest advantage of a DEFINE over the preprocessor DEFINEs in Vulcan.NET is that there is no longer a chance that a DEFINE with the same name as a Method, Property or Variable will lead to incomprehensible compiler errors.

USING STATIC <Name>

The STATIC modifier for USING (note that the # sign is no longer needed) allows you to name a static class. When you do so, you can then use the methods of this class as functions. For example:
USING STATIC System.Console  
  FUNCTION Start as VOID
     WriteLine("X# is cool!")
  RETURN  

BEGIN USING <Var>  
<Statements>  
END [USING]

The USING block allows you to control the lifetime of a variable. If <Var> has a destructor, it will be automatically destructed once the block has finished.

SWITCH <Expression>
CASE <Const>  
<Statements>
CASE <Const2>
CASE <Const3>  
<Statements>
OTHERWISE  
<Statements>
END [SWITCH]

The SWITCH statement generates a more efficient jump structure than the DO CASE command. Also, the expression is only evaluated once.

BEGIN UNSAFE  
<Statements>  
END [UNSAFE]

Allows unsafe code in the context of this block, regardless of the compiler setting for the project as a whole.

BEGIN CHECKED  
<Statements>  
END [CHECKED]

Also allowed as expression

x := CHECKED(y)

The statements inside the block will have checked conversions, regardless of the compiler setting for the project as a whole.

BEGIN UNCHECKED  
<Statements>  
END [UNCHECKED]

Also allowed as expression

x := UNCHECKED(y)

The statements inside the block will have unchecked conversions, regardless of the compiler setting for the project as a whole.

VAR <Identifier> := <Expression>

This is a synonym for LOCAL IMPLIED

CLASS <Id> < <ParamName> > WHERE <TypeConstraints>     <Classmembers>
END [CLASS]

Creating Generic classes is now supported in X#, with all the features that C# also has For example:
  CLASS MyList<T> WHERE T IS CLASS
  ..
  END CLASS
or
  CLASS MyList<T> WHERE T IS ICustomer, NEW()
  ..
  END CLASS  

ASYNC - AWAIT

The ASYNC AWAIT infratructure is fully available inside X#.

<Expression> IS <Type>

Allows to check an expression for a type. Can be used instead of IsInstanceOf() and will perform better.

Conditional Access Operator ?:
<Expression> ? <Expression>

Conditional access for properties, methods etc. For example:
  nCount  := MyList?:Count  
This translates to something like:
VAR temp := MyList
  IF temp  != NULL  
     nCount := temp:Count
  ENDIF
The expression on the left-hand side of the question mark will be evaluated only once!

<Expression> DEFAULT <Expression>

The default operator allows you to inline a check for NULL:
  lResult := Foo() DEFAULT Bar()
This translates to the same as:
lResult := Foo()
  IF lResult == NULL    
     lResult := Bar()
  ENDIF
Foo() will be evaluated only once. Bar() will only be evaluated when the result is NULL.

y := CHECKED(x)

Tells the compiler to generate code that checks for overflow.

y := UNCHECKED(x)

Tells the compiler to generate code that does NOT check for overflow.

LINQ Query expressions are now supported:
VAR CustQuery = FROM Cust in Customers ;
  WHERE Cust.City = "Athens" ;
  ORDER BY Cust.Zipcode Select Cust

The full LINQ feature set will be supported by X#:
FROM LET WHERE JOIN ORDER BY EQUALS INTO

YIELD RETURN <Value>

Can be used in a method declared as Enumerator of a type. This will instruct the compiler to automatically generate a class that implemented an enumerator and return to the calling code directly on the YIELD RETURN line. The next time the Iterator is called, the code will remember where the code was the previous time it was executed, and it will continue on the next statement after the YIELD RETURN line.