Sunday, November 9, 2008

Are internal members really internal?

Each C# developer knows the "internal" access level keyword — The "internal" keyword is an access modifier for types and type members. Internal types or members are accessible only within the same assembly.

But don't be fully confident in it when dealing with microsofties. Those artful guys invented in the .Net Framework 2.0 a special attribute — "InternalsVisibleToAttribute" and now your internal members can become - guess what? - public! (of course they will be visible only for specified assemblies).

No one knows the real reason for such an "invention" but this innovation has been highly estimated by test-driven development adopters because the usage of this attribute allows your test libraries to access internal classes and methods for additional testing and coverage.

I think that any other usage of it can be considered a lack of architectural design but what about the microsofties? Do they use it for product-level assemblies or for testing purposes only? Let's see. Oren Eini made some interesting investigation on how the attribute is used inside the .Net Framework:

System.Data allows:
  • System.Data.Entity
  • SqlAccess
  • System.Data.DataSetExtensions
Microsoft.NETCF.Tools allows:
  • System.Web.Services
Microsoft.Office.Tools.Common.v9.0 allows:
  • Microsoft.Office.Tools.Word.v9.0
  • Microsoft.VisualStudio.Tools.Office.Designer.Office2007
  • Microsoft.VisualStudio.Tools.Office.Designer.Office2007Tests
  • Microsoft.VisualStudio.Tools.Office.Outlook.UnitTests
Microsoft.Build.Conversion allows:
  • Microsoft.Build.Conversion.Unittest
Microsoft.Build.Engine allows:
  • Microsoft.Build.Engine.Unittest
System.Core allows:
  • Dlinq.Unittests
And so on.

As for Xtensive products, unit testing is the only application of the "InternalsVisibleTo" attribute.

Friday, November 7, 2008

Link: object disposal, finalization and resource management

This time I publish a link to an article - the article itself is really perfect. "Must know" for any .NET developer.

Here are some quotations from it to make you a bit more interested:
- Do allow your Dispose method to be called more than once. The method may choose to do nothing after the first call. It should not generate an exception.
- Consider setting disposed fields to null before actually executing Dispose when reference cycles in an object graph are possible.
- Avoid throwing an exception from within Dispose except under critical situations where the containing process has been corrupted.
- Do not assume your finalizer will always run.
- Do write finalizers that are tolerant of partially constructed instances.
- Do write finalizers that are threading-agnostic. Finalizers can execute in any order, on any thread, can occur on multiple objects concurrently, and even on the same object simultaneously.
- Do gracefully handle situations in which your finalizer is invoked more than once.

The original article is here.