-
Implementing Equals in C#
-
While working on refactorings, I often notice domain objects that implement Equals incorrectly. Below is a sample implementation of Equals. The key points are that Equals should not throw an exception if obj is null or of the wrong type. Also note the different patterns for comparing reference and value members. See pages 154-160 of Richter's excellent Applied Microsoft .NET Framework Programming for more details, including different patterns for reference or value objects:
public override bool Equals(object obj)
{
if (obj == null) return false;
if (this.GetType() != obj.GetType()) return false;
// safe because of the GetType check
Customer cust = (Customer) obj;
// use this pattern to compare reference members
if (!Object.Equals(Name, cust.Name)) return false;
// use this pattern to compare value members
if (!Age.Equals(cust.Age)) return false;
return true;
}
-
Debug only methods in C#/.NET
-
In Steve Maguire's Writing Solid Code, he encourages writing Debug only code that double checks complex logic. For example, Excel uses a highly optimized evaluation method. In the Debug build, there is another method that evaluates the same arguments and the two results are compared to ensure that the optimizations haven't broken the intent of the code.
Writing Debug only code is a powerful technique, but can break the Release mode build. For example, debug only methods are often defined as follows:
#ifdef DEBUG
private void DoDebugChecks() {}
#endif
Then each call to DoDebugChecks needs to be wrapped in #ifdef blocks. Forget one, and the release mode build breaks. C# offers a better solution: the Conditional attribute.
[Conditional("DEBUG")]
private void DoDebugChecks() {}
This indicates to the compiler that DoDebugChecks is only executed in builds where DEBUG is true. The compiler automatically compiles out all references during the build. Two comments:
- I wish the .NET team had provided a [DebugOnly] attribute that gives the same functionality. I'm a stickler for compile time checks, and so I worry about someone mistyping DEBUG and creating a very hard to find defect.
- Debug only methods are great, but make sure they do not alter the state of the application. Just like in Debug.Asserts, make sure there aren't any side effects, or the release build will behave differently than expected.