Anonymous methods, unnamed classes, try catch blocks are all examples of these type of tools that when used improperly will kill the system performance, code readability, maintainability and extensibility.
We are specifically talking about C#. LINQ was specifically held as one of the improvements to the language. I am not quite sure what your point is relative to that.
There are shockingly few examples where LINQ is superior to alternatives. LINQ is the brute force technique of avoiding proper collections/algorithms.
Maybe you're refering to LINQ-to-whatever (LINQ to SQL, etc.), a LINQ generalization where you can quote your expressions, rewrite the AST and emit something else (a very constrained kind of macros, if you will).
MS is probably to blame here, but people keep conflating the two.
Take a block of code with LINQ in it and rewrite it minus LINQ but logically performing the same operations that the sugar is resolving to. To most developers it would offend the sensibilities of construction, but somehow in LINQ-land all seems fine.
What LINQ does is make your code more concise and readable. It makes it easier to find bugs and easier to understand by someone else (even if someone else is you, 6 months down the road).
It also just takes a lot less time to write.
So when you want to sort, search or transform a list, you prefer a technique which doesn't iterate over the items in the list at all? That makes no sense.
But I don't agree that LINQ is bad because someone on your team didn't know how to use a Dictionary and thought that iteration would be fast on large in-memory lists.
In many cases there are efficient LINQ constructs, e.g lazy lists, and First() not enumerating past the matching item. Hand-coding these is prone to doing it worse than Linq would. Teach your team how to use .ToDictionary() if need be.
Personally, I like LINQ a lot. I don't use it very much in my code (and usually it's for things like light filter or ordering), but it has these little things that save a lot of time.
Fine examples:
.ToList() materialization multiple times in a call graph. Ok so the thread is eating 200mb of ram?!?!?!
Generic method hell.
complete lack of understanding regarding IEnumerable, ICollection, IList etc.
O(log N) that doesn't go bang until you stick a production dataset in it.
The specification pattern - bottled rape is the only way I can quantify this. Sounds great until you have 2500 specifications and are stacking them 20 deep and your ORM decides it has had enough of clauses (EF4 bug).
My favourite: junior developer turns up and says "I wrote this awesome linq query - come and look!". Get there: all of the above.
I couldn't agree less. Any language construct can be abused, but LINQ is not particularly susceptible to abuse, unless you try very hard.
Because Java has been so conservative, people actively hate it's verbosity, boilerplate-ness, and lack of language features (anonymous functions, first class functions, etc.).
So Java has, for many years, helped huge teams of mediocre developers avoid certain kinds of self-inflicted wounds by being conservative in terms of language features. And the result seems to be that Java is increasingly scorned.
I know if I had to replace my C# work with Java, I'd feel incredibly frustrated at the lack of language power. In fact, I wouldn't choose to do it -- it would have to be a hell of a project or opportunity to pull me into it.
(Luckily for me, there are many better options, like Clojure or Scala on the JVM, or Haskell, Python, Ruby, etc. off the JVM).
List<List<Tuple<int, Dictionary<string, object>, string>>>
See also: "primitive obsession" http://c2.com/cgi/wiki?PrimitiveObsession http://sourcemaking.com/refactoring/primitive-obsession
It's in system.windows.forms isn't it? Don't really want that dependency and associated resolution being dragged in to a web app otherwise the compiler has to load the entire assembly's metadata.
Also, it requires full trust.
Oh and finally it isn't serializable.
Which is why we end up with SerializableDictionary<K, V> which is even longer and is an adaptor for Dictionary<K,V> which implements serialization.
That's why it all sucks.
And I haven't even included ConcurrentDictionary thread safety yet.
The whole thing is a fucking mess.
This 'cancer' is simply a data layer; if you use proper design patterns and seperate your layers correctly, you can surgically remove this tumour and replace it with another ORM.
Your comment on "where there is no noticeable performance hits" strikes a chord because when first used there are no noticeable performance hits. But then that application grows and scales and suddenly it is death by a million paper cuts, thousands of grossly inefficient set operations devastating performance. That's aside from the fact that LINQ is often a short-circuit saving from having to think about appropriate algorithms of object-methods to deal with the likely uses.
Take another example, anonymous functions in Javascript. I've seen plenty of tremendously horrible JS code bases that were just a deep series of nested anonymous functions. Almost impossible to debug or maintain. However, when used appropriately the anonymous function is very powerful and can make certain things much easier.