CSharp Similarities and Differences - vilinski/nemerle GitHub Wiki

This document lists some basic differences between Nemerle and C# in a terse form. If you know Java or C++ it should still be fairly helpful.

Changes In Expressions

C# Nemerle Remarks
```csharp const int x = 3; const string y = "foo"; readonly Object obj = getObject(); ``` ```nemerle def x : int = 3; def y : string = "foo"; def obj : Object = getObject(); ``` Variables defined with def cannot be changed once defined. This is similar to readonly or const in C# or final in Java. Most variables in Nemerle aren't explicitly typed like this.
```csharp int x = 3; string y = "foo"; Object obj = getObject(); ``` ```nemerle mutable x : int = 3; mutable y : string = "foo"; mutable obj : Object = getObject(); ``` Variables defined with mutable can be changed once defined. Most variables in Nemerle aren't explicitly typed like this.
```csharp var = 3; //Will compile. var y; y = "foo";//Won't compile. ``` ```nemerle def = 3;//Will compile! mutable y; y = "foo";//Will compile! ``` Nemerle's type inference is lightyears ahead of C#'s. If there is clear evidence of a variable's type, there's a 99% chance Nemerle will infer it.
```csharp int a = b = c; ``` ```nemerle def a = c; def b = c; ``` The type of the assignment operator is void.
```csharp value = cond ? var1 : var2; ``` ```nemerle value = if(cond) var1 else var2 ``` No ternary operator is needed as everything is an expression in Nemerle. The 'else' branch is mandatory here! (Don't panic! if-without-else has its own keyword.)
```csharp Class myClass = new Class(parms); ``` ```nemerle def myClass = Class(parms); ``` Nemerle doesn't require new when calling a constructor.
```csharp Book[] books = new Book[size]; ``` ```nemerle def books = array(size) : array[Book]; ``` Often the array type can be inferred and this is simplified; as in the next example.
```csharp Book[] books = new Book[size]; books[0] = new Book(); ``` ```nemerle def books = array(size); books[0] = Book(); ``` When the type can be inferred from context or later use (which is most of the time), you can drop the type declaration
```csharp int[] numbers = {1, 2, 3}; ``` ```nemerle def numbers = array[1, 2, 3]; ``` Initializing an array. Without the array keyword this would create a list.
```csharp int[,] numbers = new int[2,3]; ``` ```nemerle def numbers = array(2,3) : array.[2][int]; ``` Multidimensional array constructor. The type can usually be inferred from use and not declared.
```csharp int[,] numbers = { {1,2,3}, {1,4,9} }; ``` ```nemerle def numbers = [ [1,2,3], [1,4,9] ]; ``` Multidimensional array initialization.
```csharp new {Prop1 = 1; Prop2 = "string"} ``` ```nemerle using Nemerle.Extensions; new (Prop1 = 1, Prop2 = "string") ``` Nemerle anonymous types are a bit more flexible (e. g. can be generic or returned from a method). They must be imported from Nemerle.Extensions however.
```csharp new Class { Property1 = 1; Property2 = "string" } ``` ```nemerle Class() <- { Property1 = 1; Property2 = "string" } ``` The Nemerle Object Modifier macro is more powerful.
```csharp if(cond) answer = 42; ... ``` ```nemerle when(cond) answer = 42; ... ``` if without else is called when. Nemerle requires if statements to be paired with else for clarity.
```csharp if(!cond) answer = 42; ... ``` ```nemerle unless(cond) answer = 42; ... ``` In Nemerle, if(!cond) can use the clearer unless(cond) syntax. Of course, when(!cond) can also always be used.
```csharp if (cond) return foo; do_something (); return bar; ``` ```nemerle match(cond){ | true => foo | _ => {doSomething(); foo} } ``` Pattern Matching provides a clearer way of delegating control flow.
```csharp if (cond) return foo; do_something (); return bar; ``` ```nemerle using Nemerle.Imperative; when(cond) return foo do_something (); return bar; ``` Alternately the Imperative namespace may be imported. This is discouraged however.
```csharp try {...} catch (FooException e) { ... } catch (BarException e) { ... } ``` ```nemerle try {...} catch { | e is FooException => ... | e is BarException => ... } ``` Nemerle's somewhat different try ... catch syntax is consistent with its pattern matching syntax.
```csharp (type) expr ``` ```nemerle expr :> type ``` Runtime type cast, allows for downcasts and upcasts.
```csharp (type) expr ``` ```nemerle expr : type ``` Static cast, only upcasts are allowed.
```csharp using System; using SWF = System.Windows.Forms; using System.Xml; ... Console.WriteLine ("foo"); SWF.Form x = new SWF.Form(); XmlDocument doc = new XmlDocument(); ``` ```nemerle using System; using System.Console; using SWF = System.Windows.Forms; ... WriteLine("foo"); def x = SWF.Form(); def doc = Xml.XmlDocument(); ``` In Nemerle, you can apply the using directive to classes as well as namespaces. Opened namespaces allow you to drop the prefix of other namespaces, like System in System.Xml. More info.
```csharp using System.Windows.Forms;

Button button = control as Button;

if (button != null) ... else ...

</td><td>
```nemerle
match (control) {
  | button is Button => ...
  | listv is ListView => ...
  | _ => ...//something else
}
as can be simulated with match. It is a bit more to type up in simple cases, but in general Nemerle's construct is more powerful.
```csharp int y = x++; ++x; ``` ```nemerle def y = x; x++; ++x; ``` The ++ and -- operators return void, just like assignment. So, both prefix and postfix versions are equivalent.

Changes In Type Definitions

C# Nemerle Remarks
```csharp static int foo (int x, string y) { ... } ``` ```nemerle static foo (x : int, y : string) : int { ... } ``` Types are written after variable names.
```csharp class Foo { public Foo (int x) { ... } } ``` ```nemerle class Foo { public this (x : int) { ... } } ``` The constructor's name is always this.
```csharp class Foo { ~Foo () { ... } } ``` ```nemerle class Foo { protected override Finalize () : void { ... } } ``` There is no special syntax for the destructor, you just override the Finalize method.
```csharp class Foo : Bar { public Foo (int x) : base (x) { ... } } ``` ```nemerle class Foo : Bar { public this (x : int) { base (x); ... } } ``` The base constructor is called in the constructor's function body.
```csharp class Foo { int x; } ``` ```nemerle class Foo { mutable x : int; } ``` Fields which will be changed outside of the constructor need to be marked as mutable.
```csharp class Foo { readonly int x; const int y = 10; } ``` ```nemerle class Foo { x : int; y : int = 10; } ``` Read-only/const are used by default.
```csharp class Foo { static int x = 1; } ``` ```nemerle class Foo { static mutable x : int = 1; } ``` Static variable.
```csharp class Foo { static readonly int x; static int method() { ... } } ``` ```nemerle module Foo { x : int; method() : int { ... } } ``` A module is a class in which all members are static.
```csharp using System.Runtime.CompilerServices.CSharp;

class C { public object this [int i] { ... }

[IndexerName("MyItem")] public int this [string name] { ... } }

</td><td>
```nemerle
class C {
  public Item [i : int] : object 
  { ... }

  public MyItem [name : string] : int 
  { ... }
}
Indexers.
C# Nemerle
When two interfaces use the same method to perform different functions, different names can be given to each method.
```csharp interface SpeaksEnglish{ void Speak(); }

interface SpeaksGerman{ void Speak(); }

class GermanTransfer : SpeaksEnglish, SpeaksGerman{ public void SpeaksEnglish.Speak() {} public void SpeaksGerman.Speak() {} }

</td><td>
```nemerle
interface SpeaksEnglish{
    Speak() : void;
}

interface SpeaksGerman{
    Speak() : void;
}

class GermanTransfer : SpeaksEnglish, SpeaksGerman{
    public Speak() : void implements SpeaksEnglish.Speak{}
    public Sprechen() : void implements SpeaksGerman.Speak{}
}

Generics

C# Nemerle Remarks
```csharp class A { T x; } ``` ```nemerle class A [T] { x : T; } ``` Type parameters are written in square brackets [...].
```csharp typeof(A<,>); ``` ```nemerle typeof(A[_,_]); ``` typeof expression

New Stuff

Nemerle contains many constructs which are not present in C#. Unfortunately, most of them don't really fit into a side-by-side comparison format:

Other Minor Differences

Ambiguity Isn't Tolerated

namespace YourAttributes{
    class Serializable : System.Attribute { }
}
namespace MyAttributes{
    using YourAttributes;
    class Serializable : System.Attribute { }

    [Serializable] class SomeClass { }
}

C# compilers will choose MyAttributes.Serializable or, if its definition is commented out, YourAttributes.Serializable. Nemerle will raise an error telling you to be more specific about which attribute you want to use.

Exclusion of Overridden Methods

 class BaseClass
 {
   public virtual AddItem (val : string) :  void { }
 }
	
class TestClass : BaseClass
{
   public AddItem (val : object) :  void { }
   public override AddItem (val : string) :  void { }
}
 ...
   TestClass().AddItem ("a");  // C# will choose TestClass.AddItem (object)
                               // Nemerle will choose TestClass.AddItem (string)

This behaviour comes from section 7.6.5.1 of the C# specification, which states "...methods in a base class are not candidates [for overload resolution] if any method in a derived class is applicable (§7.6.5.1)." Unfortunately, this rule is patently absurd in situations like the above. The Nemerle compiler always chooses the method whose signature best matches the given arguments.

⚠️ **GitHub.com Fallback** ⚠️