This page notes some differences between C# and boo.
C# to Boo Converter
The easiest way to see how code in boo differs from C# is to use the C# to boo converter included in the Boo AddIn For SharpDevelop.
The converter is also accessible online via a webform here: http://developer.sharpdevelop.net/codeconvert.net/
While viewing a C# file in SharpDevelop, you can select from the menu: Tools -> Convert C# to boo. Or you can convert an entire C# project at once by right-clicking on the project icon and selecting: Convert -> C# to boo. Note, however, the converter is still new and in development.
The converter will convert C# to legal boo code, but it will not show you the simplest way to write that code. For example, instead of "System.Console.WriteLine
", in boo you can simply say "print x". And many times the type will be declared "x as int" when it is unnecessary since the type can be inferred by the boo compiler: "x = 3" or "m = MyClass()".
C# vs. Boo Syntax Examples
Here is a table noting some diffences between C# and boo, based on this table from the Nemerle programming language site. See also the C# language specification.
Expressions
C# | Boo | Remarks |
|---|
| Code Block |
|---|
int x = 3;
string y = "foo";
FooBarQux fbq = make_fbq ();
|
| | Code Block |
|---|
x = 3
y = "foo"
fbq = make_fbq()
|
| Types are inferred, no semicolons needed |
| Code Block |
|---|
expr_1 = expr_2 = expr_3;
|
| | Code Block |
|---|
expr_1 = expr_2 = expr_3
|
|
| Code Block |
|---|
Class c = new Class (params);
|
| | Code Block |
|---|
c = Class(params)
|
| No "new" keyword required |
| Code Block |
|---|
Class[] c = new Class [size]
|
| | Code Block |
|---|
c = array(Class, size)
|
| See Lists and Arrays |
| Code Block |
|---|
GenericClass<int> c = new GenericClass<int>();
|
| | Code Block |
|---|
c = GenericClass[of int]()
|
| See Generics |
| Code Block |
|---|
Type[] l = new Type[] { expr_1, expr_1,
..., expr_n }
|
| | Code Block |
|---|
l = (expr_1, expr_1,
..., expr_n)
|
| Types are inferred when you use arrays |
| Code Block |
|---|
if (cond) return foo;
do_something ();
return bar;
|
| | Code Block |
|---|
if cond:
return foo
//You can also say:
return foo if cond
do_something()
return bar
|
|
| Code Block |
|---|
if (cond) answer = 42;
|
| | Code Block |
|---|
if cond:
answer = 42
//or
answer = 42 if cond
|
|
| Code Block |
|---|
if (!cond) answer = 42;
|
| | Code Block |
|---|
answer = 42 if not cond
|
|
| Code Block |
|---|
try ...
catch (FooException e) { ... }
catch (BarException e) { ... }
|
| | Code Block |
|---|
try:
...
except e as FooException:
...
except e as BarException:
...
|
|
| Code Block |
|---|
try { foo (); bar (); }
catch (Exception e) { baz (); }
finally { qux (); }
|
| | Code Block |
|---|
try:
foo()
bar()
except e:
baz()
ensure:
qux()
|
|
| Code Block |
|---|
throw new System.ArgumentException ("foo");
|
| | Code Block |
|---|
raise System.ArgumentException("foo")
|
| Use "raise" to generate an exception. |
| Code Block |
|---|
type t = ((type) expr)
|
| | Code Block |
|---|
t = expr cast type
//or
//null if cast fails:
t = expr as type
|
| See Casting Types |
| Code Block |
|---|
using System.Windows.Forms;
Button button = control as Button;
if (button != null) ...
else ...
|
| | Code Block |
|---|
import System.Windows.Forms
button = control as Button
if button != null:
...
else:
...
|
|
| Code Block |
|---|
using System;
using SWF = System.Windows.Forms;
using System.Xml;
...
Console.WriteLine ("foo");
SWF.Form x = new SWF.Form ();
XmlDocument doc = new XmlDocument ();
|
| | Code Block |
|---|
import System
import System.Windows.Forms as SWF
import System.Xml
print "foo"
x = SWF.Form()
doc = XmlDocument()
|
| You can creates aliases for namespaces. Also use print instead of console.writeline. |
| |
| Code Block |
|---|
readonly int X = 2;
const int Y = 3;
|
| | Code Block |
|---|
final X = 2
static final Y = 3
|
| Read-only and constant fields. |
Type definitions
C# | Boo | Remarks |
|---|
| Code Block |
|---|
static int foo (int x, string y)
{ ... }
|
| | Code Block |
|---|
static def foo(x as int, y as string) as int:
...
|
| Use "def" for methods and functions. Types are declared with the "as" keyword like VB. |
| Code Block |
|---|
class Foo : Bar {
public Foo (int x) : base (x) { ... }
}
|
| | Code Block |
|---|
class Foo (Bar):
def constructor(x as int):
super(x)
...
|
| Illustrates a class with a superclass and a constructor |
| Code Block |
|---|
class Foo {
int x;
}
|
| | Code Block |
|---|
class Foo:
x as int
|
| a class with a field |
| Code Block |
|---|
class Foo {
readonly int x;
}
|
| | Code Block |
|---|
class Foo:
final x as int
|
| or else a "const" keyword may be added to boo |
| Code Block |
|---|
class C : I1, I2 {
void I1.m () { ... }
void I2.m () { ... }
}
|
| | Code Block |
|---|
class C (I1, I2):
def I1.m():
...
def I2.m():
...
|
| Implementing two interfaces that have the same named method. |
| Code Block |
|---|
using System.Runtime.CompilerServices;
class C {
public object this [int i] { ... }
[CSharp.IndexerName("MyItem")]
public int this [string name] { ... }
}
|
| | Code Block |
|---|
import System.Reflection
[DefaultMember("MyItem")]
class A:
private _val = (1,2,3,4)
MyItem(index as long) as int:
get:
return _val[index]
set:
_val[index] = value
a = A()
print a[2]
a[2] = 10
print a[2]
|
| Use the DefaultMember attribute. |
| | char() builtin |
| Code Block |
|---|
float v = 1.0f;
|
| | Code Block |
|---|
f = 1.0f
//or
f as single = 1.0
|
| Uses "single" instead of "float" |
Miscellaneous Differences and Similarities
C# | Boo | Remarks |
|---|
| Code Block |
|---|
// A comment.
/* A possibly multiline
comment. */
|
| | Code Block |
|---|
// A comment.
/* A possibly multiline
comment. */
# Another comment
|
| C++ style commenting plus Python # comments. |
| | Quoted string literals. Triple-quoted strings can span multiple lines, too. |
| |
| |
Other Notes on Differences Between C# and Boo
These are some early notes from looking at the C# language specification.
Assigning multiple variables at once
In C#, you can assign a value to two variables at once like so:
In boo, however, "a, b" refers to a sequence. So you would instead use:
Note also declaring the type is unnecessary because of boo's Type Inference.
Use "a, b" when unpacking multiple values. For example:
| Code Block |
|---|
name = "First Last"
firstname, lastname = @/ /.Split(name)
print firstname, lastname
|
Also note in boo you can use the "print" statement instead of System.Console.WriteLine.
Buffer overflow checking
You can turn off overflow checking in boo like so:
| Code Block |
|---|
try:
checked:
i = 100000
i += 1000000000
i += 1000000000
i += 1000000000
except:
print "did overflow i"
unchecked:
j = 100000
j += 1000000000
j += 1000000000
j += 1000000000
print "didn't overflow j: $j"
|
Variable number of parameters.
| Code Block |
|---|
static void F(params int[] args) {
Console.WriteLine("# of arguments: {0}", args.Length);
for (int i = 0; i < args.Length; i++)
Console.WriteLine("\targs[{0}] = {1}", i, args[i]);
}
|
Boo uses syntax similar to python:
| Code Block |
|---|
def F(*args as (int)):
print "# of arguments: $(len(args))"
for arg in args:
print arg
|
By reference and output parameters.
In C# you can pass types to functions by reference using "ref" or "out" keywords.
| Code Block |
|---|
static void Swap(ref int a, ref int b) {
int t = a;
a = b;
b = t;
}
....
Swap(ref x, ref y);
|
Boo supports the "ref" keyword, too, but not "out", which is unnecessary in boo.
| Code Block |
|---|
def Swap(ref a as int, ref b as int):
t = a
a = b
b = t
x = 1
y = 2
Swap(x,y)
|
Note though that in this particular sample, you can swap two values more easily like so:
| Code Block |
|---|
x = 1
y = 2
x, y = y, x
print x, y //-> 2 1
|
As a more general alternative to by reference parameters, in boo you can also return multiple values from a function instead:
| Code Block |
|---|
def Swap(a as int, b as int):
return b, a
a, b = Swap(a, b)
|
Things in C# but not Boo
do..while loop
Boo doesn't have do..while or do..until loops like C# or VB.NET.
You can emulate them with "while true" loops.
unsafe code
| Code Block |
|---|
static void WriteLocations(byte[] arr) {
unsafe {
fixed (byte* pArray = arr) {
byte* pElem = pArray;
for (int i = 0; i < arr.Length; i++) {
byte value = *pElem;
Console.WriteLine("arr[{0}] at 0x{1:X} is {2}",
i, (uint)pElem, value);
pElem++;
}
}
}
}
|