tags:

views:

490

answers:

2

There are some cool and exciting features in .NET 3.5/C# 3.0, and with those features comes some darn interesting ways to write the exact same line of code.

Using the above stated tool set (and by extension .NET 2.0 stuff), what are the different ways the below code snippet could reasonably be rewritten?

        string uploadDirectory = "c:\\some\\path\\";
        if (Directory.Exists(uploadDirectory)) {
            string[] files = Directory.GetFiles(uploadDirectory);
            foreach (string filename in files) {
                if (File.GetLastWriteTime(filename).AddHours(12) < DateTime.Now) {
                    File.Delete(filename);
                }
            }
        }
+9  A: 

Lambda:

if (Directory.Exists(uploadDirectory)) 
  Directory.GetFiles(uploadDirectory)
    .Where(f => File.GetLastWriteTime(file) < DateTime.Now.AddHours(-12))
    .Each(f => File.Delete(f));

Edit: On 2nd thought, you can avoid the security lookups on each File access by using DirectoryInfo and FileInfo instead of the static File methods:

var di = new DirectoryInfo(uploadDirectory);
if (di.Exists()) {
   di.GetFiles()
     .Where(f => f.LastWriteTime < DateTime.Now.AddHours(-12))
     .Each(f=> f.Delete());
}

And for those missing their own Each method:

void Each<T>(this IEnumerable e, Action<T> action) {
  foreach (T t in e) {
    action(t);
  }
}

To make this really crazy, and fit the C# 3.0 theme, let's throw in an anonymous type:

di.GetFiles().Select(f => new() {
   Delete = f.LastWriteTime < DateTime.Now.AddHours(-12) ? f.Delete : () => { }
}).Delete();

But that just doesn't make any sense. ;)

Mark Brackett
Well, you'd need to define Each, but yes ;-p
Marc Gravell
I think he meant ForEach instead of Each
Ray
Which also doesn't exist...
Marc Gravell
Who hasn't already defined Each themselves? IMHO, it's a no brainer that it should've been included. But, for the .NET FX purists, just call .ToList().ForEach if it makes you feel better. ;)
Mark Brackett
+3  A: 

Well, the first bit maps quite neatly to a LINQ query... but there is (deliberately) no ForEach in regular LINQ. We can annoy Eric and add one, though ;-p

So the following uses LINQ and a custom extension method - but we could re-write the exact same code (i.e. the same IL) as:

  • query syntax (as below)
  • fluent syntax (.Where().Select() ec)
  • explicit static (Enumerable.Where(...))
  • lambdas vs anonymous methods vs named methods (last changes the IL)
  • delegates with/without the abbreviated (C# 2.0) delegate "new" syntax
  • generic calls with/without generic type inference (Where() vs Where<T>())
  • call to File.Delete vs call to x=>File.Delete(x) etc

etc

static void Main()
{
    string uploadDirectory = "c:\\some\\path\\";
    if (Directory.Exists(uploadDirectory))
    {
        var files = from filename in Directory.GetFiles(uploadDirectory)
                  where File.GetLastWriteTime(filename) < DateTime.Now.AddHours(-12)
                  select filename;
        files.ForEach(File.Delete);            
    }
}
static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
{
    foreach (T item in items)
    {
        action(item);
    }
}

We could write the DateTime code with a custom Expression, but that would be overkill...

However, I doubt we could ever run out of ways of writing it ;-p

Marc Gravell
lol... good one.
Jason Whitehorn