Depends on a lot of things, really.
As an example, when memory becomes an issue and a lot of temporary objects are being created I tend to use object pools. (Having a garbage-collector is not a reason to not take care of memory allocation). If speed is what matters then I might use unsafe pointers to work with arrays.
Either way, if you find yourself struggling too much with optimization techniques in a c#/.net application you probably chose the wrong language/platform.