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.
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