views:

23300

answers:

101

What are some common mistakes made by .NET developers, and how can we avoid them?

For example, trying to open a file without checking whether or not it exists, or catching an error unnecessarily.

Please look in to the list before posting new


Please justify your answer as well, if applicable and give examples.

+16  A: 

never publicly expose generic Lists - and this is why not.

flesh
Also, use IEnumerable<T> where appropriate (read only collections). It's always best to stick with the lowest interface possible.
TheSoftwareJedi
Good point, I never thought about that.
unforgiven3
You have to keep in mind a few things about the framework guidelines.They are designed for APIS used by millions of developers, where the inconvience they generate makes up for the massive expense that would occur if they were violated.Most classes written by most programers are ...
Scott Wisniewski
... only designed for internal use, or for use by at most a hand full of developers and a hand full of applications.In those cases, the cost of following the framework guidelines rarely justifies the inconvience.You have to take those recommendations in context.
Scott Wisniewski
Agreed with Scott. If you are not working on a reusable/public library (API) it's often too much of a hassle.
Pawel Krakowiak
This is nothing specifically to do with generic lists. Non-generic List is no better (obviously worse in most cases), nor is an array.
Daniel Earwicker
Earwicker, if you read the linked page, you can see what the parent poster is talking about. It boils down to this: If you use Collection<T> instead of List<T>, then you reserve the option of overriding the Collection<T>'s add/delete/replace behavior to send out events, do validation, etc.
Neil Whitaker
+167  A: 
Marc Gravell
This is great, and interesting how many of those represent language gaps. Structs could have been disallowed except in unsafe blocks (for interop), Equals/GetHashCode could have been part of an interface, non-private/non-internal fields could have been banned, we need better IDisposable support...
Daniel Earwicker
Structs do serve a useful purpose - but the terminology often makes people think of C structs, which are sooooo different.
Marc Gravell
Why do you think structs should be immutable? Aren't they often used as optimizations so you can pass small bits of data around on the stack instead of bothering the heap. Restricting structs to being immutable possibly means you're denying some further optimizations that could be made?
Scott Langham
Preferring immutability is a good guideline for reducing complexity because you can rely on immutable objects to not change their state. But.. is there any reason why designing immutable structs is somehow more strongly preferred to designing immutable classes?
Scott Langham
I found that reSharper lets you refactor between for and foreach - very useful for post-hoc optimization.
Dmitri Nesteruk
I did the Static-class-in-a-web-app error once. Never again! :-)
Rune Grimstad
What are the problems with struct?
dr. evil
@fm - the biggest problem is people making "mutable" structs, without realising the absolute chaos this can quickly cause. Oversized structs can put stress on the stack (and CPU, as it has to blit them often). Boxing is a minor pain point, but not as big as you'd imagine. But in most cases, people are thinking of them as "objects without methods", which is false on two different levels (they aren't "objects" as such, and can have methods). I commonly see people type `struct Person` etc; it should be a `class`. `struct` should be reserved for values only.
Marc Gravell
The only problem with static in a webapp is most web devs don't think in terms of web safety... this can also affect instances of static classes in libraries in web apps that aren't threadsafe. Saw about 4 major weirdness issues related to services w/ unsafe clients used statically. You can cut yourself with a knife, but its hard to be a chef without one.
Tracker1
@Tracker1 - I like the analogy. I think we agree *inappropriate* use is the problem. That is true of most things, of course - but with web the balance of inappropriate-to-appropriate (for static) is so heavily shifted.
Marc Gravell
What's wrong about static in web apps?? I use it all the time in http modules, http handlers, http applications together with a ReadWriterLock from System.Threading. It works great...???
Henrik
If you synchronize (via lock, ReadetWriterLock etc), then it will at least work... but many developers use static **without** any locking (and it works fine on their machine)... "scales to 1" ;-p But even *with* locking you need to be careful about the amount of blocking - if the locks are too long, you can cause big problems. But used **correctly** static can be fine... but it is rarely used correctly.
Marc Gravell
I agree with the struct advice. Structs have value type semantics, which can be confusing when you're expecting reference type semantics. You can pass an object reference to a method and access the object directly, but if you pass a struct, you're copying the struct and all of its fields, and any modifications within the method will only affect the in-method copy. This can easily lead to confusing bugs if you're not expecting it.
Kyralessa
I had a problem with a static variable in a web app once. The data in the variable suddenly being shared across sessions caused some headaches that took a little debugging to see what wasn't working as I thought it would work...
JB King
struct are usefull when the equality of an object is determined by its data. (Address for example)
Nicolas Dorier
True, but classes can have equality operators (etc) too...
Marc Gravell
I agree that structs should be immutable. Structs do have one unique feature that classes cannot offer: they are never null.They also have some small perks, like getting value equality without writing any code and better performance if they are very small. But I agree that a class is better in most cases.
Neil Whitaker
`int?` is a struct, and can be null (depending on how you define null) ;-p
Marc Gravell
int? is not a struct, int? is the same as INullable<int> which is an object.
Sekhat
@Sekhat - no, it **really** isn't. `int?` is *defined* as `Nullable<int>`; `Nullable<T>` is a generic struct (**not** an object). There is no such thing as `INullable<int>`, and even if there were if would be an interface, not an object. Even if it was - even though interfaces are *generally* treated as ref-types, there are some edge-cases where they are non-boxing. Note, however, that even though `Nullable<T>` **is** a struct it *is* excluded from the `: struct` generic condition, and has special compiler and runtime treatment for `null` etc. Bit it still remains a value-type / struct.
Marc Gravell
I was working off memory and meant Nullable<int> :P I didn't know it was a generic struct. :) Nor the rest of it. Well thanks for the info :)
Sekhat
+115  A: 

The most common error I make is starting to code without thinking first. I still catch myself doing it from time to time...

Does happen when I work outside the .net framework, too.

Another bad habit (which I successfully dropped) is swallowing exceptions:

 try
{
    //something
}
catch
{
    // do nothing
}

Understanding the pitfalls of exception handling took me some effort, but was worth the time I spent on it.

Treb
+1. I wish more developers would take more time to truly understand exception handling. It is one of the most misunderstood and abused features in the whole .NET Framework.
joseph.ferris
Oh yes, I have done my share of abusing it...
Treb
What is a recommended authority on .NET exception best practice?
Jimmy
don't use them unless you have to. They're like beer, good in moderation, but you can give yourself one nasty hangover if you have too many.
gbjbaanb
I'd appreciate if you elaborate on this one: I use it regularly and would love to know if I must get rid of it. Eg.: try { File.Delete(blah); } catch {} to avoid reporting an unlikely file deletion problem that user will not understand anyway.
Serge - appTranslator
@Serge: There are a few conditions where its ok to do so. In general its better to at least log the exception information, so if the program crashes you know where to look for the cause. See http://stackoverflow.com/questions/313839/what-is-the-best-way-to-write-event-log-entries for example.
Treb
I have been lobbying the management to make swallowing an exception without even a comment on why it's being swallowed a fireable offense. No luck yet.
James Schek
We had a guy that was upset that we would catch exceptions log them (via email or DB call) and then return an error from some of our libs, he wanted us to catch the exception, and then re throw it so another try catch could catch it vs. just checking what is returned
Bob The Janitor
+1 Had to waste lots of time fixing apps with random catch-alls. And the data inconsistencies they leave behind.
Andomar
@Bob The Janitor - I agree with that "guy". He is correct. Why swallow the exception in your libs?
Bobby Cannon
@Bobby Cannon: For a long time I was doing exactly that: Catching all exceptions and returning false in the catch block. This is what happens when you learn C and get to know exception handling by the way of 'there are soem new keywords you can use: try, catch and finally'.
Treb
This is Java-ish
SztupY
Occasionally I get forced to put in a catch with nothing happening. It always gives me a bad feeling. A recent example was displaying a tooltip on a grid, occasionally for some reason it would go out of scope and not get the correct row handle so I needed a cacth just to stop it crashing.
PeteT
Once I worked with a programmer that "swallowed" any logging exception in the code - horrible...
Eran Betzalel
Pokemon exceptions - when you just gotta catch 'em all.
vash47
+334  A: 
throw ex;

Instead of

throw;

The first example will reset the stack trace to the point of the throw, whereas the latter will maintain the original stack. This is crucial for debugging.

throw ex;

Is never right when being used to re-throw an exception.

TheSoftwareJedi
I hate when someone does that. Especially when I'm the one trying to locate the bug :(
Ruben Steins
+1 for this. I've been writing .NET code for years, and somehow never came across this. It explains a lot :blush:
ChrisA
I believe that even better is: throw new SomeOtherException( "More useful information", ex );
Mike Scott
@Mike Scott unfortunately in more cases that leads to a 10 layer deep complex arrangement of SomeOtherExcpetion("Useless or obvious information", ex[nested ex, ex, ex, ex, ex]);
TheSoftwareJedi
2Jedi. 10 layers probably indicates too much exception handling. I've been using "Throw newEx(message,ex)" since forever, and never have >1 inner one. Also, Throw can only be used inside the Catch block, not in a called private method, so it's hard to abstract out the tidyup after the first Catch.
ChrisA
@TheSoftwareJedi - lots of MS and 3rd party libraries do InnerException wrapping, it makes a lot of sense. So you just have to accept it as reality. The flaw lies with the debugger UI for exceptions - it should list all the exception objects conveniently instead of making you dig through the list.
Daniel Earwicker
I wonder how many people are aware that you can stop in the debugger when an exception is first thrown, or that you can walk the chain of InnerExceptions from the debugger UI (it's just not that obvious).
Daniel Earwicker
Yes, wrapping it up into a another exception is good practice - as long as you don't overuse this by putting it in every method 10 layers deep through your framework.
TheSoftwareJedi
Everything You Wanted To Know About Exception Handling but were Afraid to Ask: http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx
Mike Scott
@Mike Scott - Exactly. Here's the section from that long ass link that says what I'm trying to: "Between the 1st and 3rd forms, I suppose it depends on whether the intermediary can add important information by wrapping the original exception in a MyExcep instance"
TheSoftwareJedi
throw ex can be usefull, if you check you parameters by an underlying function for example. While dealing with interop'd dlls you often only get an bool as result and my require an errorcode, that needs to be translated... then a throw ex is useful.
BeowulfOF
@BeowulfOF correct, I was referring to the context where it is being RE-thrown. updated answer with that info. Thanks!
TheSoftwareJedi
Never experienced it, but would hate to!
Peter Morris
When your catch block is just outside of a call to a library that you do not have control of, e.g. a persistence framework, there does not seem to me to be much advantage in knowing the gnarly details of what went wrong inside it, as long as you retain the message they meant you to see (e.g. 'Error: UnexpectedRowCountUnclassified: The number of returned rows 0 did not match the expected count of 1.').
Nij
@Nij NO, NO, NO! :) if the try block contained multiple places where that error could have occurred, you wouldn't know which line it happened on. It NEVER hurts to maintain the original stack!
TheSoftwareJedi
@TheSoftwareJedi: I have ex.ToString() output in front of me that shows the line number inside the try block?! I'll still take 'my' way over what my colleagues do: catch (Exception) {}. That is to say, catch everything and don't handle it. I know there may be flaws in my approach (I know you are confident my ways are flawed :) but at least I am pretty sure I have improved on what was (not) there before. I hope you agree!
Nij
Ooops! Quite right. Here I go grovelling. The line number was for the throw not the line that caused the exception - but you knew that :) Perhaps I was fooling myself because this was a one-line try block. Hey - I'm learning :)
Nij
@ Nij: catch Exception ex, log, handle, etc, rethrow IF DESIRED using "throw;" NOT throw ex;". Cheers!
TheSoftwareJedi
It's still possible to loose the stack trace using throw; - see http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx
Kragen
I personally think this should come up as a complier warning as I see no good reason for it.
PeteT
Yes, I just fell for this trap and had to find this question to remember how to properly rethrow an exception. They should really make it a compiler warning to use `throw exc` inside of a catch block. It is ridiculously useless.
Earlz
Here's a great article that talks about the various kinds of exceptions, and how to treat them. "Let them bubble up to the top" is a good rule for some exceptions, but definitely not for all (e.g. file I/O operations): http://blogs.msdn.com/b/kcwalina/archive/2007/01/30/exceptionhierarchies.aspx
Kyralessa
@TheSoftwareJedi, I never knew this. Is there any equivalent problem/solution in Java? Though there we're always wrapping in RuntimeException :)
Yar
Resharper warns you if you do this.
Carra
+38  A: 

1 - Some of us don't use using. Use using where ever possible

using (StreamReader reader=new StreamReader(file)) 
{ 
 //your code here 
}

2 - Forgetting to check if something is null, instead of trying to catch a null condition when an exception occurs

//This might throw an exception
string val=obj.Value.DomeSomething()


//Better, check for null

if (null!=obj.Value)) { 
 // Do your stuff here 
 }

3- Forgetting to check for null after a runtime type cast

   MyType t= x as MyType;
   if (null!=t) { 
      //Do stuff here 
    }

4- Where ever you are allocating something in try block, make sure you've a finally block to release stuff.

amazedsaint
If obj.value == null, then obj.Value != myval (unless myval == null), so your extra check is unnecessary. Also the if(rhs == lhs) pattern (e.g. null == x, instead of x == null) is unintuitive and unnecessary in C#, since if(x = null) is not valid in C#.
P Daddy
BobbyShaftoe
Clarified the intent of the comment
amazedsaint
May I ask why you opt for `null != x` as opposed to `x != null`? Seems like a [Yoda Condition](http://stackoverflow.com/questions/2349378/new-programming-jargon-you-coined) if you ask me!
David Foster
+37  A: 

I am sure that I have more. These are more like my current "Top Pet Peeves":

  • Not properly disposing of disposable resources. The using() keyword should be used with every object that implements IDisposable. Considering the code compiles to the equivalent of a try / finally that properly disposes of the object provides cleaner and safer code.

  • Catching Exception instead of a specific exception. Not only that, but seeing code where every single method has the entire body inside of a big try / catch. You should only ever catch exceptions that you can handle and are expecting. Add a top level handler to catch unhandled exceptions.

  • Seeing exceptions used to control program flow. If an exception is thrown, it should not be swallowed or used to initiate another set of logic that would not happen for any other reason.

joseph.ferris
"compiles to the equivalent of a try / catch" - a try/finally actually.
Joe
Yes, Joe. Thank you. I'll update the post! :-)
joseph.ferris
Catching `Exception` is fine as long as it is only for logging purposes, and you are going to re-throw (`throw`, not `throw ex`).
Marc Gravell
@Marc - Yes. That is why I said that you should use a top-level handler for unhandled exceptions.
joseph.ferris
But in some cases that generate a lot of unknown exceptions (when you're interacting with external data) you will often need the context of what you were doing at the time (use a local try/catch) but not know what exception it will throw (catch a general exception)
Yes, but that is why Microsoft provides inheritence in their exception model, as well. You don't need to know the exact exception all the time. For example, FormatException can be caught and catches FileFormateException, CookieException, etc. There are scenarios, but they are uncommon.
joseph.ferris
Catching the general exception "generally" is fine as long as it's handled at the topmost level of the code (IE the main method, top level UI event handlers). Also catching the general exception should always be followed by logging or displaying an UI message whiteout continuing execution flow.
Pop Catalin
Using exceptions to control program flow isn't bad idea. Exception IS NOT an error, exception is just NOT-STANDARD behaviour. Don't afraid exceptions. I had situations where using exception made code 100 times more elegant than checking returned value for null and then checking value itself.Here's simplified example. Your method must parse file to some data hierarchy. Throw an exception if the file wasn't found or if content of file didn't match expected format (maybe different exceptions). If would be much more clearly than returning null. Of course your exceptions must have meaningful type.
Dmitry Lobanov
+150  A: 

not using a using statement to ensure that Dispose() is called.

Greg Dean
Hah! Try missing a Dispose() on a mobile device and see how long your app runs before it pukes. Been there, missed that. ;)
Mat Nadrofsky
This is very important for Dialogs as they are not normally disposed of by the garbage collector.
Chris Porter
I'm not sure how preferring "using" over calling "dispose" is necessarily much better or will necessarily solve the problem. Don't get me wrong "using" is good practice.. but if you are going to forget to dispose of something, aren't you likely to forget the "using" block anyway?
BobbyShaftoe
@BobbyShaftoe - think about the effect of exceptions. You should at least use try/finally to ensure that Dispose is definitely called. Using statements are a more convenient form of that patter.
Daniel Earwicker
The trick is to put a Debug.Fail in a conditionally compiled (#if DEBUG) finalizer, and GC.SupressPendingFinalizers() in Dispose. Then you'll catch it at runtime, in DEBUG.
Jay Bazuzi
@Jay Sounds like the real tricky part is being able to control the source for all of the IDisposable type that you use, or you subclass them all. I suspect most people do not have this luxury.
Greg Dean
I wish they would modify the syntax to allow one using to dispose multiple objects. I often get SQL statements disposing of the connection, command and dataadapter causing lots of nesting.
PeteT
@BobbyShaftoe: Calling `StreamReader.Close()` can easily be forgotten or accidentally be deleted whereas it is hard to accidentally remove the `using()` block's curly braces.
Marius Schulz
+8  A: 
  • Using View State instead of Control State. View State saves everything, where as control state saves only the information needed to operate the statefull control on the statelessweb enviernment.
  • Not using paterns such as MVP in order to reduce coupling.
  • Having too much logic in the view instead of the domain objects.
Charles Graham
+96  A: 

Deploying your ASP.NET applications to production with Debug="true" set in the web.config. The compiler can't do any optimizations, and batch build is disabled. When we used to debug performance problems, this was one main area we'd look at. Tess has a great article on it.

It's so common, there is a built-in command to the SOS extension to WinDBG. Just get a memory dump of an ASP.NET application and run:

!finddebugtrue

which would output something like:

0:016> !finddebugtrue

Debug set to true for Runtime: 61b48dc, AppDomain: /MyDebugApplication

Debug set to true for Runtime: 1f50e6d8, AppDomain: /MemoryIssues

Total 16 HttpRuntime objects

Tess' article above has more examples.

Cory Foy
+1 because I do that too often...
Andy May
While I generally agree with that, I think that having a detailed stack trace when an exception occurs (namely, the line number) is **very** valuable, therefore I usually leave debug="true".
Dario Solera
I've done that a couple of times.... i'm going to have a look to see what sort of performance impact is has now.
GordonB
Dario - You can still output PDBs even with debug turned off. For any production application, you really should never deploy with Debug=true. There are much better ways to troubleshoot your apps without taking the performance hit.
Cory Foy
Can you get the line numbers if it's a Web Site with debug="false" as opposed to a Web Application?
Min
System admins should really add this to machine.config on production/live servers:<System.Web> <deployment retail="true" /></System.Web>This over-rides any debug="true" settings in web.config
Dan Diplo
@Dan Diplo thanks for the tip I have been doing it manually.
PeteT
+106  A: 

Use this cast:

Tree tree = obj as Tree;

... only if the program logic is such that you anticipate obj may or may not be of type tree.

In the situation where you expect that obj will only ever be of type Tree, prefer this style of cast:

Tree tree = (Tree)obj;

Prefer a (TargetType) style cast unless you really do need to make use of the conditional functionality offered by an 'as' cast.


Note: be sure to follow an 'as' cast with an 'if' or other appropriate logic to ensure that if the result of the 'as' was null, an attempt won't be made to dereference it. This is a mistake:

Tree tree = obj as Tree;
tree.GrowBranch();   // Bad. Possible NullReference exception!

In this case, the programmer meant one of these:

// Expected obj always to be a tree
Tree tree = (Tree)obj;
tree.GrowBranch();

// Expected obj could be a tree or could be something else
Tree tree = obj as Tree;
if( tree != null )
{
    tree.GrowBranch();
}

Some people believe that...

Tree tree = (Tree)obj;

...is bad because it may throw an exception if the prerequisite that obj is a Tree isn't met. It's not bad though, because it will throw an InvalidCast exception. That's the right sort of exception and is thrown at the right time.

The NullReference exception that occurred after the 'as' cast in the first GrowTree() example gets thrown:

  • When the real cause of the problem was not a null reference, it was an invalid cast.
  • Some time after the real problem (the bad cast) occurred.

These two reasons make it more difficult to debug and determine what the real problem was.

The performance if these two types of cast is similar. It is true that a (TargetType) style cast throws an exception if the cast fails. However, this is not a problem that would affect performance. The reason is that we use a (TargetType) style cast only when we expect the cast will always succeed. So, no exception should ever be thrown! If an exception does get thrown, then there is a problem in the logic/design of the code. Fixing a problem like this by changing the (TargetType) cast into an 'as' style cast is probably wrong as it will probably just mask the real cause of the problem.

Using the 'as' cast instead of the (TargetType) cast because you think it looks prettier is not a good reason for writing incorrect code.

Writing:

Tree tree = obj as Tree;
if( tree != null )
{
    tree.GrowBranch();
}

every time you need a cast, "just to be on the safe side" is absurd. You have to stop somewhere, otherwise one day you'll find yourself writing:

if( thisComputersPowerHasFailed )
{
    SendEmailToAdministratorToSaySomethingHasGoneWrong();
}

Code like this introduces more and more conditional execution paths through your code. Every time you write some code to cope with a case that you don't expect should happen, you will increase the complexity of your program. Unnecessary complexity is just the kind of thing that causes bugs to slip in to code. The root causes of bugs will be tricky to find because they'll be hidden behind other unnecessary error handlers that try to hide or log the problem and carry on. A (TargetType) cast adheres to the generally good advice of writing code to fail-fast.

Scott Langham
totally agree. the direct cast shows a programmer assertion and gives a more understandable exception on error.
TheSoftwareJedi
-1, cause obj as Tree is much faster, even including the necessary if(obj != null). On failing this is faster although since exception raising costs really much time.
BeowulfOF
-1, I agree with BeowulfOF, performance wise it makes more since to do the "as" because you can always test for the null and not have to worry about it blowing up and than having it throw an exception.
Donny V.
BeowulfOF - this is a myth. "obj as Tree" is *not* much faster if the cast succeeds (only if the cast fails and you save throwing an exception).
Joe
Agree with Jedi. If its gonna fail anyway, make it fail as early as possible, with the most relevant exception/message...
Arjan Einbu
I agree with Scott here +1 .. When you do a as you always risk passing around a null object that may rise a NullPointer later on (masking where that null came from). Use "as" if you expect nulls as ok input, but if the null is an exception to you, let it throw one!
Tigraine
Exceptions are for exceptional cases only, not program flow.
John Sonmez
John Sonmez, exactly. The "as" keyword isn't just there to make Anders feel better about himself.
BobbyShaftoe
Many methods in the BCL have a Try version. "as" is like "TryCast". If you know the cast may not work, use 'as'. If you'd regard a failed cast as indicating a bug in your code, do a normal throwing cast.
Daniel Earwicker
@Jedi, Tigraine: Exactly... you've hit the nail on the head, the exception will be for a failed cast, instead of for a null exception occurring sometime later that is tricker to track down.
Scott Langham
Note.. I wasn't saying never use 'as'. 'As' is perfect if you anticipate obj might not be a Tree... just remember the appropriate 'if' afterwards so that code can be written to deal correctly with the two possible conditions (obj being a Tree and obj not being a Tree).
Scott Langham
It's unfortunate that the C# language designers decided to use the C-style syntax for casting. It *is* ugly.
Jay Bazuzi
You should use the 'as' variant. Don't C-style cast.
sixlettervariables
Agree with Arjan -- fail fast
Jason Slocomb
I disagree - C style cast is generally a bad idea. A common source of bugs is when programmers cast to an expected type and an exception is thrown when they are wrong, crashing the program. Much better to use "as" and a check for null - as well as focussing the programmer on handling the wrong-type case properly, it's more efficient than using a try/catch around your cast.
Jason Williams
@Jason. I didn't say anything about putting a try/catch around the cast... although I'd expect you to have at least hooked the UnhandledException event for you application so you can log the failure. The two types of casts perform about the same. Try/catch isn't slow.. but throwing an exception is. And one shouldn't be thrown if you're using a non-as cast, if you're expecting an exception... use the 'as' cast.
Scott Langham
@Jason. Also. I can't imagine how you'd handle this error. If a non-as cast fails, then there's a problem with the application logic. All you can do is log the exception and then terminate the application. It would be a mistake to let the application continue because it would be running in a non-deterministic state, and there's no knowing what damage it could cause. One thing you could do in a handler is throw an exception, but then why would you bother writing this handling logic when you could have written a non-as cast that would have done that for you.
Scott Langham
-1. You need to consider the situations that you're casting in. You will not always want to throw an exception when a 'cast' doesn't work. Effective C# goes into this in some detail. The way to use 'as' here is to use the fact you can examine tree to see if it is null or not: Tree tree = obj as Tree; if (tree != null) {tree.GrowBranch();} else {//whatever}. This gives you more control than relying on catching exceptions.
Martin Clarke
@Martin. I agree with you entirely. In the answer, I said an 'as' cast is perfectly acceptable for the type of situation you've described. I did not say never use the 'as' cast, which is what a lot of people seem to think is what I said. Maybe I'll edit the answer to make that clearer.
Scott Langham
So true; I often have to catch myself before I type something like `Tree tree = obj as Tree; if (tree == null) throw new Exception();`.
MiffTheFox
Thoroughly agree with this answer. Strongly disagree with those suggesting using the 'as' operator. To reword the posting "Don't use as for conditional casts where the type conversion is part of the function's contract". In the above example part of the function's contract is that 'obj' if of type Tree. You should not be writing additional code to attempt to 'avoid' broken invariants. However, what you sometimes do want to do is also add explicit precondition checks
Phil
Thank you for the thorough explanation for your recommendation. As a newbie, I appreciate hearing the reasoning behind it.
PRINCESS FLUFF
Yes! Yes! Yes! Finally someone mentions this shitful construct that plagues so much sample code and even production one too.. :(
Andrei Rinea
I can't for the life of me figure out the reasoning that goes on in the heads of the downvoters here. Using 'as' plus an if-check is actually equivalent to saying "it's okay for this cast not to work". But generally, the cast is supposed to work and if it doesn't, there's a bug. To say that, use the C-style cast. That's what it's there for. I'd hate to work in their code where invalid behavior is swept under the rug to avoid an exception.
siride
+107  A: 

Not unhooking event handlers appropriately after wiring them.

This is because each event registration causes a reference to be created from the event source to the object/delegate that handles the event. These references can easily form part of a path of references from a root heap object to the handler.

Any object that has a path of references from the root heap object will not be garbage collected.

Scott Langham
I was typing the same thing when you posted yours!
TheAgent
In my opinion this is one of the biggest things - people just assume the magic garbage collector will take care of things. If you understand the event system in .NET, you know painfully well that that is not true.
unforgiven3
Circular references are garbage collected. I assume you meant hidden live references which a lot of developers don't realize is what you get when you hook up an event handler.
Stephen Martin
Stephen is correct - circular references *are* GCed properly.
RoadWarrior
Actual problem is very simple - if you want your object to be collected, don't add it to some list that will live for the entire process lifetime. Registering with a static event (or an event on your main window) is an example of this.
Daniel Earwicker
@Stephen: Thanks for the correction. I've corrected the answer.
Scott Langham
+1 because I got stung by this.
geofftnz
Don't forget: (Apart from forms objects) your dead object will still be called when the event is raised, causing all kinds of bizarre effects and leaving programmers wondering why they "seem to have two of everything even though there is only one instance of their class".
Jason Williams
Oh yeah this is a big one. I sort of wish weak events were the default, though that has its own problems too.
Rei Miyasaka
It's so frustrating that I can only upvote you once..
Andrei Rinea
+30  A: 

Locking on this is always a nice one. Not immediately fatal but a good way to get deadlocks.

Mendelt
assuming "this" is a public type... just sayin'...
TheSoftwareJedi
yep, use System.Threading.Monitor.TryEnter() and System.Threading.Monitor.Exit() instead.
vitule
why use monitor when you can lock on a private object?
Jimmy
I always create an individual readonly private object to lock on for each logically-separate lock. With Monitor.TryEnter()/.Exit(), it can be easy to fail to unlock when intended, especially when an exception is thrown.
Spodi
Agreed. A shame that [MethodImpl(MethodImplOptions.Synchronized)] and field-like-events both do exactly this.
Marc Gravell
afaik lock actually uses Monitor.Enter and Monitor.Exit. I tend to use Monitor directly because this enables you to do use TryEnter and Wait too.
Mendelt
I don't lock(this), but I don't see why it would cause a deadlock any more than lock(SyncRoot)
Peter Morris
If you lock on something that's publicly accessible (Microsoft uses lock(this) a lot in examples but locking on a publicly accessible SyncRoot is just as bad) you can easilly get deadlocks when other code locked the same object.
Mendelt
Got advice from my concurrency teacher that public synchronized void M() { /* mod internal state */ } is completely acceptable and he got verbally angry with me for even dragging up such a stupid issue not affecting real code (obviously this is the same as locking on this). Don't go to Imperial College Computing, they don't know their stuff :P.
Henrik
+27  A: 

One of the most dangerous pitfalls:

Creating a temp object, using its events by utilizing AddHandler (in VB) and then forgetting to remove those handlers. One would think that the object is collected by Garbage Collector when it goes out of scope, but it won't since there is still a pointer to that object (a function pointer) and GC won't clean it up.

You will also notice that the event handler hits many times. Once for every object you've created, used its events, and forgot to remove it. In addition to memory problems, this would cause your app to run slower and slower while it is working because the code in your handler would execute multiple times.

Just realized this problem because of performance issues of my app.

TheAgent
+1 this is good advice, and is often overlooked, IME.
hmcclungiii
This has caused us some serious issues in the past. Can't upvote it enough.
Jeffrey
Been there, done that! And I have learned from the experience.
Stefan
+14  A: 

Raising an event without first checking if it's null: ie:

public event EventHandler SomethingHappened;

private void OnSomethingHappened()
{
   SomethingHappened(this,new EventArgs()); //if no one hooked up to this event, it'll blow up
}
BFree
This is C# specific issue, VB.NET RaiseEvent will check it for you. Or is it something else I'm missing?
dr. evil
I'm lazy, so I write: public event EventHandler SomethingHappened = delegate{};There, now something is *always* hooked up to it!
Joe
@Joe: And your calls to otherwise unsubscribed event handlers will take 2 times longer than if you'd just checked for null and not default subscribed. Your calls to otherwise single-cast event handlers will take 3 times longer (excluding time within the actual handler, of course).
P Daddy
The performance does not really matter for = delegate{}; (see http://mafutrct.wordpress.com/2009/07/08/firing-c-events-without-manual-null-check/). IIRC, setting it = null explicitly is impossible at all.
mafutrct
I think you should also copy the event handler reference before test if it is null to avoid problems with race conditions. For a further discussion on this topic check http://stackoverflow.com/questions/786383/c-events-and-thread-safety question.
Carlos Loth
+17  A: 

Change the name of a property without carefully checking if it is used in data binding.

Properties are used for databinding. Unfortunately the binding mechanism in Windows Forms and WPF use the property name as string. If you change the name of a property, you will not get any compiler error or warning, only a runtime error if you are lucky.

nruessmann
shhh .. we're all supposed to believe in the dynamic language propaganda and eschew any nonsense about compiler errors. :)
BobbyShaftoe
Doesn't refactoring from the IDE solve this problem?
dar7yl
dar7yl, no it doesn't, because when you bind a property, you refer to it by name, in a string. IDE refactoring won't even replace literal strings, and of course they don't even have to be literals anyway.
Blorgbeard
The same with object data source in webforms. I guess there have to be workarounds through extension methods.
Arnis L.
The rename refactoring in Visual Studio *can* be set to look in strings. Which isn't an ironclad guarantee, but helps, at least.
Kyralessa
a solution to this issue, here : http://stackoverflow.com/questions/1329138/how-to-make-databinding-type-safe-and-support-refactoring/1329275#1329275
Toto
+246  A: 

I always get hung up on this one.

string s = "Take this out";
s.Replace("this", "that");  //wrong

oooops didn't actually change s....

s = s.Replace("this", "that");  //correct

Its pretty easy to make that mistake.

John Sonmez
Dude, that ALWAYS happens to me, but only with Replace! With SubString and the like, that never happens, but with Replace that ALWAYS happens to me!
BFree
Yeah it's an easy mistake to make, String is immutable so remember that you can never modify the contents of a String, just reassign the value to another String.
weiran
Really nice that it is this way though.
corymathews
It would be nice if Visual Studio warned you about this type of mistake.
Uhall
It would be nice if there were a "Code has no effect" warning for that sort of thing.
Kyralessa
FxCop will catch this problem, warning you that you're ignoring the return value.
jalbert
Yeah, the compiler can't be your babysitter. But jalbert is right, this is just calling a function and not doing anything with it's return value .. tools like FxCop do the job.
BobbyShaftoe
The compiler ought to error if you discard the return value of a function unless you prefix the call with (void). Valid reasons for ignoring return values are so unusual that it would have be worth the minor inconvenience. Too late now.
Daniel Earwicker
I find this one particularly confusing because String.Replace leaves String intact and return the modified result, whilst Array.Reverse works in-place and returns void...
Dylan Beattie
This one got me a couple of times, too.
Dmitri Nesteruk
hah yeah that one gets us all at one time or another, worst thing is makes you feel so stupid for doing it, its good to know there are lots of developers out there as dumb as me!
Agile Noob
i do this at least once a week, lol
Neil N
i used to get stung by this one... lol
GordonB
I did this just today actually! But with Remove() and Insert() instead! ;P
MiffTheFox
It makes sense as long as your remember that strings are immutable.
Hermann
I was doing this just the other day. I like the way it is though, having to reset the variable to keep the same identifier.
Chet
Makes me long for `gsub` and `gsub!` in Ruby. The former does like C#'s `Replace`, not modifying the calling string. The latter, with the exclamation mark, is destructive: it modifies the string that calls it.
Sarah Vessels
I always make this mistake too - glad I'm not alone! Wonder if you could write an extension method that actually worked like this, though?
Dan Diplo
I did it like 100 times LOL
martani_net
I always found the "immutable" concept confusing, because if you do `s=s.method()` then you HAVE changed the original string.
DisgruntledGoat
@DisgruntledGoat: No. You've given s a new referent; the original referent is unchanged. That's immutability.
Jason
This happened to me all the time when I first learned C#!
Dinah
i've done it too, many a time. But ever since i really pondered what immutability meant for an object, i haven't made the same mistake. Why is that so important? Because when you really think about what immutable means (http://en.wikipedia.org/wiki/Immutable_object) it really sinks in. Later you see a string object and you call one of its methods that is supposed change the object's state, your "immutability" sensitivity should fire and tell you: "Hey! There's gonna be a string returned from this method that you need to use! Ain't nothin' gonna happen to this string at all!"
Paul Sasik
Sometimes discarding the result of a function call makes sense. For example, List.Remove(..) and StringBuilder.Append(). Very often, we don't care about these results. What we need is a way to distinguish between functions where it does and does not make sense to ignore the result. If we can't change the syntax of C#, we could add an attribute to the function. Also, if the compiler could see that a class was immutable (e.g. with another attribute), it could issue a warning when we ignore results, although there may be false positives, like WriteValuesToConsole().
Neil Whitaker
I also think there should be some kind of standard (maybe possible in naming conventions only) regarding methods on immutable vs mutable objects. For example this method could be called s = s.GetReplaced("monster", "zombie") or (as such methods are chainable) s = s.WithReplaced("monster", "zombie").WithReplaced("chainsaw", "pump gun"). Also immutable collections should have an API that is different from mutable ones and adhere to some standard e.g. myFavoriteMovies = myFavoriteMovies.WithAdded("Night of the Living Dead").WithAdded("Friday the 13th").WithRemoved("Titanic");
herzmeister der welten
Everyone forgets that strings are immutable.
fastcodejava
@Earwicker: There are valid reasons for disregarding the return value from a method, sometimes. Better to emit a warning than an error.
Chris Charabaruk
Thanks, I didn't knew that.
Ismail
Thankfully this is one of those mistakes that almost always makes itself apparent as soon as you test or debug it. Maybe if C# had `[System.Diagnostics.Contracts.Pure]` built in from the beginning and used all over the base class libraries, the compiler might have been able to give a warning whenever a pure function's return value is discarded. That would have been pretty damn cool.
Rei Miyasaka
+204  A: 

Don't use "magic numbers" in your code.

Ex:

if(mode == 3) { ... }
else if(mode == 4) { ... }

Use Enumerations wherever possible, so the meaning, not the number, is exposed:

if(mode == MyEnum.ShowAllUsers) { ... }
else if(mode == MyEnum.ShowOnlyActiveUsers) { ... }

(I could have used a switch statement here, as well)

Pwninstein
That's always a good idea regardless of the language that you're using. If not enumerations, at least use named constants. (The is actually one of the rules in the coding standards of the company that I work for.)
RobH
This also allows you to define your constants in a central place and make only one change rather than hunting all over the code for the changes that you'd have to make otherwise.
RobH
Right, regardless of language this is definitely a "best practice."
BobbyShaftoe
Same goes for magic strings. Don't put the same string literal hundreds of times in your code. What if you spell it wrong somewhere?
Daniel Earwicker
Is it possible to have enumerations vailable throughout the whole project??
Kiewic
If I have 'if' over an enum, I'm probably better off with 'switch'.
Jay Bazuzi
While I agree with this as a best practice, I think pragmatism is appropriate here. Taking this practice to the extreme will leave you with dozens of constants that are only used in a single place in your entire application and are a nightmare to sort through.
rmz
Enumerations are great... And to answer Kiewic, yes you can.. in a previous windows app i've used a public enum throughout the project....
GordonB
+1 Because this is something that should be followed regardless of language
byte
That's an old one...
ilya n.
IMO you should put the const first: if (CONST==value), so that you will get a compiler error if you typoed == to be = instead. Goes for any language.
Commander Keen
@Commander Keen: In C#, implicit conversions from int to bool are forbidden.
Jason
I've never thought to use that before, good tip!
Jamie Keeling
+83  A: 

If you are going to be doing a large amount of string concatenation, use the System.Text.StringBuilder object.

Bad:

string s = "This ";
s += "is ";
s += "not ";
s += "the ";
s += "best ";
s += "way.";

Good:

StringBuilder sb = new StringBuilder();
sb.Append("This ");
sb.Append("is ");
sb.Append("much ");
sb.Append("better. ");
DaveK
In this example I'd rather do s = "This " + "is " + "not " + "the " + "best " + "way.";http://stackoverflow.com/questions/21078/whats-the-best-string-concatenation-method-using-c#21113
Greg
why is stringbuilder better? learning...thanks.
johnny
Johnny, each time you append to a string, it recreates the value in a new memory space. Using StringBuilder gets around this by handling in a more dynamic manner. A quick search should give you plenty of references to the specifics.
Chris Porter
shh .. somewhere Jon Skeet is cringing ... The most common post I see from him is how the "StringBuilder is preferred of concatenation" is complete nonsense.
BobbyShaftoe
I disagree with blanket use of StringBuilder. If you're only doing 5 concatenations in the above example then StringBuilder might actually be slower (due to the overhead of constructing it). But any difference will be negligible either way. It only really matters for thousands of concatenations.
Evgeny
String has a Concat method that can accept multiple strings. If you write s1+s2+s3 the compiler is smart enough to turn it into a single Concat call. However, if you're calling s1+=s2 in a loop that may get long, use StringBuilder (sb.Append(s)) instead.
Daniel Earwicker
I wrote a simple test app on this, and under 4 concatenations string.concat is fastet. From 4 concatenations up, stringbuilder is faster. Try it, write it, use System.Diagnostic.Stopwatch.
BeowulfOF
Good advice, this is one of those little things that irks me as well :)
hmcclungiii
Does this really matter?http://www.codinghorror.com/blog/archives/001218.html
Gary Willoughby
I'd only using stringbuilder if doing a lot of concatenation, in a loop or if i knew there was going to be a lot of manual concatenations.... Otherwise the first example does suit.
GordonB
Gary Willoughby: yes. Read Dennis Forbes's comment below the article. Using += is slow, but concatenating a bunch of strings in one expression is not.
Neil Whitaker
String concatenation using + operator **is** a real performance killer **when** the size of the strings is somewhat large, concatenating strings that will yield a resulting string of a few hundred bytes won't make any perf. difference.
Pop Catalin
I actually optimized an aspx page by replacing string concats with a single stringbuilder in an application. The page took a minute to load with concats. Several seconds afterwards. The aspx itself basically had a literal...
Min
You have to concatenate 1000's of strings before having a performance impact (and a huge one, granted, since you're in O(n^2) instead of O(n)). But the example is actually bad. You use StringBuilder if 1) You know you'll have 100's of strings to concatenate 2) you DON'T KNOW how many strings you will concatenate.
Yann Schwartz
I generally only use StringBuilder on loops (or incredibly long lists, such as over 50+ items). Anything else, I don't think there is a significant benefit -- from a performance stand point. However, from a consistency standpoint that is another matter. It's also important to remember that StringBuilder preallocates how much memory goes in to it and as such, if you know you're loops will be *huge* you can plan for this ahead of time and save yourself some milliseconds (which count in loops).
Nazadus
Please justify your answer
Avram
This is wrong... having the number of concatenations known makes the concat the better choice over the stringbuilder
Andrei Rinea
string.Format is really the answer here. For those situations where StringBuilder is too bulky, and string concatenation is not cutting it (it never is),
Mark Cassidy
As Jeff Atwood put it: **It. Just. Doesn't. Matter!** (see http://www.codinghorror.com/blog/2009/01/the-sad-tragedy-of-micro-optimization-theater.html for explanation)
Marius Schulz
+22  A: 

Like, trying to open a file without checking whether it exists ...

This is not necessarily a mistake. If you know the file ought to exist (e.g. a configuration file, or a file name obtained using an OpenFileDialog), it's often perfectly OK to just go ahead and open it, and let any exception propagate.

And checking for existence doesn't guarantee it will still exist when you try to open it.

It may make sense to check if you're opening a file in the presentation tier - where you can, for example tell the user the file doesn't exist.

But in the business tier, what are you going to do if the expected file doesn't exist?

  • Throw a FileNotFoundException? In which case you might as well just try to open the file.

  • Throw a custom exception? In which case callers will need to be aware that either your custom exception (for the common case) or a FileNotFoundException (if the file disappears between checking and attempting to open) - which potentially adds complexity.

Joe
Joe is correct: Its can be extra work to check for existence before opening. For example, you existence call could succeed, then the file be deleted before your open call which will then fail. The value here is that it can be a tad more effient to check. But its not a correctness issue.
Foredecker
Foredecker ... oddly, a very good point!
BobbyShaftoe
Raymond Chen has written on this issue: http://blogs.msdn.com/oldnewthing/archive/2007/11/09/6001644.aspx
Eclipse
Personally, I'd check (which will cover 99% of cases) but also handle the exception (to cover the 1% of cases where the check succeeds but the file disappears immediately after).
Kyralessa
Here's a great article that talks about what kinds of exceptions you need to handle. IOException is one of them. http://blogs.msdn.com/kcwalina/archive/2007/01/30/ExceptionHierarchies.aspx
Kyralessa
+72  A: 

Unnecessary initialization

DataTable foo = new DataTable();  // Initialization unnecessary
foo = FetchDataTableFromDatabase();

better:

DataTable foo = null;
foo = FetchDataTableFromDatabase();

also fine

DataTable foo = null;
try{
     foo = FetchDataTableFromDatabase();
}
catch{ 
     //do something
}

best

DataTable foo = FetchDataTableFromDatabase();
MatthewMartin
However, you can't blindly remove those constructs. What if the `DataTable` constructor contains side effects? It might be there for a reason. Though, I would agree that this is bad practice.
Tom Lokhorst
Wow, that is an interesting edge case. You mean the original programmer intended the side effects of the constructor to happen twice and wasn't just copying a common COM/VB6 construction pattern? Unnecessary init causes the constructor to run twice, and the results of the 1st are discarded.
MatthewMartin
Your second case is necessary if your "Fetch" needs to be in a try/catch, and your Foo needs to be declared out of the try/catch scope. In that case you would not be able to use your third case.
best: var foo = FetchDataTableFromDatabase();
Arnis L.
Agree! It gets on my nerves and denotes the developer doent know much about the language/paradigm
graffic
I have code to maintain (not my code originally) that uses the first construct to ensure the result is never null. Of course you still need to see if .Tables.Count > 0 anyway.
Mark Hurd
@Arnis - I disagree for most cases. IMO, var is great for locals within methods where you can see what type it is, but with your example you can't tell what the return type is of that method.
Paul
@Paul those are Your rights. I did believe in `Type`s too.
Arnis L.
@Paul "FetchDataTable" isn't clear enough?
Brian Ortiz
@Brian This is example code, I actually almost never embed data types or signature info into the name. I fear the day when people resume writing Hungarian to make code written with var more readable.
MatthewMartin
@MatthewMartin I disagree that it is bad practice. In fact, I believe it is common and nothing like Hungarian notation.
Brian Ortiz
@Mark: The first construct doesn't guarantee anything about nullness, because the method could return null. In all cases, the first initialization is a waste.
Mark
@Mark: Good point. I really mean something more like a combination of the first and third construct. (BTW Will this realise I wouldn't be replying to myself?)
Mark Hurd
A: 

Avoid thinking you're a Hero and ask those around you for help!

Or doing this:

if ( SomeValue == null )
SomeObject.Value = null;
else
SomeObject.Value = SomeValue;

Instead of this:

SomeObject.Value = SomeValue ?? null;

EDIT: My point is, don't write three lines when one will do.

EDIT, from GordonG:

I think what he meant to say was...

Or doing this:

if ( SomeValue == null )
    SomeObject.Value = OopsSomeValueWasNull;
else
    SomeObject.Value = SomeValue;

Instead of this:

SomeObject.Value = SomeValue ?? OopsSomeValueWasNull;
Chris
Why use the null coalescing operator if you're going to put null on the right-hand side? You could just do "SomeObject.Value = SomeValue".
P Daddy
Yeah, no difference at all.
Ed Swangren
SomeObject.Value = PossiblyNullValue ?? SomeValue would make more sense.
Daniel Earwicker
Corrected your post. I think that is what you meant.
Alex Baranosky
+35  A: 

I've caught myself a few times writing my getter and setter properties in C# incorrectly by referencing the name of the property in the get {} set {} blocks instead of the actual variable. Doing this causes an infinite loop due to the self-referential calls and eventually a StackoverflowException.

Example (Incorrect)

public int Property
{
    get
    {
        return Property;
    }
}
Matthew Ruston
+1 for saying Stackoverflow and meaning it :D
DrG
Heh I learned this one really early in my programming career. 'WTF is going on with this Stack Overflow? My class only has one property so far!?!?!?'
steve_c
This is when tools like Resharper come in handy. It'll put a recursion icon on the side-bar next to the line of code, making it easy to identify accidental recursions like this.
Spodi
Spodi, definitely, resharper! Also, I tend to do "this.property" when referencing instance member variables.
BobbyShaftoe
Let's hear it for autoprops, that make this problem less likely to occur.
Jay Bazuzi
Would be nice if the compiler generated warnings for this!
Dan Diplo
I think everyone has made this mistake at least once.
chris
A coding convention, like using underscore as a prefix of private fields, helps to avoid this kind of issue. In addition, you'll have the convinience of typing _ on the code editor and Intellisense will show up all your private fields together. I know it is a matter of coding style/convention, but for me it is useful.
Carlos Loth
After the first time this one is completely obvious.
kirk.burleson
it happened to me yesterday :))
+3  A: 
 i = i++;

is not the same as

 i++;

I found a great SO post about this, but this also does a decent job.

It's a dumb thing to do anyway, but the point is that it increments differently from c++.

Ah here is the SO one What’s the difference between X = X++; vs X++;?

DrG
i++ is more like i = ++i (increment before assign)
jishi
+6  A: 

Setting local objects to null will not free up any resources, so there is usually no reason to do it.

Michael Stum
This is usually good advice for locals, but often bad advice for members. It often makes logical sense to assign null to a member to indicate that it is restored to its initial state.
Daniel Earwicker
I agree with Earwicker. Setting objects to null can cause the garbage collector to collect them and free up the used memory resource. I think you've taken that question you've linked slightly out of context and over-generalized it. This answer only applies in some circumstances.
Scott Langham
I never thought about that, but now that you mention it - you're right, this only applies to locals, because they will go out of scope rather fast, whereas members can stay in scope for a long time. Modified article, thanks for the comments!
Michael Stum
For members no, but for local variables yes, it drives me mad! I read that actually it postpones collection because setting the variable to null accesses the variable which implies to the GC that the value it holds is still required.
Peter Morris
+22  A: 

Use generics collections (List<T>) instead of ArrayList so that you can maintain type safety.

re:using
Don't unnecessarily nest using statements do this instead:

 using (SQLconnection conn = new SQLConnection() )
 using (SQLCommand cmd = new SQLCommand("select 1", conn)) // no need to nest
 {
    conn.open()
    using (SqlDatareader dr = cmd.ExecuteReader()) //nessesary nest
    {
      //dr.read()
    }     
 }
rizzle
Why mark this down? Both good points.
Daniel Earwicker
A lot of style guides would frown on this because the first using isn't using brackets. It's mostly an issue of preference...but I think it's *better* to have the brackets.
Beska
I would still call that nested, even if there are no brackets used.
Neil Whitaker
It's "better" to just use C++ in the first place where RAII is done right! ;)
Eclipse
That is still nested, and VS will indent it as such when you put the closing brace on your method.
Blorgbeard
I already forgot that such a thing like ArrayList exists. And it's ain't bad NOT to use brackets, if code is readable.
Arnis L.
*Logically* it's nested, sure, but *visually* it's not nested. The point of this style is to avoid *visual* nesting, which clutters the code for no good reason.
Kyralessa
I wish that the using statement would allow for something like this, it would solve most of the readability issues: using (Resource res = new Resource(), Wrapper wra = new Wrapper(res))
Allon Guralnek
This is a post that would get closed if it were a question. It's akin to the bracket/indentation debate.
Rei Miyasaka
+20  A: 

Use FxCop to pick up on common coding mistakes. Some of the things it picks up on are a bit trivial, but it has helped us pick up a number of bugs which might otherwise have been missed. Run it from Visual Studio, Analyze->Run Code Analysis for ..., or be really good and set it up to run every time you do a build in the Code Analysis section of the project properties.

Matthew Wright
+6  A: 

Unnecessary boxing and unboxing.

Tim Merrifield
Could you give an example?
Anthony
Yeah, that would be good.
Andrei Rinea
Sure, one example would be using an ArrayList to store a collection of value types. So if I use an ArrayList to store ints. When I add or remove an integer it must be boxed/unboxed. Clearly this is wasteful. Maybe a bad example but you get the idea.
Tim Merrifield
Boxing is bad... mkay...
BigBlondeViking
+2  A: 

As some have mentioned swallowing exceptions is a really bad habit. Another thing that I see people do all the time that's quite similar to swallowing exceptions is redundant null checks.

Let's say that we have a method that returns an object and we it should never return null a lot of times you'll see this.

var o = this.Foo();
if (o != null)
{
  o.Bar();
}

// more code here...

Really if the method Foo returns null this is exceptional behavior and an exception should be thrown, so either in an else block throw an appropriate exception or just remove the if-statement and allow for the NullReferenceException to be thrown.

Patrik Hägne
This is debatable. I think this is just another case of using exception handling for control flow. The only time I might agree is if this method is certain to not return null under normal circumstances. But, I also don't like using var in this case when the type returned is non-obvious to the reader
BobbyShaftoe
First of all, as I say this is when the method never should return null, in other words if null is returned it's an exceptional behavior. Using var in this case is because it's pseudo code.
Patrik Hägne
I don't know that allowing an NRE is a good option. Better to throw an ArgumentNullException as soon as you know something's wrong.
Jason Baker
The NRE is way better than the alternative specified in the example which is the equivalent of swallowing a checked exception. Of course the called method shouldn't return null, so the method should've probably thrown an exception. I'm not sure I explained this one well enough.
Patrik Hägne
+152  A: 

Oh, I forgot my number one pet peeve, over specification of input parameters. Let's say we have a method that takes a collection of some type, always allow the least specific type of collection needed by the method.

This is what you see A LOT:

public void Foo(List<Bar> bars) 
{
  foreach(var b in bars)
  {
    // do something with the bar...
  }
}

As you see the method does nothing but loops through the list, so requiring a list is an over specification, all you need is something you can loop through, ie. an IEnumerable<Bar>.

This is a lot nicer to the caller:

public void Foo(IEnumerable<Bar> bars) ...

If the method requires to know the count of the bars collection use ICollection<Bar> instead, or maybe you need to access bars by index, then use IList<Bar> but always the least specific sub type needed.

Patrik Hägne
Yeah, this is a good tip. You don't see this tip very often. Most of the others in this list are good but sort of cliche, this is more original. :)
BobbyShaftoe
On the other hand, methods that take interfaces can be a little harder to figure out how to use. Example is TextRenderer.DrawText, which takes an IDeviceContext as a parameter. Took me a bit to realize that a Graphics object implements IDeviceContext.
MusiGenesis
You're right that in some cases you trade off the learnability for flexibility, but that must be edge cases. I still think this is most common for collections and there should be no problem for anyone to understand what IEnumerable(T) means.
Patrik Hägne
Resharper tells you to do this.
Daniel Earwicker
why not ask for a simple array?
Harry
Ohh, Harry, if you every do that people will hate you. Actually don't ever use arrays for anything else than local variables (OK, there might be some other cases but that's a good rule of thumb). In this case it's just not needed, use the interface and you can pass an array, a list or something else
Patrik Hägne
Agreed in general, MusiGenesis, but not for IEnumerable(T). Essentially every generic collection implements it (even stuff like Stack(T) or Queue(T)), so there's no reason to use anything more derived.
Kyralessa
`public void Foo<T>(IEnumerable<T> bars) where T : Bar ...` is nicer still.
finnw
@finnw, I don't agree, mostly because the type constraint is not part of the signature so you could not have an overload for "foos". I see your point in .net 3.5 and earlier but in .net 4.0 there's absolutely no point in doing this since you have co- and contravariance.
Patrik Hägne
F# would have inferred the most general type.
Jon Harrop
Take `String.Join` for example – before .NET 4.0, it needed to be called by passing an array: `String.Join(string delimeter, string[] strings)`. Now, it is possible to hand over an `IEnumerable<string>` which is perfectly acceptable because the method does not have to restrict the specified collection type – it can act on it as long as it is enumerable.
Marius Schulz
A: 

using leading (or trailing) underscores to denote member data (or anything else)

class HowToMakePeopleHateYou
{
  string _doShit;
  double _likeThis;
}

There are a total of probably 10 people in the world who prefer to read code formatted that way. Chances are, your co-workers will not be among them.

Same goes for Hungarian notation, or any other punctuation meant to imply type or role of a variable.

and there are a million people in the world who use m_ for member variables and similar. You need to stop annoying them with your preference :)
gbjbaanb
These days, notation that denotes type or role is frowned upon because code gets refactored quite often. The last thing you want to do is have to change your intSpeed to be called floatSpeed. Prefixes typically just clutter up a variable name, making it just that bit more difficult to read.
Soviut
i don't agree; using hungarian notation makes reading through other people's code much easier. If the complaint is that code is refactored often why not just use the rename functionality built in....
Gordon Carpenter-Thompson
I consider hungarian notation a nuisance; i don't need to know the type of an object because IntelliSense tells me.
Dmitri Nesteruk
Actually, this is the recommended way of doing things in .NET from most of what I've read. Plus I like the fact it denotes a private field instead of a regular old variable. And it's infinitely better than m_ or Hungarian notation.
Wayne M
-1 I prefer the underscore for instance variables. Easier to read.
TheSoftwareJedi
I'm with @TheSoftwareJedi on this, the underscore makes it easier to read and maintain which in turn makes my life easier. the only time I have had a use for Hungarian Notation is with asp.net controls because it makes it easier to find them with IntelliSense
Bob The Janitor
Agree 100% with @Bob-The-Janitor
Christian Hagelid
I personally hate the whole underscore thing. Hungarian notation I can live with for asp.net controls like Bob said.
BBetances
I like m_PrivateField because of the capitalization, but I don't mind _privateField. Though naming a private field like a local variable (privateField) or a property (PrivateField) is unreadable and unacceptable as far as I'm concerned.
Allon Guralnek
-1 "private string _myString" is the convention used in the .NET framework implementation itself, so I don't see why using that convention should be wrong. It's so much easier to tell local vars from private fields that way.
alexander.biskop
I don't usually do "me too" posts, but in this case I want to OP to know that there are more than 10 people in the world who like using a leading underscore to denote a class variable, including me.However, I don't like Hungarian notation.
Bill W
-1 I always use _s and all my coworkers are happy with it.
Behrooz
Arghhhh... hate when people uses unnecessary and strange keywords like `class`. Idiots. :E
Arnis L.
Do you know that the code VB.NET generates for automatically implemented properties in VS 2010 uses this method? An auto-implemented property with name `SomeProperty` is stored to and retrieved from a private field `_someProperty`. I think you jumped too soon.
Alex Essilfie
Maybe dont use any underscores? just name your fields as you like.
Hooch
+66  A: 

Not using ReSharper! (Or another code analysis tool - but R# is the best.)

I'm surprised nobody has mentioned it yet, because it automatically picks up many of the mistakes mentioned in other answers.

Evgeny
I was going to say that! Although gradually VS is picking up the features of Resharper. The Resharper folks are going to struggle to differentiate themselves. (Although for us this is a good thing - the tools just get better and better.)
Daniel Earwicker
Live Templates... VS still has a while to go.
Min
Resharper is good.In one way it pump up Your performance, but greatly reduce overall performance of PC. And it always bring down on knees my work IntelCoreQuad with 4 gigs of RAM. Without R# I feeling more productive and getting more attention on errors by myself.
AlfeG
Not using Resharper is not a common programming mistake.
kirk.burleson
I hope you work for jetbrains (making this answer explainable.. otherwise...)
Andrei Rinea
@kirk - perhaps not a "mistake" as such, more of a sub-optimal development practice. I think the answer was still relevant and useful, however.@Andrei - No, I do not work for JetBrains - but I probably would. :)
Evgeny
+26  A: 

Violating standards or conventions without knowing why they are there, or worse, refuse to even acknowledge their value.

It makes their code hard to read, hard to re-use.

Echiban
This needs more upvotes.
Tordek
This needs an example.
kirk.burleson
+74  A: 

1. RAII (resource acquisition is initialization)

A stupid name for a great idea. In C++, constructors are mirrored by destructors. After some serious internal and external lobbying right before C# was released, MS added the using statement, providing at least minimal support for this idea, though there is more they could do. But the usefulness of RAII is still not widely grasped. It's sort of true to say it cleans up "unmanaged resources", but think about what that means: anything other than memory. Think of all the places in your code where you modify state, and later want to put it back again.

Simple example - an Undo system. You want to support "batch" undo transactions, in which several actions get bound up into a single one. The application would do this:

undoSystem.BeginTransaction();

// do stuff, add several undo actions to undoSystem

undoSystem.EndTransaction().

The point is, EndTransaction MUST be called, however we exit the function, to restore the system to the state we found it in. You should at least use try/finally - but why not follow a pattern consistent with the language? Make BeginTransaction return an object:

public class UndoTransaction : IDisposable
{
    public void Dispose()
    {
        // equivalent to EndTransaction
    }
}

Now the application code can just do this:

using (undoSystem.BeginTransaction())
{
    // do stuff, add several undo actions to undoSystem
}

Now there is no need to correctly figure out which method is the "ender" for the "beginner" of the state (which in some situations would not be as obvious as in this example). And ask yourself - would it make much sense for UndoTransaction to have a finalizer as well? Absolutely NOT. Finalizers cannot safely call on to managed objects, and they run in a different thread. The one thing they are useful for (calling an interop API to dispose of a Win32 handle) is now done much more easily by using SafeHandle.

Unfortunately the internet and older books are riddled with advice about how IDisposable implies the need for a finalizer. Ignore them. And also not really explaining the implications of "unmanaged resources" - anything about the state of your program can be regarded as an "unmanaged resource". By taking advantage of IDisposable/using, you can apply a consistent coding style to deal with states that change in line with the method call stack. Which brings us to...

2. Exception Safety.

There are some operations that do not throw. Assignment cannot be redefined in C#, so:

x = y;

Assuming x and y are fields or variables of the same type, that will never, ever throw (except under truly bizarre circumstances where you can no longer rely on anything working). How reassuring is that?! But also useful. Think of how, often, one of your methods will update the state of the class it belongs to. Sometimes it will modify two or three (or more) private fields.

What if an exception is thrown at some point during this multiple-update of state? What state is your object left in? Will one of the fields be updated, but not the other two? And does the resulting state make any sense? (does it "satisfy the class invariant"?) Or will it later cause your code to get confused and cause further damage?

The solution is to figure out what the changes need to be, before doing anything to update your fields. Then when you have all the answers ready, do the assignments - safe in the knowledge that assignments never throw.

Again, because of GC, C# programmers have been encouraged to think that this is a C++-specific problem. It's true that exception safety (and RAII) are commonly spoken of in terms of deleting memory allocations, but that is just one example (it happens to be very important in C++). The truth is, exception safety is an issue that concerns any program that has non-trivial modifiable state in it, which is most programs.

Another issue with exceptions is that they are just as much a part of the "interface" exposed by a method as are the parameters and the return value. We are encouraged (by some of the people answering this question) to catch specific exceptions instead of just Exception itself:

try
{
    funkyObect.GetFunky();
}
catch (SocketException x)
{

}

How do you know that GetFunky throws SocketException? Either documentation, or trial and error. What if the author of that method later changes it so it doesn't use sockets, so it throws something else? Now you're catching the wrong thing. No warning from the compiler.

Compare with this cautionary tale:

IEnumerable<int> sequenceInts = funkyObject.GetInts();

// I found out in the debugger that it's really a list:
List<int> listInts = (List<int>)sequenceInts;

Very clever, until the author of GetInts changes it to use yield return instead of returning List<int>.

The moral is that you shouldn't rely on undocumented, untyped coincidences, you shouldn't sniff out the internals of a method you are calling. You should respect information hiding. But this applies to exceptions as well. If a method allows a huge variety of exceptions to leak out of it, then it has a very, very complicated interface, which its author probably didn't intend for you to be reliant on. It's not really any of your business how a method works internally.

This is all partly the fault of lazy library authors. When writing a nice clean modular library, consider defining your own exception type(s). Make sure that your library's methods ONLY throw your approprate exception types and document this fact. Your library methods' code will look like this:

try
{
    // do all kinds of weird stuff with sockets, databases, web services etc.
}
catch (Exception x) // but see note below
{
    throw new FunkyException("Something descriptive", x);
}

I call this normalizing the exceptions. Note that by passing x into the constructor of FunkyException, we cause it to become the InnerException. This preserves complete stack trace information for logging/debugging purposes. Also note that this contradicts the advice given by several other answers to this question (including the highest rated answer), and also many blog posts on this subject. But there it is; I think those people are dead wrong. Exceptions are part of the visible interface of a method, and it is just as important to control that aspect of the interface as it is to specify the type of the parameters and return values.

And when catching exceptions thrown by a badly written or badly documented method (one that may or may not throw all manner of exception types - who knows?) I would advise that you do NOT catch whatever specific exception types it throws, discovered by trial and error in the debugger. Instead, just catch Exception - wherever you need to in order to ensure the exception safety of your program's state. That way, you are not becoming dependent on undocumented or coincidental facts about the internals of other modules.

But...

Unfortunately catching (Exception x) is a really bad idea until CLR 4.0 comes along. Even then, it still won't be ideal, though not as bad as it is today. And yet, it has long been advised by the Exception Handling block of Microsoft's Enterprise Library!

For the details, see:

In short - if you catch all exceptions, you also catch fatal exceptions (ones that you want to cause your program to stop and capture a stack trace or a mini dump). If your program attempts to limp along after such an exception, it is now running in an unknown state and could do all kinds of damage.

Reponses to several comments from P Daddy:

"Your advice to ignore the conventions prescribed to by the majority of the industry, as well as Microsoft themselves..."

But I'm not advising that at all. The official advice on Dispose/finalizers used to be wrong but has since been corrected, so that now I'm in agreement with the majority opinion (but at the same time this demonstrates that majority opinion can be wrong at any given time). And the technique of wrapping exceptions is widely used by libraries from Microsoft and 3rd parties. The InnerException property was added for precisely this purpose - why else would it be there?

"IDisposable is not RAII... the using statement, as convenient as it is, is not meant as a generic scope guard..."

And yet it cannot help but be a generic scope guard. Destructors in C++ were not originally intended as a generic scope guard, but merely to allow cleanup of memory to be customised. The more general applicability of RAII was discovered later. Read up on how local instances with destructors are implemented in C++/CLI - they generate basically the same IL as a using statement. The two things are semantically identical. This is why there is a rich history of solid practise in C++ that is directly applicable to C#, which the community can only benefit from learning about.

"Your Begin/End Transaction model seems to be missing a rollback..."

I used it as an example of some thing with on/off state. Yes, in reality transactional systems usually have two exit routes, so it's a simplified example. Even then, RAII is still cleaner than try/finally, because we can make commit require an explicit call but make rollback be the default, ensure that it always happens if there is not a commit:

using (var transaction = undoSystem.BeginTransaction())
{
    // perform multiple steps...

    // only if we get here without throwing do we commit:
    transaction.Commit();
}

The Commit method stops the rollback from happening on Dispose. Not having to handle both kinds of exit explicitly means that I remove a bit of noise from my code, and I automatically guarantee from the moment I start the transaction that exactly one of rollback and commit will occur by the time I exit the using block.

Case Study: Iterators

The IEnumerable<T> interface inherits IDisposable. If the implementation needs to do something interesting in its Dispose method, does that imply that it should also have a finalizer, to protect itself from users who do not call Dispose?

For an example, look at the most widely used (in modern C#) way of implementing IEnumerable<T>.

When you write an iterator (a function returning IEnumerable<T> and utilizing yield return or yield break), the compiler writes a class for you which takes care of implementing IEnumerable<T>. It does do something important in its Dispose, and yet it does not have a finalizer.

The reason is simple. The Dispose method executes any outstanding finally blocks in the iterator code. The language implementors realised that it would be better for the finally block to never run than for it to run on the finalizer thread. This would have required anything called from finally blocks in iterators to be thread safe!

Fortunately, most clients of IEnumerable<T> use foreach, which works exactly like a using statement - it calls Dispose for you. But that still leaves the cases where the client needs to directly control the enumeration. They have to remember to call Dispose. In the event that they don't, a finalizer cannot be assumed to be a safe fallback. So the compiler does not attempt to solve this problem by adding a finalizer.

Ultimately, this is just one (very widely used) example that demonstrates that there is a class of cleanup problems for which lazy cleanup (GC, finalizer thread) is not applicable. This is why using/IDisposable was added to the language - to provide a purely deterministic cleanup pattern - and why it is useful in its own right in situations where a finalizer would be the wrong choice.

This is not to say that you must never add a finalizer to something that is disposable, just that finalizers are only appropriate in a subset of cases.

Daniel Earwicker
I like the counter-points on exceptions. catch(Exception) is sometimes a very valid thing to do. This is a long one! Some refactoring into 2 answers would have been good!
Scott Langham
+1, got to say I recall the lobbying about adding idispose, the hassle from the MS boys who thought a GC was the answer to all resource problems was an eye-opener. I'm not sure they quite get it today.
gbjbaanb
Regarding "x = y can never throw": two corner cases where that is not true (and the world is not falling of its axis) include (1) when the type of y has an implicit cast operator to the type of x, and (2) when y is a property (or, of course, any other method call).
P Daddy
Your advice to ignore the conventions prescribed to by the majority of the industry, as well as Microsoft themselves, sounds a lot like http://thedailywtf.com/Articles/I-am-right-and-the-entire-Industry-is-wrong.aspx.
P Daddy
IDisposable is not RAII. The using statement, as convenient as it is, is not meant as a generic scope guard. The D language has a very handy scope(exit) statement (as well as scope(success) and scope(failure)), but C# is neither D nor C++. C# doesn't have scope guard statements (except for (cont.)
P Daddy
...try/catch/finally) like D, and it doesn't have deterministic destruction like C++.
P Daddy
Your Begin/End Transaction model seems to be missing a rollback. Rather than make an IDisposable class so that you can do using(BeginTransaction), you'd be better off with BeginTran;try{dostuff; success=true;}catch{Rollback}finally{if(success) Commit}. It's longer and not as nice to read, (cont.)
P Daddy
...but it's more correct.
P Daddy
@P Daddy - I've answered your comments in an edit above, also clarified the assignment-doesn't-throw assumption.
Daniel Earwicker
My comment about advising to ignore conventions didn't refer to your exceptions advice. There is plenty of debate about wrapping vs. not wrapping exceptions (some within this very post) which I'd rather not get in on, except to say that wrapping an exception is definitely a good thing if and only...
P Daddy
...if you add value. This can be by making the message more descriptive, or by, as in your example, changing the exception type to fit your interface. Your exceptions argument starts to sound a little like the checked vs. unchecked exceptions debate, which I'd rather just stay out of.
P Daddy
What I *was* referring to was your advice to ignore others' advice about using finalizers in the disposable pattern. There's a good reason to use finalizers in [some, but not all] IDisposable implementations, which I think we've covered fairly completely in the comments to Kev's answer in this post.
P Daddy
+1 for your 'rollback if not committed' transaction implementation, though. That is a definite improvement.
P Daddy
It's not suitable for a public API, though, because you rely on `using`. Whenever you implement an disposable class, you must always assume that consumers of your class (which may even be you on a bad day) will forget to dispose of it (including forgetting to wrap its use in a using statement). ...
P Daddy
One thing we can definitely agree on is that SO should allow longer comments!
Daniel Earwicker
... this is why finalizers are absolutely necessary for any state that won't be cleaned up by the GC.
P Daddy
That argument about consumer forgetting to Dispose, if I took it seriously, would destroy all programming techniques ever invented. Absolutely any library design is vulnerable to consumers who forget to call the right method...
Daniel Earwicker
Agreed on the comments thing! There's a suggestion at uservoice for that: http://stackoverflow.uservoice.com/pages/general/suggestions/39007-allow-for-longer-comments, but it doesn't appear to be going anywhere.
P Daddy
But if you name your method IDisposable.Dispose(), the language helps you to call it at the right time (just before the object that implements it disappears). So it's better than ANY other way of designing a library that requires a predictable clean-up callback, even if it's still not perfect.
Daniel Earwicker
re: "would destroy all programming techniques". That's baloney. There are many programming techniques that were invented simply *because* people screw up. Exceptions were more or less an answer to programmers neglecting to check error codes. The IDisposable pattern itself, along with RAII, ...
P Daddy
...are answers to programmers neglecting to release resources. People are imperfect. I am imperfect. You are imperfect. You must code defensively against people's imperfections.
P Daddy
Note that in C++ the same problem exists. A coder may say std::vector<int> *p = new std::vector<int>(1000000), and be surprised that it doesn't reclaim the MB of memory when p goes out of scope. The exact equivalent of forgetting 'using'.
Daniel Earwicker
Hmm... maybe you're missing my point. I suggest using Dispose as the name for a clean-up method. You say "that's no good, what if they forget to use using?" I say: what if I call my method something else, and they still forget to call it? Hence your criticism has no force against my suggestion.
Daniel Earwicker
"the language helps you call it at the right time (just before the object disappears)": Huh? What you're describing is a feature of the GC, not the language, and is an argument *for* having a finalizer.
P Daddy
Note that in C++, memory leaks (like the one you show) are the #1 source of bugs.
P Daddy
Obviously I don't deny people screw up if left to their own devices - that's precisely why I recommend using over try/finally. It makes it just a little bit more clean, automatic and hard to get wrong, which is always a good thing.
Daniel Earwicker
Dispose absolutely should be the name of a cleanup method, and is why this pattern exists. However, you suggest *relying* on consumers to *always* call it, and I'm insisting that you can't. Like it or not, not everybody is as infallible as you or I. By not everybody, I mean you or me on a bad day,
P Daddy
...or our less-skilled coworkers who must use our class, or the people we sell to whom we sell our libraries.
P Daddy
And you must know I'm talking (throughout) about the using statement, not the GC. I'm starting to wonder if you're just looking for ways to misinterpret whatever I say! It's the same with that comment about C++ memory leaks - how does that address my point?
Daniel Earwicker
There are basically two reasons for the disposable pattern. One is to provide for early release of limited resources, or otherwise early cleanup of state. It's great when a well-behaved programmer calls Dispose as soon as he's done using an object. The other reason is for a limited guarantee...
P Daddy
...that resources (or state) will be cleaned up eventually, even if the consumer is not well-behaved. This is where the finalizer comes in. If we could always rely on users to call Dispose, then we wouldn't need to add finalizers, ever. But then, we wouldn't need to disposable pattern at all. ...
P Daddy
... Each class would have its own cleanup method, like File's Close (which File.Dispose calls).
P Daddy
I'm not relying on consumers to always call anything. I can't even begin to see how you've reached that interpretation.
Daniel Earwicker
I don't think I'm misinterpreting you at all. You said "And ask yourself - would it make much sense for UndoTransaction to have a finalizer as well? Absolutely NOT." I've directly addressed this. About your C++ memory leaks comment: just what *was* your point?
P Daddy
You appear to arrived back at the idea that Dispose REQUIRES a finalizer. You just aren't reading what I'm saying, and you aren't reading current advice. An IDisposable object does not always need a finalizer, and as such it is reliant on being used correctly (as is any class!)
Daniel Earwicker
My point with the 'new std::vector' was to provide another example of how you cannot stop users from abusing your class. They can always use it wrong. This is not an argument against providing them with an easier way to use it correctly.
Daniel Earwicker
Yes, you're relying on consumers to always call Dispose (either directly, or indirectly though a using). Not that, for example, wrapping your transaction in the disposable pattern is a bad thing, but without guarding against user non-compliance to the pattern, you've added little value.
P Daddy
If UndoTransaction had a finalizer, that would mean that the undo transaction would get ended at a random time by the finalizer thread. That would actually be worse than it never being ended, as it would be harder to detect and the results would be non-deterministic.
Daniel Earwicker
We're getting somewhere - you agree I've added some "little value". In fact I've added precisely the value of the using statement itself. It's in the language for a reason - for that "little value" it provides.
Daniel Earwicker
You're missing my point, then. A user forgetting to free something in C++ that he has allocated himself is a user error that you can't do anything about, but it's not your responsibility, unless you're the user that did it. A user forgetting to free something that *your* library returned to him ...
P Daddy
... is a user error that you *can* do something about. You can return the wrap the memory in a smart pointer, so that it will be freed automatically as soon as the user's pointer goes out of scope. Similarly, if you provide a finalizer with your disposable object, you can prevent user errors...
P Daddy
... in C# when users forget to call Dispose.
P Daddy
"If UndoTransaction had a finalizer ... the undo transaction would get ended at a random time": only in the worst-case scenario where the user neglected to Dispose of it properly. But ending at a random time is better than not ending at all!
P Daddy
Er.. you prefer programs with _random_ behaviour? I wish you good luck, and adieu.
Daniel Earwicker
That's ludicrous and argumentative. What I do prefer is eventual finalization to none at all. Of course, I'd *prefer* my users to be perfect and never miss a Dispose call, but if everybody were perfect, then this post would have no place!
P Daddy
Your response is "It would be better if your library attempted non-deterministic cleanup in the eventually of a bug in the user's code." You have to accept that this might be a disastrous thing. You have to accept that there are many situations where this would make the bug harder to track down...
Daniel Earwicker
If you can't accept that, we'll just be going round in circles forever. It's the crux of what I'm saying. There are situations where an attempt at non-deterministic cleanup is *worse* than no cleanup. Specifically, any system of states that work like a stack.
Daniel Earwicker
In such cases, the bug can simply be detected by noting that the stack is not emptying correctly, and the program halted with an exception saying "You forgot to dispose" so the user can fix the bug.
Daniel Earwicker
This is where the rest of the industry disagrees with you. Late cleanup is better than no cleanup. See http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx or http://www.bluebytesoftware.com/blog/2008/02/18/IDisposableFinalizationAndConcurrency.aspx.
P Daddy
Have you actually read the second link? "We may or may not want people to implement a finalizer to do the same [as Dispose]. I currently believe we will." It's an open question, not a thing with expert consensus at all. So I'm afraid you're going to have to think about it, not blindly follow rules.
Daniel Earwicker
Late cleanup is better than no clean up - except when it would cause non-determinate side-effects and make the bug harder to find. How can I make it simpler than that? You're blindly applying a rule that is not always applicable, that's all.
Daniel Earwicker
The point about wrapping exceptions is interesting - but do you mean that I should wrap every single public method in a try-catch block? Is it not far simper and less error-prone for the user of the class just to expect any exception to be possible, and handle specific ones as appropriate?
Joel in Gö
@Joel - my point really is that there is no single correct answer. It depends what level of binary compatibility you want to offer the caller of your code. The language supports filtering exceptions by type, hence exception types are part of the binary interface...
Daniel Earwicker
... but you could document that "all bets are off" when it comes to exceptions thrown by your method. I increasingly believe that there should only be two exception types that a 'catch' can specify: Fatal and Recoverable.
Daniel Earwicker
If a Fatal exception leaves a method, the caller should attempt to unwind whatever they were doing and propagate the exception. For a Recoverable exception, they can unwind and either "swallow" the exception (e.g. display a message, log, continue) or propagate it.
Daniel Earwicker
But callers should never second guess *how* to recover based on information in the exception. So beyond the fact that the exception is either fatal or recoverable, the caller's code path must not depend on information in the exception. Wrapping is potentially a way to enforce this.
Daniel Earwicker
-1 this answer is just too long
finnw
@finnw - that's okay, just stop reading as soon as your brain starts to hurt.
Daniel Earwicker
hmm, I didn't mean to upvote Earwicker's comment. I hit the arrow by accident.On an unrelated note; I love it that I can say "using (RWLock.ForReadingOnly) { ... }" in C#. It now becomes so much easier to see when the lock is taken and released and what part of the code makes use of it.In this case RWLock is a class I wrote that wraps an ReaderWriterLockSlim and has three properties that return a disposable to get a read, upgradable read or write lock from the ReaderWriterLockSlim.
Patrick Huizinga
+1 for GetFunky();
tsilb
Regarding your use of Dispose for general RAII, it looked like a good idea at first but now I'm thinking you're probably always better off using a higher-order function that guarantees the initial and final code is run.
Jon Harrop
@Jon Harrop - Definitely, that's what I usually recoomend now, e.g. http://stackoverflow.com/questions/2617400/synchronized-ienumeratort/2617514#2617514 - it's not always possible though because sometimes you need to be able to compose resources.
Daniel Earwicker
This is the longest answer I've ever read on any forum.
kirk.burleson
+7  A: 

One common mistake is using

if (obj is SomeType) {
  ((SomeType)obj).SomeMethod();
}

instead of

SomeType tempVar = obj as SomeType;
if (tempVar != null) {
  tempVar.SomeMethod();
}

The latter does not double the cast (which does occur in the first snippet and means a slight perfomance hit).

petr k.
The corollary to this is SomeType tempVar = obj as SomeType; tempVar.CallMethodAssumingNotNull();
Cameron MacFarland
Without profiling data indicating that this micro-optimization will improve my user's experience, I would choose the one that more clearly indicated my intent in code.
Jay Bazuzi
I timed it and didn't notice any difference. So I prefer the first one. It doesn't clutter the function with a new variable that some other programmer could accidentally try and access later in the function without realising it may be null because it wasn't of SomeType.
Scott Langham
Downvoted: In a loop of 10 million times it was 10 milliseconds slower. I'd rather go for the 2 lines of code that don't need a local variable.
Peter Morris
+1 the right way to do casting in c#
Martin Clarke
Downvoted because this is a prime example of premature optimisation.
Timwi
+8  A: 
  • Serializing huge amounts of data to the Viewstate in ASP.NET. Things like storing a serialized User object in the Viewstate rather than just using a session properly.
  • Including an entire, massive, Viewstate crushing toolkit just to add an "are you sure?" prompt or a tooltip.
  • Being afraid to use lightweight toolkits that don't specifically target ASP.NET, such as JQuery or Prototype. (note: JQuery is now being adopted by Microsoft as the premiere client side toolkit for ASP.NET MVC).
Soviut
+2  A: 

Also don't forget all the common code smells:

http://en.wikipedia.org/wiki/Code_smell

God I hate that name, "Code smell".
TraumaPony
+47  A: 

Referencing constants across assemblies, that may not get updated together.

Here is an article i wrote in 2007, pasted whole sale

Referencing Constants

We all know the classic lesson from school. Never use “magic numbers” in your code. Always define a constant and use it throughout. Not only does it give it contextual meaning, it also makes it easy to alter the value only at one place in the future. Sweet deal huh? Well, maybe not as much as one might think. There is a subtle issue with the use of constants that perhaps not everybody is aware of. Let’s do something practical to sink the idea; go ahead and open up Visual Studio:

  1. Create a class library project, call it ConstantLibrary
  2. Create a WinForms project, call it ConstantDependent
  3. Let’s imagine for a moment that we’re going to program World of Warcraft all over again. :-)

Those who play WOW know that the maximum attainable player level used to be 60. So let’s create a PlayerLimits class in ConstantLibrary

namespace ConstantExample
{
    public class PlayerLimits
    {
        public const int MaxLevel = 60;
    }
}

Now, in ConstantDependent, 1. Use Form1 2. Put in a button btnMaxLevel 3. Put in a label lblMaxLevel 4. Set the btnMaxLevel click event to

private void btnMaxLevel_Click(object sender, EventArgs e)
{
    this.lblMaxLevel.Text = PlayerLimits.MaxLevel.ToString();
}

Build and run the solution. When you click the button, 60 appear. Now,

  1. Go back and adjust PlayerLimits.MaxLevel = 70, the new level limit introduced in The Burning Crusade expansion.
  2. Build only the ConstantExample project, and copy its new assembly to ConstantDependent’s bin/Debug directory to overwrite the old assembly.
  3. Run the ConstantDependent.exe that is directly there; make sure you did not recompile it.
  4. Go ahead and press the button again.

It remains at 60. Oops. What is happening here?

  1. Launch MSIL DASM, the disassembler supplied with the .NET Framework SDK.
  2. Load ConstantDependent.exe into it.
  3. Look for method btnMaxLevel_Click and open it up, and look at the line with the ldc instruction to load an integer value onto the stack.

To be specific, it would be IL_0007 in the sample below.

.method private hidebysig instance void btnMaxLevel_Click(object sender, class [mscorlib]System.EventArgs e) cil managed

{

  // Code size       24 (0x18)

  .maxstack  2

  .locals init ([0] int32 CS$0$0000)

IL_0000:  nop

IL_0001:  ldarg.0

IL_0002:  ldfld      class [System.Windows.Forms]System.Windows.Forms.Label ConstantExample.Form1::lblMaxLevel

IL_0007:  ldc.i4.s   60

IL_0009:  stloc.0

IL_000a:  ldloca.s   CS$0$0000

IL_000c:  call       instance string [mscorlib]System.Int32::ToString()

IL_0011:  callvirt   instance void [System.Windows.Forms System.Windows.Forms.Control::set_Text(string)

IL_0016:  nop

IL_0017:  ret

} // end of method Form1::btnMaxLevel_Click

The IL code is using the literal integer value of 60. Ouch. What the C# compiler has done is to inline the constant value literally into the client assembly. If you are in one of those environments where you are only allowed to promote changed assemblies into UAT or production environment, and you thought you could alter just an assembly with modified constants, well, we all thought wrong.

Recommendation: Use constants only within an assembly. If they are placed in some other assembly, make sure they get compiled together and promoted together, even when the client assembly has no change in code. If you can guarantee the constants never change values, then power to you. Otherwise, use static read-only values for dynamic referencing. The following snippet will “propagate” the correct value to the client assembly even if it wasn’t compiled together.

public class RaidLimits
{
    public static readonly int MaxPlayers = 25;
}
icelava
How about wrapping constanst into read-only properties? Does that get inlined in the client assembly too?
DrJokepu
Would not you use readonly right from the start, then? :-)
icelava
+1 for very informative and good investigated answer.
BeowulfOF
Very good answer! I always use internal constants unless the constant should *never* change (I comment it that way too). Otherwise I use readonly members.
Peter Morris
I think that constants is just for constants. Not number of player. Example: PI, Plank and others math consts, speed of light, int.MaxValue....
Fujiy
It's definitely important to be aware of this, but constants have one big advantage over static readonly public variables: you can `switch` on them.
Jeff Sternal
+1 This is very infomative and clear explaination!
Emrah GOZCU
+12  A: 

Not testing!!! This is the biggest mistake I made in the past. Glad I'm finally turning around. Due to testing my code is better, more logical and all of it is being made easier to maintain. Also, I noticed my speed in development went up as well. Not testing is the biggest mistake you can make imo ...

SpoBo
+2  A: 
  • Using string literals repeatedly instead of string constants.

  • Accessing a single list item repeatedly instead of getting it once and assigning it to a local variable.

  • Using less efficient string comparisons like string1==string2 instead of more efficient ones like string.Equals, StringComparer.

  • Always making classes and methods public even for those that should be internal to a library or a class.

etsuba
String.Equals is not much faster unless you are doing it loads, and it doesnt read as well. Premature optimization!
Tim
+2  A: 
Assert.AreEqual(0, resultOfCalculation);

Comparisons with 0 aren't a good way to go, especially in engineering - in a complex calculation, the end result might diverge by at least double.Epsilon and typically a lot more due to all sorts of precision loss.

This is why some test frameworks overload the AreEqual() method, allowing the user to specify tolerance values:

Assert.AreEqual(expectedResult, actualResult, tolerance);
Dmitri Nesteruk
Down voted because (1) You are so vague that I have no idea what you are trying to say and (2) because the parameters are the wrong way around. If you fix your answer nudge me and I will consider removing my down vote.
Peter Morris
Fair enough. Fixed.
Dmitri Nesteruk
There's a Assert.AreEqual for floating point numbers, that take a tolerance. Use that if you must compare non integers in a test.
Brian Rasmussen
0 is an integer. It is reasonable to assert that an integer variable is zero. Did you mean 0.0?
finnw
+4  A: 

Not quite a language thing, and perhaps arguably a "mistake" but...Deploying web-based apps without using HTTP Compression (GZip, Deflate, etc.) There rarely a good reason why you should not use HTTP Compression...

Also, not checking Page.IsValid() to ensure server side validation is done.

+17  A: 

Putting bad execution code in Get accessors

If you have code that modifies an objects state in its Get accessor, then examining that property in the debugger, which causes the code to execute, can alter the state of your object.

For instance, if you have the following code in a class...

private bool myFlag = false;
public string myString
{
  get
  {
    myFlag = true;
    return "test";
  }
}

The first time you run into this in the Debugger, myFlag will show as having a value of false, and myString will show as having a value of "test". If you hover over myFlag, however, you will see that its value is now true. The debugger's display of the property value has changed the state of your object.

Tom Moseley
Very interesting. Not something I would hope happens often in a getter, more likely to happen in a setter, but interesting none the less.
Ray Booysen
Modifying an object state in a property getter is not a problem as long as the state change is idempotent. In your example it is indeed idempotent, so you have not demonstrated a programming error. Of course, it is still possible to write crazy getters, but I don't think that is very common.
Timwi
@Timwi I don't know what you mean can you explain. In this getter if it's examined in debug mode it will cause the state of myFlag to change when it might not have in the program. This could affect the program later based on what myFlag is used for.
PeteT
@petebob796 It is difficult to explain the concept of idempotency in just a few words. Of course the change to myFlag could affect the program, and if it does, the program has a bug — but the bug is *not necessarily* in the property getter that changes myFlag. Consider, for example, a cache: a property retrieves a value and then places it in a private field for faster retrieval in future. This can certainly have an effect on the program if you use the private field in crazy ways, but that doesn’t mean you shouldn’t ever cache any values — it only means you shouldn’t use caches in crazy ways.
Timwi
+6  A: 

Adding threads to an app without knowing the basics of writing threaded apps.

Peter Morris
+10  A: 

Your class doesn't need a Finalizer just because it implements IDisposable!

You can implement IDisposable to give your class the ability to call Dispose on any owned composite instances, but a finalizer should only be implemented on a class that directly owns unmanaged resources.

Any compositely owned instances that own unmanaged resources will have their own finalizers.

Peter Morris
+60  A: 

What I really hate is when programmers ignore compiler warnings and just leave them in the code.

If your project ends up with 100 compiler warnings that you consider "okay to live with" when the 101st compiler warning appears that you might not be happy with you are very unlikely to spot it, you're then likely to be introducing unexpected behaviour.

On a similar line, I also hate it when people change source code in a way that causes it to break unit tests and then don't fix the source code or the test so that they pass. I've been working on a solution that has had 9 broken test cases new for the past 3 weeks and it is driving me mad! Whenever I break a unit test it is harder for me to find what I have broken.

Peter Morris
If you're overrun with a particular warning that you don't plan to fix each instance of, you can disable it in the project settings. (Example: Warning 1591, undocumented public or protected method. Unless you're creating a reusable library to sell, you may not want to, nor have time to, document all those.) Go to the Build tab of your project properties, and in the Suppress warnings box, type the number of each warning you want to ignore, like this: 1591 1867 1883 This can help you reduce warning noise and see only the most essential warnings.
Kyralessa
+100 (if I could) When does StackOverflow introduce multiple upvotes??? :)
gehho
... or as Scott Hanselman put it jokingly: *"If they were important they'd be errors, wouldn't they?"*
Marius Schulz
+6  A: 

In many cases I've seen this scenario:

IDbConnection conn = null;

try
{
    conn = new SqlConnection("SomeConnString");
    conn.Open();
}
finally
{
    // What if the constructor failed?
    conn.Close();
}

If an exception originated in the constructor of SqlConnection class, the variable would never be assigned, which will cause a System.NullReferenceException in the finally in the Close method never being called, resulting in a memory leak.

Generally, it is always a good idea to be as defensive as possible in the catch and finally blocks, since that code is critical and simply can't fail:

IDbConnection conn = null;

try
{
    conn = new SqlConnection("SomeConnString");
    conn.Open();
}
finally
{
    if (conn != null)
    {
        conn.Close();
    }
}
Enrico Campidoglio
Better still, use a Using statement to ensure the connection is both closed and disposed.
Dan Diplo
+4  A: 

I would say mine are more general, as I deal with good architecture more than coding nick nacks:

  1. Applications are logic, not UI. You are building an insurance application, not an ASP.NET application.
  2. Putting anything other than UI logic in the UI layer. This makes for very inflexible applications that have to remain a certain type.
  3. 0% Code Coverage with tests. Big pet peeve. I know development is an art and a science but that means you have to have at least SOME science.
  4. Belief that small apps do not require design. Small apps routinely become large apps.

String concatenation, already mentioned, is a big no no for me. Another is try ... catch. If you are not catching, use try finally. Just as a hands up for noobs, these are functionally equivalent:

using(SqlConnection conn = new SqlConnection(connString))
{
    conn.Open();
}

AND

try
{
   conn.Open();
}
finally
{
    conn.Dispose();
}

One big one I have seen over and over again, with ASP.NET, is writing ASP.NET like ASP. The same can be said for VB.NET devs who moved over from VB. Binding = good; looping to Response stream = bad.

What else>? Oh, you can run through almost any sample on the web and see some pretty bad examples of proper architecture. I do not denigrate the writers, as they are not there to illustrate architecture, but to show how to solve one problem, but still ...

Gregory A Beamer
The .Net 3.5 compiler has got really good at fixing string concats - take a look at the IL after it has been compiled with optimisations on.
Keith
+11  A: 

I saw this one recently...

public void MyMethod()
{
    if (this == null) 
    {
       // some kind of bizarre error handling...
    }
    ....
}

He insisted that you should always check if what you're trying to look at is null before using it. My claim that you couldn't actually be in this method if "this" was null fell on deaf ears.

Beska
I like this answer. Attempting to call MyMethod would throw a NullReferenceException to begin with.
David Anderson
Reminds me of a former colleague who insisted on copying strings in setter methods in case the caller changed the (immutable!) string later.
finnw
Is this really a common programming mistake?
Kyralessa
Dumb is bad. Dumb and thinking you know better - really bad.
Phil
Well, in his defense, if he was used to writing in Delphi, it's understandable; In Delphi (v6, at least), you can call methods on nil-objects. You'd notice your mistake when the method tries to access instance variables.
Lennaert
@Lennaert: That's weird. But, no, this is a C# guy from the bottom up. He's also my superior. Whee!
Beska
I'll second the Delphi bit. If the method is static there will be no dereference of the pointer in order to find the method and thus no error when you call the method. You'll only get the error when you try to access a field. AFAIK that applies across all versions.
Loren Pechtel
[Actually, this can happen](http://stackoverflow.com/questions/1600662/this-null-in-c)! (Sort of)
SLaks
I don't believe this is a common mistake.
kirk.burleson
My condolences, Beska.
Rei Miyasaka
Well... I used to think that this==null will never happen but, just like you people, I was **WRONG** : http://stackoverflow.com/questions/2464097/why-doesnt-the-compiler-at-least-warn-on-this-null
Andrei Rinea
+40  A: 

If you know in advance the size of collection you are about to fill, reserve the space when creating your collection.

List<Person> persons = new List<Person>(listBox.Items.Count); // Reserve
foreach (ListBoxItem lbi in listBox.Items)
{
    persons.Add(lbi.Tag as Person); // No reallocation
}

For very large list, not reserving the space causes the collection to be re-allocated over and over (at each power of two).

Another tip: When adding a lot of items to a collection, it's more efficient to use one AddRange instead of a sequence of Add. This is especially true with observed collections like the Items collection on a ListView.

foreach (string line in File.ReadAllLines(fileName))
{
    // Not the best: there might be overhead when the collection changes
    // and multiple reallocations 
    listBox.Items.Add(line);
}

// Much faster: Single call, minimal overhead, and only one 
// potential reallocation
listBox.Items.AddRange(File.ReadAllLines(fileName));
Anthony Brien
Have you done any testing to indicate that reserving space in the collection this way speeds things up significantly?
Kyralessa
(Agreed on the AddRange, though, which in WinForms is often essential to keep your app from slowing to a crawl.)
Kyralessa
It remember after I introduced a Reserve(), it did improve my performance a lot according to dotTrace (a .NET profiler). But it was for a specific example where the collection was huge (over 100,000 items). As your collection grows very large, the cost of resizing the array (e.g. reallocating it and copying all elements to the new one) becomes bigger and bigger. So if you expect a collection to be very large, and you know the size in advanced, its worth using Reserve. If you have a small array with under 100 items, you probably wont notice a difference.
Anthony Brien
Upvote for space reservation thingy.
Arnis L.
+1 for space reservation thingy haha
SwDevMan81
+14  A: 

Calling GC.Collect().

It is a rare case when we need to interfere with the Garbage Collector work.

ArielBH
That can make sense in a game.
finnw
+20  A: 

A common error when trying to create a central exception handler on winforms:

try 
{
   Application.Run(someForm)
} 
catch (Exception ex) 
{
   //this won't catch your winforms exceptions
   //(even if inside visual studio it does)
}

You should use this for the behaviour you want:

// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += someThreadExceptionEventHandler;

// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Fredy Treboux
+10  A: 

I am a C++ programmer and there was a time when started to code in C# without doing any reading on the language, here are some of the mistakes I did.

Writing a method that write\read your object state to a file instead of using XML (or binary) serializers.

Applying the observer pattern instead of using the built in Events.

Applying the Iterator pattern instead of using enumerators and the IEnumerable interface.

Writing a clone method to classes without implementing the IClonable interface.

Not using the "Using" keyword on IDisposable objects.

Some realy strange things with strings which I can't recall now. (Strings in C# work a bit different then c++)

+6  A: 

Not using flagged enum, where actually we need to.

 public enum Hobby {
    None,
    Reading,
    Cooking,
    Cricket,
    All   
    }

 public class Student {
      public List<Hobbies> Hobbies{get;set;} 
//Bad: we have to make it a collection, since one student may have more than one hobby.
    }

Better Idea.

[Flag]
public enum Hobby {
None=0,
Reading=1,
Cooking=2,
Cricket=4,
All=7   
}
public class Student {
  public Hobby Hobby {get;set;}; 
//Now, we can assign multiple values to it, eg: student.Hobby= Hobby.Reading | Hobby.Cooking;
}

For more info: http://msdn.microsoft.com/en-us/library/cc138362.aspx

Amby
Also check out using this kind of extension: http://stackoverflow.com/questions/7244
Keith
While this is good for cases where you have A, B, C or All, this is complete nonsense for generic lists like a list of hobbies. In the first example, the "All" doesn't make sense at all - it is not a hobby!So, while the point might be right, your example is horribly confusing and/or wrong.
Sander
@Sander, Amby's point (perhaps with not the best example, but most examples are imperfect) that some people design an enumeration _intending_ them to be treated as flags, but not marking them with that attribute. Contrary to Amby's point, though, it IS still possible to use such an enumeration as the basis for testing a field, but you always have to cast it.
Nij
... to be more specific, your member variable can not be typed to the enumeration, but the type underlying the enumeration (default is int). The result is horrid casts:
Nij
why use flags? I don't see why it matters. Aren't flags outdated?
Alex Baranosky
Yuck. I'd sooner use a collection that you can add Hobby objects to than an Enum for this. Granted, you could erroneously try to add a Hobby more than once to such a collection; but you can use a Flag enum incorrectly as well. I believe the Microsoft guidelines discourage flag enums these days.
Kyralessa
@Kyralessa: You'd really rather create an object and a container when all you need is two ints?Then presumably loop through your container to see if a flag is set?It's not pretty but it is efficient.
JonB
+2  A: 

I saw this one before: a programmer is assigned a 'feature' that results in an exception being thrown inside a catch. He proceeds by implementing another catch, that does nothing:

Original code:

try
{
    // Do something
    // Cause an exception
}
catch(Exception e)
{
   Logger.Log(e.Message); // throws
}

Fixed code:

try
{
    // Do something
    // Cause an exception
}
catch(Exception e)
{
   try
   {
   Logger.Log(e.Message); // throws
   }
   catch { }
}

We never saw the bug again, until customer looked at the final product. Need I say more.

GregC
From what I've seen, it's pretty common practice to ignore errors that occur during error logging. Why is this bad? How should the situation be handled instead?
Sander
1. If logger is yours, have a fail-safe method to log exceptions in the logger. Also, make sure that logger catches its own exceptions.Common practice is to log to different files with file names that include thread name and process name. This will help to avoid threading issues.2. If logger is someone else's... i don't know. Make your own, I guess.
GregC
So your logger code completely sucks and can't be trused. The problem should never have occured in the first place. Poor example
Mahol25
If logger can't write to its normal output, maybe it should have a secondary output, just for failures during logging. A simple message box won't do, especially if you're running on a headless server.
GregC
A mistake to avoid -- catch-all blocks that do nothing.
GregC
+11  A: 

I always get annoyed when I see these in web forms:

try
{
  int result = int.Parse(Request.QueryString["pageid"]);
}
catch
{...

Instead of using

int result;
if (!int.TryParse(Request.QueryString["pageid"] , out result))
{
    throw new ArgumentException.... 
}
Jon Jones
+2  A: 

Here is a good set of guidelines and best practices from Juval Lowy (founder of IDesign).

Most of them are presented as facts without justifications, but answers can be found in his book "Programming .NET components".

Although some statements can be considered as too strict and arguable I think it's worthwhile for everyone to run through his list and think about them.

+13  A: 

Forgetting this:

DBNull.Value != null

From MSDN,

Do not confuse the notion of a null reference (Nothing in Visual Basic) in an object-oriented programming language with a DBNull object. In an object-oriented programming language, a null reference (Nothing in Visual Basic) means the absence of a reference to an object. DBNull represents an uninitialized variant or nonexistent database column.

The common mistake isn't necessarily thinking that DBNull.Value is a null reference. I think it's more common to forget that your DataTable or other database-sourced object contains DBNulls rather than null references.

Kyle Gagnet
+1 I don't forget but I find it a pain to deal with as you end up checking for null to give a DBNull.Value often.
PeteT
+3  A: 

Not writing defensive code that checks for nulls.

MyClass t = GetAnInstance();
t.SomeMetehodCall(); // may throw NullReferenceEx

// or worse...

SomeOtherFunction( t ); // may also throw NullReferenceEx

Debugging NullReferenceExceptions can be a frustrating time-killer in .NET development.

LBushkin
Depends, if GetAnInstance will ever return null?If not, don't check it. If for some odd reason it does when it never should, you now know that GetAnInstance is wrong.
Sekhat
+13  A: 

Forgetting that exception catch blocks are matched in the order defined and that more general exceptions will supersede more specific ones.

try
{
  // some code that may throw...
}
catch( Exception x )
{
  // catches all exceptions...
}
catch( NullReferenceException x )
{
  // never reached because catch( Exception x ) is more general...
}

Resharper and FxCop can help avoid this error.

LBushkin
Your example does not compile. The C# compiler actually catches the very error you are describing. There is no need for Resharper or FxCop here.
Timwi
VB.NET also warns about this, but it also has to remove this warning when When is used (irrespective of if it is still valid).
Mark Hurd
+6  A: 

Failing to synchronize to the GUI thread from a different thread causing "Cross-Thread Operation not valid" Exception

How to resolve

SwDevMan81
This is a good one.
Rei Miyasaka
+2  A: 

This one sometimes gets us: in Linq, using First() instead of FirstOrDefault() on a IEnumerable that may be empty. Sometimes, it seems intuitive that First would return a null, rather than what it does with the exception throwing.

Jacob
+3  A: 

Check out this book: Framework Design Guidelines

it contains a lot of DOs and DO NOTs

HomieG
I hope it says "do not design frameworks"
finnw
+8  A: 

Modifying a collection by iterating the collection

Contrived code sample:

List<int> myItems = new List<int>{20,25,9,14,50};

foreach(int item in myItems)
{
   if (item < 10)
   {
      myItems.Remove(item); 
   }
}

If you run this code you'll get an exception thrown as soon as it loops around for the next item in the collection

The correct solution is to use a second list to hold the items you want to delete then
iterate that list i.e

List<int> myItems = new List<int>{20,25,9,14,50};
List<int> toRemove = new List<int>();

foreach(int item in myItems)
{
   if (item < 10)
   {
        toRemove.Add(item);         
   }
}

foreach(int item in toRemove)
{
     myItems.Remove(item);
}

Or if you're using C# 3.0 you can use the List.RemoveAll like this

myInts.RemoveAll(item => (item < 10));
zebrabox
Actually, you can simply write:myInts.RemoveAll(item => item < 10);
ShdNx
And you must mean C# 3.0, since neither C# 3.5 exists nor do lambda expression require .NET 3.5 (in fact, I use list.RemoveAll(x => x < 10) all the time in my .NET 2.0 application, along with all the other C# 3.0 language features, excluding linq).
Allon Guralnek
@ShdNx - Thanks for the tip :)@Allon - Yep, thanks for the correction, I'll update
zebrabox
how about: for (int i = 0; i < myItems.Count; ) { if (myItems[i] < 10) { myItems.RemoveAt(i); } else { i++; } }
SwDevMan81
+8  A: 

I've run into a lot of code that doesn't make use of the TryParse functions in classes (like int.TryParse). It makes the code look a little neater and returns a bool result instead of throwing an exception in which you will have to try to catch.

Mike
Just an addition, handling exceptions can be somewhat heavy on the CPU if you expect a lot of errors.
Rei Miyasaka
+8  A: 

Similar to this answer, but using String.Format.. It helps readability a lot..

Instead of this..

Console.WriteLine("A: " + 9 + "\nB: " + 34 + "\nC: " + someInt);

Use..

Console.WriteLine("A: {0}\nB: {1}\nC: {2}", 9, 34, someInt);
Bluestone
Please note that you don't need String.Format() to reach this effect as Console.WriteLine has the same behavior if I am not mistaken.
TomWij
@Tom: True, the Console.WriteLine has an overload that saves you a call to String.Format. I just wish Debug.WriteLine has such an overload as well...
Allon Guralnek
I took the liberty to correct it.
Konrad Rudolph
I just wished that the {0}...{x} parameters could be optional named for some clarification when working with multilanguage-strings and translations. Instead of string.format("You are {0} years old and we have {1} people who are at same age. The median age are {2}",x,y,z)this would be prefered in some cases when sending strings to translators:string.format("You are {0:Age} years old and we have {1:AmountOfSameAge} people who are at same age. The median age are {2:MedianAge}",x,y,z)
Stefan
+3  A: 

One horrible pitfall is a method calling itself when you meant to call an overload eg.

 public static void MyMethod(int id, bool always, string filter)
 {
  // Do something
 }

 public static void MyMethod(int id, bool always)
 {
  MyMethod(id, always); // Ouch!
 }

 public static void MyMethod(int id)
 {
  MyMethod(id, false, null);
 }
Dan Diplo
Viva optional parameters, no need to write these useless overloads
moi_meme
@moi_meme: If it's a public method in a public class, you don't really want to use optional parameters as they are compiled into the caller. Great fun when you change the Default Value of one of them and wonder why it doesn't work :) http://www.stum.de/2010/04/19/how-optional-parameters-work-why-they-can-be-dangerous-and-why-they-work-in-net-23-as-well/
Michael Stum
A: 

One of the worst thing even the experience programmers also doin is assigning db null values to variables without verifying it

-- missing db null verifications

always perform a check on db ops

(drOutput[iMainIdentifier] != Convert.DBNull) ? drOutput[iMainIdentifier].ToString() : null;

--Accessing the fields in nulled object without checking

--calling the nulled object without initializing it

--in ui apps, using non ui thread to update the UI

--using unavailable column names in the datareader getordinal() methods

--missing breaks in case staments..

--break ur loops carefully. there are scenarios we are looking for a specific item within a loop for further processing and letting the loop continue even the specified item already identified..

Ramesh Vel
+1  A: 

not catching any errors at all, or handling them wrong. I know some guys who will write whole programs and not catch any errors, then wonder why the s*** crashes. Maybe the bigger mistake is not knowing your development language thoroughly enough.

BBetances
my s*** doesn't crash because good programmers don't make exceptions and it needs a genius to understand.
Behrooz
At least `On Error Resume Next` is dead.
Bobby
+10  A: 
public DateTime IncrementDateByOneDay(DateTime date)
{
   DateTime result = date;
   result.AddDays(1); //ATTENTION
   return result;
}

This did not change "result". Correct version:

public DateTime IncrementDateByOneDay(DateTime date)
{
   DateTime result = date;
   result = result.AddDays(1);
   return result;
}

This is just an example of course. I found such bugs already inside other methods and it's really hard to find since it seems to be correct by just running over it.

Juri
This should have been written as a simple one-liner to begin with: return date.AddDays(1); . Not more needed and much less error prone.
Alex
I think someone posted a similar situation with SubString, definitely something to learn from
SwDevMan81
Found it: http://stackoverflow.com/revisions/381074/list
SwDevMan81
@Alex, it should not be written at *all*, if you allready have a datetime-object to send to the function, why not use the .Addays(1) on that object to begin with. (I know, the example was an example to make an point)
Stefan
you know the example is stupid?because it does the same thing as AddDays(1) and it returns a value while the name says it alters the input.
Behrooz
+3  A: 

Similar to this one, when defining a property

...
private string _MyString;
public string MyString
{
  get
  {
    return MyString; //ATTENTION
  }

  set
  {
    ...
  }
}

At runtime this gives a nice crash. Of course this should be written as

private string _MyString;
public string MyString
{
  get
  {
    return _MyString;
  }

  set
  {
    ...
  }
}
Juri
You can generate the properties automatically, the Visual Studio takes care of it and nothing could be wrong...
Thomasek
Of couse, but often there is the need to still keep a private variable instead of the automatic property declaration :)
Juri
@Thomasek : Not Visual Studio, the compiler takes care of it.
Andrei Rinea
Hah, this messed me up a few times.
Rei Miyasaka
+2  A: 

Boxing/Unboxing is one of the common oversights of new developers. This was a more serious problem in the early days of .Net (before generics) but it is still quite easy to create innocent-looking code which is massively unefficient due to implicit boxing/unboxing.

Addys
+2  A: 

Risky code in the constructor. When I have to initialize an object with risky code (I. E. loading from XML), I usually have an Initialize() or Load() method, so I don't do it in the constructor, which can leave the object in an "incomplete" state. So instead of

try
{
    MyObject o = new MyObject();
}
catch(Exception ex)
{
    // handle exception
}

I do this:

MyObject o = new MyObject();

try
{
    o.Initialize();
}
catch(Exception ex)
{
    // handle exception
}
Carlo
+15  A: 

Checking a string variable if it is assigned. String object can be null so;

wrong!

if(someStringVariable.length > 0) {
    //do you always get this far?
}

correct

if(!String.IsNullOrEmpty(someStringVariable)) {
    //yeah! this one is better!
}
Emrah GOZCU
+1 Good answer, this is definitely good to know
SwDevMan81
You can get even better by using string.IsNullOrWhitespace in some cases (if .NET 4 is used)
Andrei Rinea
+2  A: 

Not using Events, as a developer that came across from C++ (many years ago) I found that I programmed C++ in .NET instead of using the built in functionality.

In on of my first .NET project I've implemented the observer pattern using interface and inheritance instead of simply using events.

Dror Helper
Hmmm, I think you've stated this a little too generally - interfaces can be preferable where you want to require the client implement a set of methods as part of the contract between your component and the user of the component. One of the reasons events are typically preferable for generation of events is that the user can select individual events to optionally subscribe to. There may be cases though where you want to require that the user handles a complete set of events, in which case an interface would be the way to go.
Phil
#Phil of course you're right - there are times interfaces are the right choice for implemeting the observer pattern. In my case it wasn't ;)
Dror Helper
@Phil "a complete set of events" can also be represented by a single event (the event args may need to supply additional information to discriminate between various sub events)...hence IMO the observer pattern is best implemented using events. Also FYI interfaces can contain events too.
SDX2000
+4  A: 

well, I went through all the answers, and they're all very important things to look out for, but I think the number one mistake of programmer is not documenting their code!!

it's not really a pure coding issue, but nevertheless I believe it is a most basic skill.

everyone makes mistakes, all of us write bugs. that's all human. but not commenting on your code, thereby making life easier on yourself, and more importantly for your fellow developer that will need to debug your code after you moved on, is the worst thing IMHO.

also, not using common design patterns (everyone knows singleton, but strategy, adapter, decorator, etc...), or not even knowing them, is something I see quite often.

Ami
I've heard of "singleton" but I have no idea about the other patterns. Does that make me a worse programmer? I don't think so. I bet I probably already use those patters in some appropriate circumstances, I just don't recognise them as patterns and I don't know their names. I don't feel that I have to.
Timwi
IMHO documenting code is not as important as writng self documented code...
moi_meme
+2  A: 

Handling ThreadAbortException:

try
{
}
catch(ThreadAbortException ex)
{
}

It's hard (if not impossible) to write code that will always handle a ThreadAbortException gracefully. The exception can occur in the middle of whatever the thread happens to be doing, so some situations can be hard to handle.

For example, the exception can occur after you have created a FileStream object, but before the reference is assigned to a variable. That means that you have an object that should be disposed, but the only reference to it is lost on the stack somewhere...

An addition side note to catching the ThreadAbortException is when you call .Abort() on a thread, it throws an uncatchable ThreadAbortException. "Uncatchable" because even if you do catch it, it is automatically rethrown at the end of the 'catch' block, so you can't stop its propagation. This does, then, have the effect of terminating the thread (provided it doesn't go into a loop in the 'catch' clause).

Finding an alternative is going to save you a lot of time and headache's down the line.

SwDevMan81
I don't understand what you are saying. You say your exception could happen in the middle of creating a FileStream object, and therefore you shouldn't catch the exception? That surely doesn't follow.
Timwi
@Timwi - No, what I'm saying is that the asynchronous nature of calling Abort can cause problems within your code (the example being a FileStream object is created, but not assigned to a variable).
SwDevMan81
Yes, the issue here is you should avoid using Abort. Nevertheless, it is a useful method to catch Ctrl+C in shell-like applications.
Mark Hurd
+2  A: 

Making sure to understand that strings are immutable in .NET.

So, whenever you do any operation on a string you get back a new string with the operation applied to the new string.

So if you have a lot of operations in a loop ( say appending values to a string ), it is instead recommended to use the StringBuilder object.

anirudhgarg
+1  A: 

Use background workers to make sure your Windows Form does not freeze while executing a thread. End of.

Lawrence
+2  A: 
string foo = GetString();
if (foo == null) throw ex1;
if (string.IsNullOrEmpty(foo)) throw ex2;

foo is checked twice for null.

Shimmy
+3  A: 

The common coding mistake I find the amongst by people inexperienced with C# is that they do not account for the fact that string comparison is case-senstive (unless you explicitly specify otherwise) especially when the comparison value comes from a database:

var foo = dataRow["ColumnName"].ToString();

if (foo = "ABCDEF")
    ...

The most common reaction change I see is to convert both values to uppercase or lowercase instead of using the Equals method with a StringComparison enum like so:

//bad
if ( foo.ToUpper() == "ABCDEF")

//correct
if ( "ABCDEF".Equals(foo, StringComparison.CurrentCultureIgnoreCase )
    ...

( OrdinalIgnoreCase or InvariantCultureIgnoreCase...)

Obviously, there is also the problem with using string literals, but that has already been mentioned.

The most common mistake I see with people that write code that interacts with a database is not accounting for nulls.

Thomas
Yeah, but burying code with international considerations when the application is used by 30 monolingual users in one office is silly. The "correct" way is almost 3 times the typing and visually cluttered for reading.
MatthewMartin
@MatthewMartin - Once you realize that `==` is case-sensitive, explicitly declaring the case comparison to easier to read IMO. If I see `foo == myspiffyvar`, I have to stop and think about whether the original developer understood that the comparison was case-sensitive or whether they overlooked it. That requires more effort on the part of the reader. Further, the extra typing isn't an issue with intellisense and autocomplete.
Thomas
+7  A: 

This is one that's probably endemic to any language: Ignoring the rule of "Don't Repeat Yourself", or DRY. I sometimes wish it were possible to administratively disable an IDE's paste functionality beyond a certain clip size.

I've seen (and cleaned up) way too many instances where somebody needed a method "just like this here one", only slightly different. All too often, the method in question is about fifty lines long, and the change they want to make is to some literal magic number that's peppered throughout, so they make a copy of the method, change all the appearances of the magic literal (or whatever trivial change they needed), and call it good.

Sometimes, they don't even commit this travesty at the method level! I once found a pile of cases in a switch where each of the case bodies were so nearly identical (and loooonng!), the "programmer" had to scope each case to avoid renaming his temporary variables. I confronted him about this, and he thought he'd been incredibly clever. Unfortunately, in this particular situation, it would've been impolitic to burst his bubble, but it was tempting nonetheless.

So, people, please, THINK before you insert! (Hmm... That's good advice in life as well as coding, isn't it? ;-) If there's a method that does nearly what you need to accomplish, rework it to additionally support your case and reuse, recycle, rejoice! If it's part of a larger method, extract the code into its own method and have the original method call it! Code may be good, but more code is NOT better!

Ahem. *sigh* I feel much better now. Thank you.

Eric Lloyd
This is one of those things I wish more people would abide by because it would make my life easier when taking over projects. I'm still a fairly new programmer(a little over 2 years as of today) compared to most people, but for some reason the DRY concept came naturally to me before I even knew what it was.
rossisdead
A: 

Be careful when calling calling exception handling methods in your catch statement, where the exception handling code throws and exception itself. You will be caught in an continuous loop. I found this issue a number of times through the years.

dretzlaff17
A: 

Here my favorite pet peeves:

a) Writing C++ style or (even worse) Java style programs

b) Premature optimization

c) Classes with more than one responsibility

d) Ignorance towards design patterns

e) Ignorance towards language and CLR features

f) Use of P/Invoke because of ignorance instead of necessity

g) "Yoda me desire like": if (5 == x)

h) "Walking like an egyptian" ({ on the same line as the introducing statement, like those Java people do it for some reason)

i) No curly braces - code without that is UNREADABLE

j) Procedural code, especially methods with more than 3 lines of code

k) Ignorance towards modern, functional language features

l) Copy & Paste

m) Code in places where it doesn't belong

stormianrootsolver
Methods with more than three lines of code? How exactly is one supposed to avoid these?
Will Vousden
It's very easy to do, Will. Just think in an object oriented way and forget about procedural coding. Most of my methods are shorter than that.Same goes for my classes. I consider a class with more than a single concern a terrible code smell.
stormianrootsolver
I'm still sceptical. Object oriented programming and imperative programming (I presume this is what you mean?) are complementary disciplines, not alternatives. How would you go about condensing this? http://pastebin.com/n67gPNrA
Will Vousden
@Will @storm just because your methods are 3 lines doesn't mean you have a good design. If you need methods named `write_foo`, `write_foo_part1` and `write_foo_part2` to keep in line with your "convention" then you're doing it wrong.
Earlz
@Earlz @storm: Precisely. Sometimes you have to do something which is inherently complicated and can't (or shouldn't) be broken down into logically independent steps. Promoting logic that would naturally be expressed imperatively to objects/classes is just an abuse of OOP. Things like `while`, `if`, `switch`, `foreach`, etc. exist for a reason. To arbitrarily limit yourself to three lines per method is senseless.
Will Vousden
point j: you can't be serious.
Charles
Three lines? You joking right, A try/catch statement is more than that.
Jamie Keeling
I still stand by it - if you need more than three lines of IMPERATIVE code (try / catch doesn't count), then something is wrong.And there is NO need for write_foo, write_foo_part1, etc... "switch", btw, is a bad code smell in the object oriented age. Smells like VB 6.0.
stormianrootsolver
@WillThank you for your example. The micro - architecture I would apply here:a) In the beginning you have two "if" - statements. They form part of the contract, where it's even possible that "IsEmpty" is invariant. Therefore they don't count, but they should be rewritten using CodeContracts.b) Coding the whole loop strictly functional (LINQ) in one line IS possible if you add new extension methods - this would lead to a better, more sophisticated library for yourselfDone.
stormianrootsolver
In a shorter form:If one needs methods with more than three lines of code, it's not a problem what he is doing in the method but more a problem of what he is doing in general.Thats my point.Needing endless chunks of imperative code is a sign that something is terribly wrong with ones knowledge about software development.
stormianrootsolver
Those damn Java people, don't know sh*t about braces. :E
Arnis L.
Btw, I do agree about those 3 lines. I myself do not follow this rule zealously though. Too lazy. And that's not an irony.
Arnis L.
+6  A: 

in C#, a lot of people are still using the "" to declare an empty string. I consider this as a bad programming practice. people should use string.Empty to strictly specify that the string is empty and not a empty quote that looks like somebody accidentally deleted the string.

example: BAD

string someString = "";

example: GOOD

string someString = string.Empty;
Martin Ongtangco
You're discussing coding standards here, not real mistakes that break stuff.
vdboor
Well, it breaks my heart to see this kind of programming... common errors come from wrong coding procedures that lead to communication issues among working developers.
Martin Ongtangco
@Martin In that case I still think a different example is needed, and you're overreacting a little for this case. The compiler can easily optimize `""` out for `string.Empty`.
vdboor
.Net needs a HeartBreakException.
rossisdead
I think it makes the code more complicated to write if its just a "known variable type" such as string. Just wondering if you also initialise your int like this: int number = int.MinValue;
BerggreenDK
A: 

Another bad practice is with poor use of StringBuilders. Some people append a break line by applying a new line code inside the string when they can actually just use .AppendLine.

example: BAD

StringBuilder sb = new StringBuilder();
sb.Append("first line \n");
sb.Append("second line \n");

or

StringBuilder sb = new StringBuilder();
sb.Append("first line <br/>");
sb.Append("second line <br/>");

example: GOOD

StringBuilder sb = new StringBuilder();
sb.AppendLine("first line");
sb.AppendLine("second line");

or

StringBuilder sb = new StringBuilder();
sb.AppendLine("first line");
sb.AppendLine("second line");
Response.Write(sb.ToString().Replace(Environment.NewLine, "<br/>"));
Martin Ongtangco
Unfortunately if use use AppendFormat you are forced to either use the bad method, have a blank AppendLine following it or create an extension method.
John
Purpose of the `StringBuilder` is to avoid useless memory copying, while a string is concatenated. All 4 examples confirm to this.Nothing breaks by inserting the newlines differently. It's like discussing you should be writing `if (! ..)` instead of `if (..)`.
vdboor
@Mark: write an extension method for those :-)
Jeroen Pluimers
@vbdoor: \n is different from Environment.NewLine on certain platforms, so better go for the platform-neutral Environment.NewLine
Jeroen Pluimers
@Jeroen Pluimers: good point, so `sb.AppendLine()` it is.
vdboor
Calling `Replace` is a horrible idea.
SLaks
@Jeroen Pluimers: I think you got the idea, so why do they down-vote still? We should be able to down-vote some of that down-voters who have no idea about what they down-vote! And than i saw the last line of the answer which shows this thing went too crazy... My bad down-voters :)
Emrah GOZCU
@jeroen, everyone wants to be the expert.
Martin Ongtangco
@Martin Ongtangco: Few of them may succeed. Hope you get there :)
Emrah GOZCU
@emrah, thanks!
Martin Ongtangco
+2  A: 

I see codes that use unnecessary methods calls. I've done that before, but with a little care, i think we can make it better.

here is a little example;

    public string TestToString(int param1, int param2, object param3) {
        string result = String.Format("{0}-{1}-{3}", param1.ToString(), param2, param3.ToString());
        return result;
    }

Calling ToString() is really not necessary for param3, it is clear you can see with a help of ildasm.

.method public hidebysig instance string 
        TestToString(int32 param1,
                      int32 param2,
                      object param3) cil managed
{
  // Code size       37 (0x25)
  .maxstack  4
  .locals init (string V_0,
           string V_1)
  IL_0000:  nop
  IL_0001:  ldstr      "{0}-{1}-{3}"
  IL_0006:  ldarga.s   param1
  IL_0008:  call       instance string [mscorlib]System.Int32::ToString()
  IL_000d:  ldarg.2
  IL_000e:  box        [mscorlib]System.Int32
  IL_0013:  ldarg.3
  IL_0014:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_0019:  call       string [mscorlib]System.String::Format(string,
                                                              object,
                                                              object,
                                                              object)
  IL_001e:  stloc.0
  IL_001f:  ldloc.0
  IL_0020:  stloc.1
  IL_0021:  br.s       IL_0023
  IL_0023:  ldloc.1
  IL_0024:  ret
} // end of method Test::TestToString

And for param1 is not that neccessary at all, let suppose it is a type of decimal, still you don't have to call ToString if you don't need to display culture specific representation.

In any case boxing will work faster than calling ToString() method. It matters if you call that kind of methods soo often in short period.

Emrah GOZCU
Any other specific examples that you can think of?
James
@James: You didn't like this example then :) I need to think about it.
Emrah GOZCU
Ok! Here is another one: Suppose you have a listbox and you set the datasource of the control on each postback, instead it is easy to check if it is not postback than set the datasource only once, because you already set the wievstate to on for that control or for the page which your control in.This way, you don't go any datasource and query it each time you postback. It is still faster :)I think this one is more clear, right?
Emrah GOZCU
+3  A: 

Overengeneering...

http://en.wikipedia.org/wiki/Overengineering

Starting with interfaces and models and concepts and then stuck because I didn't noticed this and that, then changing interfaces and classes and change code and then really stuck...

I've learned: build systems from a ground up, not the opposite :)

cheers

Marko
This seems like a general anti pattern to avoid, and not something specifically related to .NET developers.
Jan Aagaard
Yes, I agree... although it could be applied to .net and I learned it doing .net technologies...
Marko
A: 
 class Foo : IDisposable
{
    public int Denominator { private get; set; }
    public int DoDivision(int x)
    {
        return x / Denominator;
    }
    public void Dispose()
    {
        Console.WriteLine("I do nothing in Dispose method.");
    }
}

The following is not wrong but...

class Program
{
    static void Main(string[] args)
    {
        try
        {
            using (Foo f = new Foo())
            {
                f.Denominator = 0;
                f.DoDivision(1);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

why not do like so:

class Program
{
    static void Main(string[] args)
    {
        Foo f = null;
        try
        {
            f = new Foo();
            f.Denominator = 0;
            f.DoDivision(1);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            if (f != null)
                f.Dispose();
        }
    }
}
xport
And why does it wrong ? Personally I also prefer the second one, but what is objectively wrong in the first version ? I don't see any arguments.
Incognito
the first version is not wrong.
xport
the `using` version is much cleaner in my opinion then the `try finally` version
Earlz
@Earlz, but with using you need try-catch enclosing it. Why not use try-catch-finally at the same time?
xport
When 'new' and 'dispose' need to be paired together, 'using' does the job in one line and makes it explicit that the 'new' needs 'disposing'. Using a 'finally' to include a dispose just because you happen to have a 'try/catch' in the code already isn't really have much of an argument for doing it. The version with the 'finally' has extra complexity because it includes some extra conditional 'if' logic.
Scott Langham
+4  A: 

Misconception about static fields.

If two instances of an assembly running on two separate processes, the static fields are no longer related. Modification on static fields in the first process will not affect static fields in the other process.

My pitfall when I learnt C#, I get provocated with the statement that "all instances of the class will share the same static fields". This statement does not emphasize that it is only true if all instances are in the same process.

xport
even more! They don't need to be in separated processes but even only in separated AppDomains and the static stuff will not be shared.
Andrei Rinea
A: 

Worst programming mistake that bothers me daily, especially in others code is not commenting on your code. Properly Commented Comments are your friend.

James Campbell
Comments are the enemy. Rarely kept in sync with code; often point to unclear code or where a method can be extracted. Only add comments in exceptional circumstances. If your code needs a comment it is often the code that is the mistake.
John Nolan
Take a listen to this podcast. it's called : Why Comments Are Evil and Pair Programming With Corey Haines -http://deepfriedbytes.com/podcast/episode-35-why-comments-are-evil-and-pair-programming-with-corey-haines/
Morten Anderson
There was a great response in another question, I can't remember which one, "A comment is an apology".
Andrew Barrett
Where i work I deal with a crapload of others peoples code, not small projects either. If the programmer had at least made some comments here and there, it would have made my job alot easier, and after years of doing this, it has been a pain without knowing what they were thinking or what also may be involved. I comment all my code for this reason, plus it is always nice to have something to refer to if I have to jump back into my old code.
James Campbell
If you stick to using comments for explaining "why" and not "what", then I believe that you generally avoid all those annoying comments that don't add anything to the code.
Jan Aagaard
From Steve McConnell's Code Complete 2 "The three kinds of comments that are acceptable for completed code are information that can't be expressed in code, intent comments and summary comments." Being dogmatic about comments is detrimental to the problem-solving aspect of development. A hint, or in some cases an explanation of the problem is going to help the reader of the code. Granted, there's lots of bad comments out there, but that doesn't make them intrinsicly bad.
StuperUser
"Only a sith deals in absolutes."
StuperUser
As an instructor I had several years ago would answer pretty much any question in class: "It depends."I've worked with maintenance on extremely huge products, and someone making a summary of what was changed in response to a bug, and probably commenting out the old code so the bug doesn't get reawoken in a few years--excellent use of comments.OTOH, look at CodeProject.com and you'll see several samples where the writer seemed to have Comment Tourette's Syndrome, only every 8th line is actual code. BAD BAD BAD!
Jay
Let me add "Properly Commented code"
James Campbell
+6  A: 

Not understanding memory managment and garbage collection

The pit fall is assuming that just because it is a managed environment, I don't have to know about memory management. That's a mistake. Not learning about these things will eventually lead to memory leaks.

This includes correct implementation of IDisposable and how to manage disposable objects correctly.

Mahol25
Also, detaching event handlers appropriately - I've seen plenty of code that causes memory leaks by leaving event handlers attached, particularly in UI code
Paul Nearney
+3  A: 

Here is one in asp.net.

<form id="form1" runat="server">
  <asp:placeholder id="ph" runat="server">
     <asp:TextBox id="tb1" ruant="server" Text="test" />
  </asp:placeholder>
  <asp:TextBox id="tb2" runat="server" Text="another" />
</form>

And in code behind he tries to do something to all TextBoxes.

foreach(TextBox tb in form1.Controls.OfType<TextBox>())
{
   //here he can only get tb2
}

because .Controls returns the first-level child controls only (in this example will return ph and tb2. To get all child controls, you need a recursion:

public static IEnumerable<T> GetChildControls<T>(this Control control) where T : Control 
{ 
    var children = control.Controls.OfType<T>(); 
    return children.SelectMany(c => GetChildControls<T>(c)).Concat(children); 
} 
Danny Chen
+4  A: 

Believing that enums are exhaustive:

enum YesNo
{
    Yes,
    No
}

string GetColloquial(YesNo value)
{
    switch (value)
    {
        case YesNo.Yes:
            return "Yeah";
        case YesNo.No:
            return "Nope";
        default:
            return "This will never happen"; //oh yes it will!
    }
}

Enums are internally implemented as integers, so you can still do things like this:

Console.WriteLine(GetColloquial((YesNo)5));

This one can be dangerous, so watch out!

Rei Miyasaka
Huh... didn't know that, but I believe you - what I think SHOULD happen is an `InvalidCastException` if the value doesn't map to any Enum value. Microsoft: get on that!
Pwninstein
Agree, though in MS' defense, this is a surprisingly complicated problem. It's important when the enum is a set of flags rather than just a mutually exclusive selection, because then the value needs to actually be calculated with binary arithmetic. Versioning issues makes it even more difficult to just make it really strict. One solution might be to throw a compiler error if `default` isn't handled by a switch clause. F# does this, but it wouldn't be as effective in C# because it's more common in C# to use complex execution paths than in F#, which relies primarily on switches (matches)...
Rei Miyasaka
+15  A: 

Believing that you're improving array iterating loop performance by extracting the Length property ahead of time.

Surprisingly, this is actually slower:

int[] values = int[10000];

int length = values.Length;
for (int i = 0; i < length; i++)
    values[i] = i;

Than this:

int[] values = int[10000];

for (int i = 0; i < values.Length; i++)
    values[i] = i;

The .NET runtime injects a check each time you access a value in an array, to make sure that the index you've given it is >= 0 and < Length. This eliminates a whole slew of horrifying security flaws known as buffer overflows, and is one of the main selling points of so-called "managed languages" like C# or Java or Python over an unmanaged language like C/C++.

On the other hand, of course, this impedes performance to some degree (usually not much). .NET alleviates this by making an exception for certain cases. In loops like the one above, where the each value from [0] to [length-1] is being accessed, the check is ommitted, and the code run as fast as if it were an unmanaged language.

But this optimization can't be performed if Length is copied to a local variable first, because it has no easy way of knowing that your variable is correct.

Rei Miyasaka
+1 Wow, I did this all the time!
vash47
+2  A: 

doing

HyperLink_Back.NavigateUrl = Request.UrlReferrer.ToString();

without checking

Request.UrlReferrer != null
y34h
+3  A: 

Avoid doing risky instantiation in a static field initializer

WRONG:

public class Whatever {
     private static SomeExternalComObject externalObj = new SomeExternalComObject();
// ...
}

Slightly better:

public class Whatever {
     private static SomeExternalComObject externalObj;

     static Whatever() {
        try {
            externalObj = new SomeExternalComObject();
        } catch(ComException ex) {
            // backup strategy and/or logging and/or whatever else
        }
     }
 }

Otherwise debugging will be a great pain in the ... neck.

Andrei Rinea
Using the static constructor is a violation according to the Code Analysis in Visual Studio 2010. http://msdn.microsoft.com/en-us/library/ms182275.aspx It is recommended to use an inline call to a static method instead.
Pierre-Alain Vigeant
Yes, that is why I called the second block "slightly better" not "CORRECT" or "Good" or sth..
Andrei Rinea
+2  A: 

Array of non-object cannot be cast to array of object

        int[] data = { 1, 2, 3 };

        object[] objs = data;//compile time error!!!
xport
+4  A: 

Returning null when an empty list/sequence/array would suffice.

HtmlAgilityPack's SelectNode function returns null instead of an empty list, so what I could have written simply as:

var links =
    node.SelectNodes("//a")
    .Select(n => n.Attributes["href"].Value);

Ends up having to be:

var linkNodes = node.SelectNodes("//a");
IEnumerable<string> links;
if (linkNodes != null)
    links = linkNodes.Select(n.Attributes["href"].Value);
else
    links = new string[] { };

Urrrghhhh!!!!1

Rei Miyasaka
I agree. "Framework Design Guidelines" book recommends returning empty lists/arrays in cases such as this.
Arnold Zokas
+1  A: 

Believing that casting a collection to IEnumerable makes it read-only.

GetReadOnlyList does not return a read-only collection. It can be written to by casting back to List:

public IEnumerable<int> GetReadOnlyList()
{
    var list = new List<int> { 1, 2, 3 };
    return list as IEnumerable<int>;
}

public void UhOh()
{
    var list = GetReadOnlyList() as List<int>;

    list.Add(4);
}

You can avoid this is by returning list.AsReadOnly() instead.

Rei Miyasaka
Upcasting is terrible practice in general. There are MANY types, including any custom types that could implement `IEnumerable`, so just upcasting it to a list is asking for Exceptions. If someone hands you an IEnumerable, you treat it as an IEnumerable.
Aye, but someone who tries to do this is often doing it for malicious purposes anyway. For instance, you might expose plugin APIs, thinking you're safe because you're returning immutable collections probably with immutable content, and then someone might come along and remove all the entries... Or someone might edit the return value thinking it's a clever way to improve performance.
Rei Miyasaka
+4  A: 

This one almost bit me good:

Prefer readonly to const.

private const string connectionString 
     = Properties.Settings.Default.ConnectionString;

Since the const connectionString is resolved at compile time not runtime, I mistakenly believed that this was actually configurable.

What I needed was a readonly variable as such:

private readonly string connectionString 
     = Properties.Settings.Default.ConnectionString;

Which is instead, resolved at runtime. :)

I link Effective C# because I had read an item addressing why you should use readonly over const like a week before so it caused me to realize the error sooner. :)

townsean
+4  A: 

Never make your Windows Forms controls public. Always keep them private and use properties if you need to.

    public string Name
    {
        get
        {
            return textBoxName.Text;
        }
    }

and when you want to parse some text from Other form make as much as possible in that form to keep main form clear.

    public string Command
    {
        get
        {
            return "#Wait(" + textBoxTime.Text + ")" + Environment.NewLine;
        }
    }
Hooch