- In raw power and flexibility, I don't think there's a clear winner.
- MSBuild has the advantage of being "built-in" and that as Microsoft itself extends the compilation process (or brings more things into it, as is the case with, say the Workflow Foundation validation targets), it will have some stuff earlier than NAnt.
- NAnt, however, has a fairly extensive (more extensive, I'd say) set of tasks, if only because it has been around earlier and has a good community around it.
- Personally, I prefer NAnt's structure; I find it easier to read and maintain than MSBuild's one. This is pretty significant to me because build scripts can easily get fairly complex. Syntax itself is irrelevant here because both are XML dialects.
- Documentation for NAnt is, I'd say, far better than for MSBuild. In particular, I found MSBuild documentation to be pretty useless in general because what you will usually find documented is the API (raw methods and properties) of the MSBuild task classes, instead of documenting them in a way that more obviously maps to how you would actually use them in a build script.
- It might be wise sometimes not to choose one over the other, but instead have them collaborate.
- If you need multi-targeting support (that is, compiling a single code base against multiple framework targets), then NAnt is the clear winner here. NAnt's framework support is pretty good and it's very easy to create a build-script that can compile a single code based against .NET 1.1, 2.0 and Mono. MSBuild is rather lacking in this area (MSBee can help with .NET 1.1, but it really is a hack and a pain in the neck to use).
In general, I would say that if you're already familiar with NAnt, and can use it effectively and efficiently, there is little compelling reason at this time to switch. But if you're not familiar, then at least trying to get acquainted with MSBuild should be worth it.