Notes on C#
C#, judged by those with no musical knowledge to mean C++++, is Microsoft’s version of Java – which should say much about it. At a first glance, it has all the boredom of Java, but a closer inspection shows how much of the exotic fruit Kool-Aid of functional programming has been sipped. The result is what you’d expect: a holy mess. Here is how clean and intuitive the usual C# program is:
internal static sealed class RunOfTheMillClass {
internal static Func < Expression , string > SomeMethod () {
var Op = new Dictionary < ExpressionType , string > { { ExpressionType . Add , "+" } };
Expression < Func < int , int , int >> add = ( x , y ) => x + y ;
Func < Expression , string > toString = null ;
toString = exp =>
exp . Match ()
. With < LambdaExpression >( l => toString ( l . Body ))
. With < ParameterExpression >( p => p . Name )
. With < BinaryExpression >( b => String . Format ( "{0} {1} {2}" , toString ( b . Left ), Op [ b . NodeType ], toString ( b . Right )))
. Return < string >();
return toString ;
}
internal static Func < T , TResult > Uncurry < T , TResult >( this Func < Func < T , TResult >> function ) => arg => function ()( arg );
internal static Func < T1 , T2 , TResult > Uncurry < T1 , T2 , TResult >( this Func < T1 , Func < T2 , TResult >> function ) {
return ( arg1 , arg2 ) => function ( arg1 )( arg2 );
}
internal static Func < T1 , T2 , T3 , TResult > Uncurry < T1 , T2 , T3 , TResult >
( this Func < T1 , Func < T2 , Func < T3 , TResult >>> function ) =>
( arg1 , arg2 , arg3 ) => function ( arg1 )( arg2 )( arg3 );
internal static Func < T1 , T2 , T3 , T4 , TResult > Uncurry < T1 , T2 , T3 , T4 , TResult >
( this Func < T1 , Func < T2 , Func < T3 , Func < T4 , TResult >>>> function ){
return ( arg1 , arg2 , arg3 , arg4 ) => function ( arg1 )( arg2 )( arg3 )( arg4 );
}
}
However, if your background is Gang of Four and nostalgic for Factories of Factories, fear not: C# also has plenty of that good ol’ OOP. The commom place Java Hello World converts almost line per line – with the exceptions that we don’t need a different file for every single class, and must Name Like This:
public interface Subject {
public void Attach ( Observer observer );
public void Detach ( Observer observer );
public void NotifyObservers ();
}
public interface Observer {
public void Update ( Subject subject );
}
public class HelloWorldSubject : Subject {
private List < Observer > observers ;
private string str ;
public HelloWorldSubject () : base () {
observers = new List < Observer >();
}
public void Attach ( Observer observer ) {
observers . Add ( observer );
}
public void Detach ( Observer observer ) {
observers . Remove ( observer );
}
public void NotifyObservers () {
IEnumerator < Observer > iter = observers . GetEnumerator ();
while ( iter . MoveNext ()) {
Observer observer = iter . Current ;
observer . Update ( this );
}
}
public String GetStr () {
return str ;
}
public void SetStr ( string str ) {
this . str = str ;
NotifyObservers ();
}
}
public class HelloWorldObserver : Observer {
public void Update ( Subject subject ) {
HelloWorldSubject sub = ( HelloWorldSubject ) subject ;
Console . WriteLine ( sub . GetStr ());
}
}
public interface Command {
void Execute ();
}
public class HelloWorldCommand implements Command {
private HelloWorldSubject subject ;
public HelloWorldCommand ( Subject subject ) : base () {
this . subject = ( HelloWorldSubject ) subject ;
}
public void Execute () {
subject . SetStr ( "hello world" );
}
}
public interface AbstractFactory {
public Subject CreateSubject ();
public Observer CreateObserver ();
public Command createCommand ( Subject subject );
}
public class HelloWorldFactory implements AbstractFactory {
public Subject CreateSubject () {
return new HelloWorldSubject ();
}
public Observer CreateObserver () {
return new HelloWorldObserver ();
}
public Command createCommand ( Subject subject ) {
return new HelloWorldCommand ( subject );
}
}
public class FactoryMakerSingleton {
private static FactoryMakerSingleton instance = null ;
private AbstractFactory factory ;
private FactoryMakerSingleton () {
factory = new HelloWorldFactory ();
}
public static FactoryMakerSingleton GetInstance () {
if ( instance == null ) {
instance = new FactoryMakerSingleton ();
}
return instance ;
}
public AbstractFactory GetFactory () {
return factory ;
}
}
public class PatternfulClass {
public static void Main ( string [] args ) {
AbstractFactory factory = FactoryMakerSingleton . GetInstance (). GetFactory ();
Subject subject = factory . CreateSubject ();
subject . Attach ( factory . CreateObserver ());
Command command = factory . createCommand ( subject );
command . Execute ();
}
}
However still, C# enables poor typing discipline too – enter the dynamic keyword:
class Rubyish
{
static dynamic field ;
dynamic prop { get ; set ; }
static void Main ( string [] args )
{
dynamic expando = new ExpandoObject ();
expando . SomeNewStringVal = "Hello Brave New Whirrled!" ;
Console . WriteLine ( expando . SomeNewStringVal );
var p = expando as IDictionary < String , object >;
p [ "A" ] = "New val 1" ;
p [ "B" ] = "New val 2" ;
Console . WriteLine ( expando . A );
Console . WriteLine ( expando . B );
}
public dynamic AnotherMethod ( dynamic d )
{
dynamic local = "Local variable" ;
int two = 2 ;
if ( d is int )
{
return local ;
}
else
{
return two ;
}
}
}
I hope this short tour can wet your appetite for the large architectural choice offered by C#, bested maybe by only C++ or Scala. You can learn more by reading the .NET source reference .