I am not sure what I am doing wrong, but using functional techniques improved my C# quite a lot.
The crucial thing about pure functional languages is that they decouple the logic of the program from the order of the computation. In an imperative language control flow and data flow are explicitly interleaved, with complex dependencies between the two. In many cases a particular bit of code is only correct if another bit of code has been executed previously, and its up to the programmer to keep track of all these dependencies.
In a pure functional language this coupling between data flow and control flow is broken because all the data dependencies are made explicit and visible to both the compiler and the programmer. That frees the programmer from bothering about it (and automating low level programming issues is always a Good Thing), and it also enables the compiler to optimise it. So for instance in Haskell the compiler will rewrite this expression
map f (map g xs)
into this map (f . g) xs
The first line would iterate through the list "xs", building up an intermediate result list by applying "g" to every element. It would then iterate through this intermediate list applying "f" and building up the result.The second line iterates through the list only once, applying "g" and then "f" to each element in turn. Haskell can do this because "f" and "g" are guaranteed by the type system to have no side effects, so it doesn't matter what order they are executed in. In impure languages the order of execution matters, so the compiler can't switch things around in this way without changing the meaning of the program.
The programmer also gets the benefit. If you see "x = complexThing" you can always replace "x" with "complexThing" and vice-versa anywhere that "x" is in scope, without changing the meaning of your program. That makes it much easier to reason about what your program does.