Welcome to MSDN Blogs Sign in | Join | Help

C# 3.0 as Python with Braces

Python philosophy holds that "readability counts" and so after giving up the world of C++, templates, and STL one finds a calm bliss in the "obviousness" of most python code. C# made big strides in readability and the IDE-supported intellisense and refactoring made a big difference, but with the new features of C# 3.0 the difference is dramatic. At times it almost feels like "Python with braces". (Pythonistas: I make no claim whether Python with braces is a desirable thing.)

Let's take a look at real code. I translated some python code to C# to illustrate my point. The original IronPython code comes from here http://www.ironpython.info/index.php/A_Notify_Icon (the author is Michael Foord). I just copied it into VS 2008 and started translating.

What the sample does: creates a tray icon. Watches a folder. When files are modified in the folder, the tray icon shows a balloon.

image

On the left, python (IronPython of course). On the right C# 3.0 via Visual Studio 2008 Beta 2. 

Iron Python code C# code
# IronPython
import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import (
    Form, FormWindowState,
    NotifyIcon, ToolTipIcon
)

from System.IO import FileSystemWatcher

from System.Drawing import Icon

from System.Threading import (
    ApartmentState, Thread, ThreadStart
)


path = r"c:\path_to_watch"

def thread_proc():
    f = Form()
    f.ShowInTaskbar = False
    f.WindowState = FormWindowState.Minimized
    
    n = NotifyIcon()
    n.Icon = Icon(r"C:\path_to_icon\icon.ico")
    n.Text = "Watching" + path
    
    w = FileSystemWatcher()
    w.Path = path
    def handle(w, a): 
        n.ShowBalloonTip(10, str(a.ChangeType), 
                         a.FullPath, ToolTipIcon.Warning)
    w.Changed += handle
    w.Created += handle
    w.Deleted += handle
    w.EnableRaisingEvents = True
    
    n.Visible = True
    def handle(*args): 
        f.Activate()
    f.Shown += handle
    f.ShowDialog()


t = Thread(ThreadStart(thread_proc))
t.ApartmentState = ApartmentState.STA
t.Start() 

# Sleep for 90 seconds so that you can 
# see the notify icon in action
Thread.Sleep(90000)

# Then die...
t.Abort()

// C# 3.0
using System;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace ConsoleApplication1
{
    class Program
    {
        static string path = @"e:\foo";

        static void thread_proc()
        {
            var f = new Form();
            f.ShowInTaskbar = true;
            f.WindowState = FormWindowState.Minimized;

            var n = new NotifyIcon();
            n.Icon = new Icon(@"e:\foo\icon.ico");
            n.Text = "Watching Path";

            var w = new FileSystemWatcher();
            w.Path = path;

            FileSystemEventHandler handle1 = (sender, e) =>
            {
                n.ShowBalloonTip(10, e.ChangeType.ToString(),
                e.FullPath, ToolTipIcon.Warning);
            };

            w.Changed += handle1;
            w.Created += handle1;
            w.Deleted += handle1;
            w.EnableRaisingEvents = true;

            n.Visible = true;
            EventHandler handle2 = (sender, e) =>
            {
                f.Activate();
            };
            f.Shown += handle2;
            f.ShowDialog();

        }

        static void Main(string[] args)
        {
            var t = new Thread(new ThreadStart(thread_proc));
            t.ApartmentState = ApartmentState.STA;
            t.Start();

            //# Sleep for 90 seconds so that you can 
            //# see the notify icon in action
            Thread.Sleep(90000);

            //# Then die...
            t.Abort();
        }
    }
}

Notes on the translation

  • overall very straightforward
  • easy parts were adding the "var" keyword, semicolons, replacing the string literals
  • trickier was remembering how to setting up the lambda expressions for the handlers (ones need to find the strongly-typed delegate in order to create the lambda expression)
  • There are still python features that don't map as cleanly, but the basics look good.
  • Note that I did not even leverage the power of C# 3.0 extension methods which provide another capability that maps nicely to a python feature
Published Saturday, August 18, 2007 9:12 AM by saveenr

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# MSDN Blog Postings » C# 3.0 as Python with Braces

Saturday, August 18, 2007 1:14 PM by MSDN Blog Postings » C# 3.0 as Python with Braces

# re: C# 3.0 as Python with Braces

Nice post. Of course it shows off the benefits of IronPython better than the benefits of C#...

Saturday, August 18, 2007 2:32 PM by Michael Foord

# re: C# 3.0 as Python with Braces

Unfhortunately there is not much idiomatic Python in the original - probably because of the type of example chosen.

- Paddy

Saturday, August 18, 2007 4:02 PM by Paddy3118

# re: C# 3.0 as Python with Braces

I have never seen C# code. But I think it become like java which more powerfull. The python are more easier to understand but the only part def is function is very confusing.

Sunday, August 19, 2007 3:58 AM by hafizan

# re: C# 3.0 as Python with Braces

sorry but this doesn`t show anything you are writting SWF code in both languages,of course it looks the same.

if you tried to write something which do dynamic things like adding methods to a object and then calling them you just couldn`t do that in C#

Sunday, August 19, 2007 12:19 PM by Uriel Katz

# re: C# 3.0 as Python with Braces

You could have also used object initializers when creating some of the objects in C#:

var n = new NotifyIcon {

   Icon = new Icon(@"e:\foo\icon.ico"),

   Text = "Watching Path" };

Any idea whether IronPython has the same facility?

Monday, August 20, 2007 4:14 AM by JJ

# re: C# 3.0 as Python with Braces

Hmm, I don't know python to save my life so excuse me if this is a really dumb question but how does the code know you are done defining thread_proc()?

I understand the dialog will be modal when shown.  Does that somehow mean you are done defining a method?

Tuesday, August 21, 2007 4:57 PM by John

# re: C# 3.0 as Python with Braces

Whitespace is significant in python

the function def ends when the code is no longer indented.

Wednesday, August 22, 2007 11:22 PM by mgb

# re: C# 3.0 as Python with Braces

Python knows you are done because the indentation level changes. all the code belonging to thread_proc() is indented one tab and more.

So in this line:

t = Thread(ThreadStart(thread_proc))

you don't have any indentation and therefore you are at the same level as the function definition and therefore its body must be over

Thursday, August 23, 2007 1:41 AM by Max

# re: C# 3.0 as Python with Braces

"You could have also used object initializers when creating some of the objects in C#:

...

Any idea whether IronPython has the same facility?"

Yes, and without the superfluous declarations. :-)

n = NotifyIcon(

  Icon = new Icon("e:\foo\icon.ico"),

  Text = "Watching Path")

Wednesday, August 29, 2007 5:07 PM by Michael Foord

# re: C# 3.0 as Python with Braces

You're kidding? Formatting matters in python?  So now besides syntax and logic defects you need to worry formatting bugs?  

Almost sounds like an esoteric language to me...

Tuesday, September 04, 2007 2:44 PM by John

# re: C# 3.0 as Python with Braces

Of course formatting matters in Python is a good thing.

Consider this C# code :

if ( a < 0)

foo();

if (a > 0)

bar();

else

bazr();

Do you think this will not lead you to bugs, if you never indent properly ?

Do you always put your lovely braces exactly at the place you want... Are not they a source of bugs themselves ?

Friday, June 27, 2008 3:18 PM by Le Dave

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker