I completely agree that Java's strengths really come to fruition when you're developing for heterogeneous systems and that's actually the purpose for which I really really like it and definitely advocate it over those who suggest you should resort to C++ and just compile multiple binaries for each system.
The problem is though many - I'm certain the vast majority of business actually just use Windows systems and in this circumstance it becomes harder to justify Java - C#'s advantage come to the forefront, even more so if the firm in question is fully invested in the Microsoft route - i.e. using SQL server as their database system, and Active Directory for account management. But ignoring that set of scenarios and looking at a system built on a Windows only network even if it doesn't need to work with AD or SQL Server (and this isn't an uncommon scenario) then that's the situation in which it really comes down to language vs. language much more.
Many of the new C# keywords like lock, using, and the LINQ constructs are actually shorthand for standard method style syntax and actually just get converted to exactly that by the compiler anyway. LINQ works based on extension methods, just in case you're not aware of them, very briefly, extension methods are methods that can be defined to act on existing types without modifying the code definition for that type. LINQ to objects for example works by adding methods like OrderBy onto the IEnumerable (which would have been better named IIterable IMO) interface such that it can be used to order any iterable collection. The following demonstrates an example LINQ query:
var query = from c in Cars
where c.Name.Contains("Focus")
orderby c.Name
select c;
This really just translates to:
var query = Cars .Where(c => c.Name.Contains("foo") .OrderBy(c => c.Name);
Effectively the methods just return a result of the same type (IEnumerable) and so you can just chain the extension methods onto each other. All LINQ does is convert it's syntax into this anyway. You don't even have to use the lambda syntax for parameters if you don't want either, you can equally use the anonymous method syntax.
Some C# programmers frankly prefer to avoid the LINQ syntax altogether and just use the extension methods, and there's actually good reason to do this too - if you want to extend the range of extension methods available then LINQ wont recognise that and so you'll end up with a mix of LINQ and extension methods anyway.
The lock keyword i.e. lock(x) { ... } to lock a variable in a multithreaded environment is really just shorthand for using the Monitor pattern:
Monitor.Enter(x);
try { ...
}
finally {
Monitor.Exit(x);
}
The using statement is just shorthand for previously prevalent IDisposable code, so using(var x = new x()) { ... } becomes:
var x = new x();
try {
statement;
}
finally {
if (resource != null) { (IDisposable)resource).Dispose(); }
}
So you can see a lot of the new syntax really needn't muddy your code if you're not keen on it, it's really just there to cut the amount of code you need to write, and in the case of LINQ may not even achieve that and you may resort to extension methods anyway.
If you're going to be building for heterogeneous systems then you've really no reason to give up on Java, but for me if I'm building a Windows only system then I use C#, and the reasons are that I genuinely find that the combination of Visual Studio + C# features let me do what I want to do faster. Some of this is down to the fact the .NET libraries are focussed towards that platform and so have that inherent advantage, but part of it is down to the language too. You touch upon the point of looking at the bigger picture and there's another issue here also for us- finding mid-level developers who will do the bulk of our work can be quite tough if we're looking for Java, there's a lot of fresh grads, and quite a few at the high end, but the middle-range here in the Yorkshire region of the UK is almost entirely dominated by C# and PHP programmers. Our London office will find it easier to get Java devs because they're much more prevalent in the city, but you'll find local talent pools tend to define choice of language as much as many other things - though I am interviewing for some interns soon and would suggest we do invest in training them to at least some extent towards languages we find it hard to recruit for, such as Java.
You're right that there's so many factors to consider and language is only a small one- there's business factors like ability to recruit, there's integration with existing platforms and systems, there's client preferences and any number of other things so yeah, certainly language debates are almost often just entirely academic.
But on that note for what it's worth I'm stuck on an inherited PHP project right now, and any discussions about Java vs. C# pale in relation to the horrors of the monstrosity that is PHP which is frankly, a truly terribly developed language, but at the end of the day I guess it's popular and it still just about works.