While the lambda pointer is certainly not the prettiest thing in the world, "x=> { CODE }" isn't all that different from "do |x| CODE end". You might prefer one over the other - and perhaps the Ruby one is easier to learn if you learn it first - but I don't think there is a big difference.
On the other hand, you're certainly right that the code I wrote is longer than yours. You are also correct that it ties itself to the Artist class, but that was because I was only exercising the use of C#'s version of blocks - not dynamic awesomesauce like method_missing. Method_missing is also possible to do in C# with .Net 4, as I'm sure you know.
A more complete rewrite of your example might be along the lines of:
//have to inherit from DynamicObject to get special dynamic treatment
public class DynamicXmlElement : DynamicObject
{
private XElement _element;
public DynamicXmlElement(XElement element)
{
_element = element;
}
//C# 4 equiv of method_missing
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if(_element.Element(binder.Name) == null)
return false;
result = _element(binder.Name).Value;
return true;
}
}
//changed this to use Action<dynamic>
public void ParseKey(XDocument doc, string elName, Action<dynamic> block)
{
foreach(var node in doc.Elements(elName))
block(new DynamicXmlElement(node));
}
public void Main()
{
var doc = XDocument.Load("..\db\music.xml");
ParseKey(doc, "Artist", artist=>{
Db.SaveArtist(artist.ArtistId, artist.Name);
Console.WriteLine(artist.Name);
});
ParseKey(doc, "Genre", genre=>{
Db.SaveGenre(genre.GenreId, genre.Name);
Console.WriteLine(genre.Name);
});
}
That said, yes, you can do this with less work/ceremony in Ruby as you've shown. I'm a big fan of Ruby and I'm glad you're showing MS devs what makes it so cool. I just don't want anyone to get the impression that some of these basic things are things that simply cannot be done in C#.