Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

CSharp Similarities and Differences

Alexander Zimin edited this pageMay 5, 2017 ·7 revisions

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

Changes In Expressions

C#NemerleRemarks
constintx=3;conststringy="foo";readonlyObjectobj=getObject();
def x :int =3;def y :string ="foo";def obj : Object = getObject();
Variables defined withdef cannot be changed once defined. This is similar toreadonly orconst in C# orfinal in Java. Most variables in Nemerle aren't explicitly typed like this.
intx=3;stringy="foo";Objectobj=getObject();
mutable x :int =3;mutable y :string ="foo";mutable obj : Object = getObject();
Variables defined withmutable can be changed once defined. Most variables in Nemerle aren't explicitly typed like this.
varx=3;//Will compile.vary;y="foo";//Won't compile.
def x =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.
inta=b=c;
def a = c;def b = c;
The type of the assignment operator is void.
value=cond?var1:var2;
value =if(cond) var1else 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.)
ClassmyClass=newClass(parms);
def myClass = Class(parms);
Nemerle doesn't requirenew when calling a constructor.
Book[]books=newBook[size];
def books =array(size) :array[Book];
Often the array type can be inferred and this is simplified; as in the next example.
Book[]books=newBook[size];books[0]=newBook();
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
int[]numbers={1,2,3};
def numbers =array[1,2,3];
Initializing an array. Without thearray keyword this would create a list.
int[,]numbers=newint[2,3];
def numbers =array(2,3) :array.[2][int];
Multidimensional array constructor. The type can usually be inferred from use and not declared.
int[,]numbers={{1,2,3},{1,4,9}};
def numbers = [ [1,2,3], [1,4,9] ];
Multidimensional array initialization.
new{Prop1=1;Prop2="string"}
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.
newClass{Property1=1;Property2="string"}
Class() <- {  Property1 =1;   Property2 ="string"}
TheNemerle Object Modifier macro is more powerful.
if(cond)answer=42;...
when(cond)   answer =42;...
if withoutelse is calledwhen. Nemerle requiresif statements to be paired withelse for clarity.
if(!cond)answer=42;...
unless(cond)   answer =42;...
In Nemerle,if(!cond) can use the clearerunless(cond) syntax. Of course,when(!cond) can also always be used.
if(cond)returnfoo;do_something();returnbar;
match(cond){ | true => foo|_ => {doSomething(); foo}}
Pattern Matching provides a clearer way of delegating control flow.
if(cond)returnfoo;do_something();returnbar;
using Nemerle.Imperative;when(cond)   return foodo_something ();return bar;
Alternately the Imperative namespace may be imported. This isdiscouragedhowever.
try{...}catch(FooExceptione){ ...}catch(BarExceptione){ ...}
try {...}catch {  | eis FooException => ...  | eis BarException => ...}
Nemerle's somewhat differenttry ... catch syntax is consistent with its pattern matching syntax.
(type) expr
expr :>type
Runtime type cast, allows for downcasts and upcasts.
(type) expr
expr :type
Static cast, only upcasts are allowed.
usingSystem;usingSWF=System.Windows.Forms;usingSystem.Xml;...Console.WriteLine("foo");SWF.Formx=newSWF.Form();XmlDocumentdoc=newXmlDocument();
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 theusing directive to classes as well as namespaces. Opened namespaces allow you to drop the prefix of other namespaces, likeSystem inSystem.Xml.More info.
usingSystem.Windows.Forms;Buttonbutton=controlasButton;if(button!=null)...else...
match (control) {  | buttonis Button => ...  | listvis ListView => ...  |_ => ...//something else}
as can be simulated withmatch. It is a bit more to type up in simple cases, but in general Nemerle's construct is more powerful.
inty=x++;++x;
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#NemerleRemarks
staticintfoo(intx,stringy){ ...}
static foo (x :int, y :string) :int { ... }
Types are written after variable names.
classFoo{publicFoo(intx){ ...}}
class Foo {publicthis (x :int)   { ... }}
The constructor's name is alwaysthis.
classFoo{~Foo(){ ...}}
class Foo {protectedoverride Finalize () :void  { ... }}
There is no special syntax for the destructor, you just override theFinalize method.
classFoo:Bar{publicFoo(intx):base(x){ ...}}
class Foo : Bar {publicthis (x :int) {base (x);     ...   }}
The base constructor is called in the constructor's function body.
classFoo{intx;}
class Foo {mutable x :int;}
Fields which will be changed outside of the constructor need to be marked asmutable.
classFoo{readonlyintx;constinty=10;}
class Foo {  x :int;  y :int =10;}
Read-only/const are used by default.
classFoo{staticintx=1;}
class Foo {staticmutable x :int =1;}
Static variable.
classFoo{staticreadonlyintx;staticintmethod(){ ...}}
module Foo {   x :int;   method() :int { ... } }
A module is a class in which all members are static.
usingSystem.Runtime.CompilerServices.CSharp;classC{publicobjectthis[inti]{ ...}[IndexerName("MyItem")]publicintthis[stringname]{ ...}}
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.
interfaceSpeaksEnglish{voidSpeak();}interfaceSpeaksGerman{voidSpeak();}classGermanTransfer:SpeaksEnglish,SpeaksGerman{publicvoidSpeaksEnglish.Speak(){}publicvoidSpeaksGerman.Speak(){}}
interface SpeaksEnglish{    Speak() :void;}interface SpeaksGerman{Speak() :void;}class GermanTransfer : SpeaksEnglish, SpeaksGerman{public Speak() :voidimplements SpeaksEnglish.Speak{}public Sprechen() :voidimplements SpeaksGerman.Speak{}}

Generics

C#NemerleRemarks
classA{Tx;}
class A [T] { x : T; }
Type parameters are written in square brackets [...].
typeof(A<,>);
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 {publicvirtual AddItem (val :string) :void { } }class TestClass : BaseClass {public AddItem (val :object) :void { }publicoverride 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.

Clone this wiki locally


[8]ページ先頭

©2009-2025 Movatter.jp