Translating C# to X#

This forum is meant for questions and discussions about the X# language and tools
User avatar
Kees Bouw
Posts: 174
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Translating C# to X#

Post by Kees Bouw »

There are a lot of C# code examples on the internet and sometimes I have trouble translating them, in the most efficient way, to X#. For example this piece of code:

Code: Select all

// Draw the custom border to appear 3-dimensional.
e.Graphics.DrawLines(SystemPens.ControlLightLight, new Point[] {
    new Point (0, e.Bounds.Height - 1), 
    new Point (0, 0), 
    new Point (e.Bounds.Width - 1, 0)
});
What would be the best X# equivalent?
(The code is on this page: https://learn.microsoft.com/en-us/dotne ... esktop-9.0)
Thanks in advance :)
User avatar
Chris
Posts: 5577
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: Translating C# to X#

Post by Chris »

Hi Kees,

The 2nd parameter is a (fixed size) array (of Point(s)), given it's elements on definition. For an INT array, the X# syntax to do this would be

aArrayOfInts := <INT> {1,2,3,6,7,0}

For an array of point, you need to instantiate Point objects withing the definition. It helps to divide this in two lines, by using an intermediate variable, to make it easier to read:

Code: Select all

LOCAL aPoints AS Point[] // single dim fixed size array of Point
aPoints := <Point> { Point {0, e:Bounds.Height - 1}, Point {0, 0}, Point {e:Bounds.Width - 1, 0} } // specify all the array elements at once

e:Graphics:DrawLines(SystemPens.ControlLightLight, aPoints)
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
Kees Bouw
Posts: 174
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: Translating C# to X#

Post by Kees Bouw »

Hi Chris,

Thank you very much!
Chris wrote: Mon Oct 13, 2025 10:31 am aArrayOfInts := <INT> {1,2,3,6,7,0}
Would this be the same as:

Code: Select all

aArrayOfInts := ARRAY OF INT
aArrayOfInts := {1,2,3,6,7,0}
Or does the < > make it into something special? It looks like some sort of cast.
Chris wrote: Mon Oct 13, 2025 10:31 am LOCAL aPoints AS Point[] // single dim fixed size array of Point
Would this be the same as:

Code: Select all

aPoints := ARRAY OF Point
Or is for example Point[] a dotnet array and an ARRAY OF Point an X# array?
Chris wrote: Mon Oct 13, 2025 10:31 am aPoints := <Point> { Point {0, e:Bounds.Height - 1}, Point {0, 0}, Point {e:Bounds.Width - 1, 0} } // specify all the array elements at once
It does work but I don't really understand the <> {} syntax. I also can't find it in the Help. Do you know where this is explained a little more?

Different topic: the horizontal line that you can add in this editor is hardly visible, it is grey on grey.

Thanks!

Kees.
User avatar
robert
Posts: 4989
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Re: Translating C# to X#

Post by robert »

Kees,

ARRAY OF INT is not the same as INT[]
ARRAY OF INT produces a dynamic array, just like the arrays in VO, but its elements are of type INT and not of type USUAL.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
User avatar
Chris
Posts: 5577
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: Translating C# to X#

Post by Chris »

Hi Kees,

The <> syntax was introduced by Don in vulcan, so we used it also in X# for compatibility. I think the logic behind it was to use a similar pattern to the syntax used universally for generics, where you specify the generic type like this List<INT> or Dictionary<STRING,Point>.

If you don't like this, in X# you can also use this syntax:

aPoints := Point[] {3} { Point {0, e:Bounds.Height - 1}, Point {0, 0}, Point {e:Bounds.Width - 1, 0} }

The first {3} is used to denote the size of the array, rest of the line lists the array elements. "Point[]" is the universal way in .Net for specifying fixed size arrays.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
Kees Bouw
Posts: 174
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: Translating C# to X#

Post by Kees Bouw »

Here another "translation" question. To find which radiobutton in a groupbox (Windows.Forms) is selected, I found this C# example:

Code: Select all

groupbox1.Controls.OfType<RadioButton>().FirstOrDefault(r => r.Checked).Name
To do this in X# I got as far as this:

Code: Select all

groupbox1:Controls:OfType<RadioButton>()
but after that I am lost. The remainder of the example gives the compiler error "Parser: unexpected input '=>'"

What is correct X# syntax?

Thanks in advance for some help!

Kees.
User avatar
Irwin
Posts: 211
Joined: Wed Mar 23, 2022 10:24 am
Location: Spain

Re: Translating C# to X#

Post by Irwin »

Hi Kees,

In X#, the => operator is not a general lambda operator like in C#. That's why this fails:

Code: Select all

FirstOrDefault(r => r:Checked)   // parser error
However, X# does allow LINQ-style shorthand inside a codeblock { }, so this is valid:

Code: Select all

FirstOrDefault({ r => r:Checked })
This shorthand is equivalent to the tradicional xBase codeblock syntax, which is the most idiomatic X# form:

Code: Select all

FirstOrDefault({ |r| r:Checked })
So, in summary:
a. => only works inside { }
b. { |r| ... } works everywhere and is pure xBase
c. Outside of a codeblock, => is not valid X# syntax

For clarity and consistency (especially in examples), the { |r| ... } form is usually recommended.

Hope this clears things up 👍

Irwin.
XSharp Development Team (VFP)
Spain | irwin@xsharp.eu
User avatar
Chris
Posts: 5577
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: Translating C# to X#

Post by Chris »

Guys,

A correction, the syntax { a,b,c => a*b*c } in X# IS a proper lambda expression, we have just used the curly braces {} to make the syntax more close to the one we know from codeblocks, but the above is not a codeblock. For an expression to be a codeblock, the || characters are also required (and the => operator should not be included), as in { |a,b,c| a*b*c }, as we know it from Clipper etc.

Kees, to explain the code a bit more, what it essentially does is this:

Code: Select all

FUNCTION GetCheckedRadio(oGroupBox AS GroupBox) AS RadioButton
	FOREACH oControl AS Control IN oGroupBox:Controls
		IF oControl IS RadioButton VAR oRadioButton // if control is a radiobutton, then it is assigned to the new local variable "oRadioButton"
			IF oRadioButton:Checked
				RETURN oRadioButton
			END IF
		END IF
	NEXT
RETURN NULL
which is pretty standard and self self explainable code, except maybe for the IS <type> VAR <oNewVar> code pattern which is new in X#/.Net, but could also had be written in two separate lines without it also.

In the above code, oGroupBox:Controls represents a collection (of controls), and the code you found cuts the code down by using the method OfType() which is available for collections, and returns a new collection, which includes only the original items of the type you specify, so another way to write this is:

Code: Select all

FUNCTION GetCheckedRadio(oGroupBox AS GroupBox) AS RadioButton
	FOREACH oRadioButton AS RadioButton IN oGroupBox:Controls:OfType<RadioButton>()
		IF oRadioButton:Checked
			RETURN oRadioButton
		END IF
	NEXT
RETURN NULL
Finally, in order to further cut down the above code, the sample uses the FirstOrDefault() method that can be applied to collections and returns the first item that satisfies a condition (that it is "Checked" in our case), or returns NULL if no item satisfies it:

Code: Select all

FUNCTION GetCheckedRadio(oGroupBox AS GroupBox) AS RadioButton
	
RETURN oGroupBox:Controls:OfType<RadioButton>():FirstOrDefault( {oRadioButton AS RadioButton => oRadioButton:Checked} )
So the code you found does what you want in a very neat and powerful way in just a single line of code, which is great for demonstrating the power of .Net and also demonstrates the poster's knowledge and one might even say it's plain showoff :)

But it's probably also making it very difficult for others to read and understand the code, without spending much time on it..For this reason, I usually personally prefer the longer versions of the code which are easier to read.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
Kees Bouw
Posts: 174
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: Translating C# to X#

Post by Kees Bouw »

Hi Irwin and Chris,

Thank you both very much for explaining it in such detail. That really helps me to understand what is going on. I would like to add one small detail, which is that you have to add "USING System.Linq" otherwise you get Error XS1061 'System.Windows.Forms.Control.ControlCollection' does not contain a definition for 'OfType'.

Kees.
mindfulvector
Posts: 29
Joined: Tue Jun 24, 2025 1:57 pm
Location: United States

Re: Translating C# to X#

Post by mindfulvector »

This is likely not relevant to this specific issue, but I wanted to add in case someone else finds this and encounters the same problem that I did:

One thing to point out for "Point" is that there is a built-in POINT type in XSharp. For this reason, I've had to use System.Drawing.Point{x,y} instead of Point{x,y} in order to resolve the collision. This is the case even with USING System.Drawing
Post Reply