Phillip Trelford's Array

POKE 36879,255

C# Light Syntax

Java and C# have somewhat reduced the ceremony over C++ by not requiring header files, but they are still both quite verbose. What would it look like if C# went one step further and adopted a light syntax like Python, where white space is significant?

Let’s start with an immutable Person class implemented in idiomatic C#:

namespace MyCompany.MyProduct
{
    public class Person
    {
        public Person(string name, int age)
        {
            _name = name;
            _age = age;
        }

        private readonly string _name;
        private readonly int _age;

        /// <summary>
        /// Full name
        /// </summary>
        public string Name
        {
            get { return _name; }
        }

        /// <summary>
        /// Age in years
        /// </summary>
        public int Age
        {
            get { return _age; }
        }
    }
}

Now lets extract the namespace, public modifiers, return statements and curly braces:

class Person

    Person(string name, int age)    
        _name = name;
        _age = age;    

    private readonly string _name;
    private readonly int _age;

    /// <summary>
    /// Full name
    /// </summary>
    string Name 
        get _name;    

    /// <summary>
    /// Age in years
    /// </summary>
    int Age 
        get _age;

Not too bad 30+ lines reduced to 20! But we could do more, what if triple slash comments were assumed to be summary text by default:

class Person

    Person(string name, int age)    
        _name = name;
        _age = age;    

    private readonly string _name;
    private readonly int _age;

    /// Full name
    string Name 
        get _name;    

    /// Age in years   
    int Age 
        get _age;

16 lines and dare I say it, no less readable!

Perhaps we could merge the class declaration and constructor to define a closure over the class members?

class Person(string name, int age)           

    /// Full name
    string Name 
        get name;    

    /// Age in years   
    int Age 
        get age;

9 lines and some might say the intent is actually clearer now!

Which incidentally isn’t a million miles away from what we can do with an F# class today:

type Person(name:string,age:int) =

    /// Full name
    member person.Name = name

    /// Age in years
    member person.Age = age
 

Or we could go one step further and take it down to just 1 line with an F# record:

type Person = { Name:string; Age:int }

It’s probably worth mentioning that both the F# class and record types can be consumed as classes from C# in exactly the same way as the original C# example.

So, if like me you’re a little bored of reading and writing verbose C# class declarations then F# might just be your thing!

Comments (16) -

  • Joe

    6/21/2011 3:20:35 PM |

    I agree the the 3 slashes meaning summary text, but don't forget C does support this context:

    class Person
    {
    Person(string name, int age)
    {
       Name=name;
       Age =age;
    }

    public string Name{get; private set;}

    public int Age{get; private set;}
    }

    which isn't that bad. Now it would be nice if you could default access to public instead of private

  • Joe

    6/21/2011 3:22:49 PM |

    i mean c#, not c Smile

  • Federico Lois

    6/21/2011 3:30:12 PM |

    Hardly a good example:

    public class Person
    {
        public string Name { get; private set; }
        public int Age { get; private set; }

        public Person ( string name, int age )
        {
           this.Name = name;
           this.Age = age;
        }
    }

    I like what F# brings to the table to the .Net development as it is a very natural syntax to define concurrent constructions. However, the use of barebones C# 1.0 is not fair for comparison purposes.

    @federicolois

  • Leo

    6/21/2011 5:11:57 PM |

    Significant whitespace is the tool of the devil.

  • Jonathan Allen

    6/21/2011 5:49:07 PM |

    > Now lets extract the namespace, public modifiers, return statements and curly braces:

    I would prefer you do it the other way and remove the redundant private modifiers. Marking something as public should be a concious choice, not the default.

    As for the rest, I find it interesting. I don't know if I want whitespace for block delimination, but it is worth talking about.

  • Phil

    6/21/2011 10:11:06 PM |

    Joe, federicolois,

    C# 3.0's auto-implemented properties are certainly more concise, and private set stops derived classes from setting the property. However they do not explicitly convey that the class is immutable after construction.

    MSDN on Auto-Implemented Properties: msdn.microsoft.com/en-us/library/bb384054.aspx
    Luca Bolognese on creating immutable value objects in C#: blogs.msdn.com/.../...-c-part-i-using-a-class.aspx
    Eric Lippert on Immutability in C#: blogs.msdn.com/.../...e-kinds-of-immutability.aspx

    Cheers,
    Phil

  • Phil

    6/21/2011 10:33:12 PM |

    Leo,

    Personally I find moustaches all over the place a little disturbing :{)

    www.cracked.com/.../

    Phil

  • Roger Lipscombe

    6/22/2011 3:10:43 AM |

    You're assuming that conciseness is the be-all and end-all of language design.

  • TechNeilogy

    6/22/2011 6:58:13 AM |

    Awesome.  F# and Python have made me a convert to significant whitespace.  In the C# example, I'd find a way to get rid of the trailing semicolons as well.

  • dude

    6/22/2011 2:02:03 PM |

    Not sure what's wrong with C# already in this regard:

    var person = new { name = "joe", age = 22 };

    Those properties are readonly and it's no more complex than one-liner as in your F# example.

  • Phil

    6/22/2011 11:29:09 PM |

    Dude,

    "Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first." - From MSDN on "Anonymous types in C#": http://msdn.microsoft.com/en-us/library/bb397696.aspx

    That said, you can't define methods, events, etc. on them. You also can't access the type information outside of the method they are defined in without resorting to reflection (although the dynamic keyword can help here).

    The F# Record type is not anonymous, it produces the same type as the original C# code, including automatically generating a constructor for you, and it can be extended with methods and events.

    There is a great introduction to F# Records on Wikibooks:
    en.wikibooks.org/.../Tuples_and_Records

    Thanks,
    Phil

    P.S. Enjoyed the irony of an anonymous post on anonymous types.

  • reno

    6/23/2011 6:53:33 PM |

    This is an awesome example and is motivating to continue trying to learn F# despite how hard it is to wrap my head around it atm.

  • Jon Harrop

    6/24/2011 8:06:11 AM |

    @Roger Lipscombe: Making an observation about brevity is obviously not "assuming that conciseness is the be-all and end-all of language design".

  • Mike

    6/24/2011 3:19:43 PM |

    In Scala all of this can be done in one line:
    class Person(var name:String,var age:Int);

  • Associator

    10/21/2011 7:42:21 PM |

    @Federico Lois and @Joe

    F# 3.0 has auto-properties with initial values something even C# doesn't support, so a mutable class with get and set properties is even more concise than in C#.

    See here: msdn.microsoft.com/.../dd483467(v=VS.110).aspx

    /// mutable class with auto-properties
    type Person(name : string, age : int) =
        /// Full name
        member val Name = name with get, set
        /// Age in years
        member val Age = age with get, set


    F# is not a 1-trick pony, it's a true general purpose multi-paradigm language.

Pingbacks and trackbacks (2)+

Comments are closed