Attention: We are retiring the ASP.NET Community Blogs. Learn more >

Contents tagged with Advanced .NET Techniques

  • Executing custom code on attributed classes at compile time

    Eoghan Murray read my blog on custom attributes and sent the following question:
     
    I am interested in doing the following:  Adding an attribute to certain classes, so that, at Compile time, information about them gets written to an xml file. I see that the built in System.ObsoleteAttribute can raise warnings at compile time, so I want to do something similar, except execute a piece of my own code at compile time.

    Now that I've spelled it out, it seems impossible!
     
    It is an interesting question.  I don't think it is possible to execute the code at compile time.  If anyone knows how, please explain.
     
    What you can do is build a custom attribute and mark your classes with it.  Then, have a post-build step that executes a program against the compiled assemblies that uses reflection to find the classes marked with your attribute and execute whatever code you want. 
     
    For example, you create a custom attribute called DocumentThis.  You mark all of your classes with that attribute, then create a small Documentor program that reflects over a .NET assembly and writes the name of each class that has the DocumentThis attribute to a text file.  Then your post-build step for the project can call Documentor with the project's output as the target.
     
    That's the best I can think of, let me know how it works.

  • 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:

  • Implementing IDisposable

    Classes that need explicit destruction semantics or wrap managed resource usually implement IDisposable to allow for predictable destruction outside of garbage collection.  As I was just reminded by a defect in my code, all classes that implement IDisposable must provide a finalizer (C# uses destructor syntax: ~MyClass) to handle freeing resources when Dispose is not called.  Additionally, the Dispose method should call should call the GC.SuppressFinalize method for the object it is disposing.  From MSDN, "If the object is currently on the finalization queue, GC.SuppressFinalize prevents its Finalize method from being called."
     
     
     

  • 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:
    1. 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.
    2. 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.

  • Transactional behavior when updating a DataTable

    Steve wrote, "I was checking out Transactional behavior on DataTables, and that's some good stuff.  Did you ever come up with a good workaround?"
     
    We already had our own DataViewWrapper class that inherited from DataView, which we were using to catch the Changed events and republish them with more information.  We then created a custom "Transaction" object, that keeps a static count of how many Transactions currently exist (it implements IDisposable for deterministic destruction).  Now the DataViewWrapper can check if we are in a transaction.  If so, we don't publish the changed events.  When the last Transaction is disposed, we publish any pending changed events.  As a later optimization, we could intelligently combine changed events.  It takes more code than I would like, but it works.