Welcome to MSDN Blogs Sign in | Join | Help

D Melodic Minor Accidental

A conglomeration of random thoughts on C#, .NET, OOP, and working at Microsoft

Syndication

Other Sites

Short, sweet, to the point - Framework 2.0 is out!

In case you haven't heard (or even if you have, IMHO this could never be spread too fast), .NET Framework 2.0 is out.  This is a major improvement over the 1.1 Framework in terms of stability, and overall offerings including the ever-so-important generics support.  You can download the x86 version of the redistributable here: http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5.

I personally will be moving to generics and never looking back, so it'd be best to get the newest version of the runtime to as many people as soon as possible :)

There are also links under the "related links" section of that page to get the redistributable for x64 (AMD64), or IA64 (Itanium), as well as the Framework SDK (free, comes with a couple extra tools for developers).

Visual Studio 2005 ("Whidbey") has also shipped, and will be hitting the store shelves very soon.  Express versions should also be downloadable soon, if not up there already.

Posted Sunday, October 30, 2005 4:49 PM by TheoY | 1 Comments

"Find All References" Design, regarding interface members

One of the things that I've been working on to help finish Whidbey, are the new refactoring features.  However, I've recently found myself questioning the design for "Find All References", in regards to its handling of interface members.  I discovered this behavior while writing a toy project in C#, but the following example illustrates it better, in my opinion.  Imagine you're writing a generalized library - and provide two different interfaces, IResource and IStream.  Both of them have the notion of a Close() method (for simplicity sake, I'll put the interfaces in separate files, which will help make it easier to see the design confusion):

 

namespace Library {

 

    public interface IResource {

        void Close();

    }

}

 

namespace Library {

 

    public interface IStream {

        void Close();

    }

}

 

Simple enough, right? The conundrum arises when you have an object that implements both interfaces, and uses the the same member to implement them, such as the following:


using
Library;

 

class NetworkSocket : IResource, IStream {

 

    public void Close() {

    }

}

What struck me as awkward, is that if you then do "Find All References", on IStream.Close(), you'll get the following results:

  • (Definition) NetworkSocket.cs - (5,17): public void Close() {
  • (Definition) IResource.cs - (5, 14): void Close();
  • (Definition) IStream.cs - (5, 14): void Close();

Thus, intellisense reports that IStream.Close() is defined in all of those three places.  However, why is IResource.Close() in this list?  Some IDE-team members argue that the design was that we would return the transitive closure of all of the methods that are captured during this find process.  I, however, argue that this is definitely unintuitive.  This gets worse too, for example, introduce the following:

 

using Library;

 

class OtherResource : IResource {

 

    public void Close() {

    }

}

 

 

using Library;

 

class OtherStream : IStream {

 

    public void Close() {

    }

}

 

 

 

using Library;

 

class StreamReader {

    public StreamReader(OtherStream stream) {

        // ...read the stream ...

        stream.Close();

    }

}

 

 

Now, invoke "Find All References" on IResource.Close(). You'll get the following results:

  • (Definition) NetworkSocket.cs - (5,17): public void Close() {
  • (Definition) OtherResource.cs - (5,17): public void Close() {
  • (Definition) OtherStream.cs - (5,17): public void Close() {
  • (Reference) StreamReader.cs - (6, 16) : stream.Close();
  • (Definition) IResource.cs - (5, 14): void Close();
  • (Definition) IStream.cs - (5, 14): void Close();

IStream.Close() is on the list (which is the reverse case of the previous "strange" element), but what really makes me think this is wrong, is that StreamReader's use of OtherStream is there.  OtherStream doesn't even implement IResource, so it's impossible for OtherStream.Close() to be related to IResource.Close().  In that context, you *know* you're not dealing with an IResource, however, it's still a reference <shrug>.  This gets worse as you have more types that implement IResource or IStream, because whenever you do Find All References on Close(), you get even more unexpected results to wade through.

So, you wonder, is there any method behind the madness? It's all about Rename refactoring.  If you rename IStream.Close() to something else, you better rename IResource.Close() to the same thing, otherwise the NetworkSocket class will suddenly no longer implement all the members of IResource.  I think that's a valid concern, but IMHO, if you're sharing implementations on the same member, and then you rename one of the interfaces's declaration of that member, then I would expect a compiler error to be introduced, saying that you can no longer implement both interfaces with the same member now.  Just because one developer happens to implement my interface, and someone else's interface, doesn't mean that if someone else renames their interface member that I too should be renamed.

So, mine is obviously a directed perspective, but how do the rest of you out there feel about this?

 

Posted Wednesday, July 06, 2005 3:42 PM by TheoY | 3 Comments

Referring to "value types" versus "reference types", Part 2

Last Friday, I blogged about confusion between the terms "value" and "reference", when relating to .NET development.  The post can be found here:

http://blogs.msdn.com/theoy/archive/2005/06/24/ValueRef.aspx

This time, I'm continuing the discussion specifically relating to value types and reference types.  After this, passing by value / passing by reference will be covered, as well as referring to an object's "value" or its "reference". So, continuing... I left off stating that I still have the following topics to cover, as part of Referring to "value types" versus "reference types":

   (1) Enums
   (2) Type unification, boxing/unboxing
   (3) Interfaces and inheritance for value types

Enums

.NET has built-in support for a special kind of type, called an enum type.  Enums are also value types, and have all of the traits that I described for value types in the previous blog entry, except for some small differences that are not relevant to this topic.  One way to look at them is as specialized value types.  For example, .NET enum types don't have instance fields, nor methods or properties.  Basically they exist so that one can specify names for what would otherwise be numeric values.  Their syntax is as follows:

    C#/J#:
        enum
MyEnumType {
        }

    VB.NET (requires all enum types define at least one value):
        Enum MyEnumType
            OneSampleValue
        End Enum

Each of the languages will automatically assign values to the enums if you don't care, but also will let you define specific values to assign to their corresponding names if you wish.  As you'd expect, they all compile down to the same thing under the hood, which is one of the reasons why .NET language integration is so streamlined between C#/VB/J#.  However, when contrasting value types and reference types, a user only needs to know that enums are in the "value types" camp.

Type Unification, Boxing and Unboxing

This is when it gets a little hairy... so in the first article, I described value types getting allocated on the stack, and reference types on the heap.  However, there are some leftover questions that you're probably pondering, such as:

(1) If anything that doesn't extend from System.ValueType is a reference type, then how does the CLR tell the difference between value types and the rest of the types that descend directly/indirectly from System.Object?
(2) How do value types implement interfaces, and how are those interface implementations distinguished between those of reference types?
(3) Is System.ValueType itself, a value type or a reference type?

Those are all good questions, and require understanding of the CLR type unification system.  Java has less of this to worry over, since it doesn't support custom value types (it only supports its built-in "primitive types").  In fact, prior to Java 1.5/5.0, users had to explicitly convert their primitive types to their corresponding wrapper objects (e.g. java.lang.Integer).  In addition, users of reflection on Java would have to deal with two different class objects for each primitive and its corresponding wrapped type.  Not fun.

Thus for .NET, there came a need to unify this more - and they introduced a concept of boxing and unboxing.  You can think of boxing and unboxing as being another special form of copying, for a value type (in fact, one must realize that boxing and unboxing performs copies).  However, the distinction between boxing and unboxing from other forms of copying (say assignment, parameter passing or receiving return value) is that boxing places a value type inside a wrapper (a "box") where it *then* behaves like a heap object.  By wrapping value types as heap objects, they can then be treated the same way as other heap objects.  .NET has built-in support for object-oriented type systems - and likewise has to implement virtual methods similar to pre-.NET C++, and Java.  You probably guessed that virtual methods require some sort of special handling, that makes them different from non-virtual methods.  Since any subclass an override a non-sealed virtual method, there needs to be some infrastructure to look up which function to actually run.

The way that those usually work is that an object in memory usually has a pointer (just an address value to some other chunk of memory) that points back to a shared virtual method table (or v-table), since in .NET and Java, overriding a method overrides it for all instances of that type.  Then the object can be passed around as any super type that it implements, and when a function call is required, a lookup of the appropriate index in the v-table will allow for code to pick up the overriden method.  As long as the means to access the v-table pointer are consistent, and the indices are consistent, then a function for one type need not worry about if it is executing on object that's actually an instance of a subclass.

This is all fine and dandy, but once you're passing around pointers to objects, and you're trying to avoid examining what type they really are, then how do you know if you're dealing with an implementation derived from a value type, or a reference type? The answer is, by default, you don't.  That's why value types need to be boxable into heap objects, so that code that consumes any interfaces that they implement may be able to dispatch off of those objects without having to concern themselves on whether or not that object is a value type or reference type.  Thus, it makes things easier to realize that when dealing with objects at an interface type-level, you're always dealing with heap objects - either reference type objects, or boxed value type objects.

The reason why I discuss "unification" is that in .NET, this wrapped value type support is automatically generated for you whenever you define a new value type.  It would be a nightmare if each user had to define their own heap wrapper type for every new value type they defined.  That's why Java's explicit type wrappers aren't a scalable solution if they were to allow users to define their own primitives.  Also, when using reflection, boxed and unboxed value types share the same type object (e.g. if you use C#'s typeof() keyword).  This means that if you're dealing with boxed or unboxed objects using reflection, you can confidently know that testing them against a type object will do what you'd expect (another issue with Java's having two separate class objects for wrapped and unwrapped primitives).

The last tricky part is that the type, System.ValueType itself, is not a value type.  Users can only create objects of types that derive from System.ValueType, and using a value type as an instance of System.ValueType causes it to be boxed.  The reason why is that once you're dealing with a value type at the System.ValueType level, you have very little knowledge remaining about the value type (for example, you have no idea what fields it has).  All you have are virtual methods that you can call, which require boxing, as you'd expect.  The same thing applies to System.Enum - once you're dealing with an enum value at the System.Enum level, you're actually dealing with a boxed enum.

As you can tell, System.ValueType and System.Enum have to be special-cased in the runtime, as their descendents are all value types.  In my opinion, there's not really a great way to structure them in the inheritance tree, but here's how they're structured in reality: (go, go, ascii art)

   System.Object
      |
      +- System.ValueType
      |   |
      |   +- System.Enum
      |   |   |
      |   |   +- <all enum-types>
      |   |
      |   +- <all-non-enum-value-types>
      |
      +-
<all-other-reference-types>

I use VS 2005 (Beta2 is pretty stable) when I code, and one of the things that I always change first is the fonts and colors preferences.  I set VS to colorize all enums and value types in navy, instead of teal, so that I can notice what my code is doing, and whether or not I'm going to copy, box, or unbox.  As you can see, I've actually colorized the types System.ValueType and System.Enum in teal, because those types specifically, are actually reference types.  It's their derived types that are value types.

Interface inheritance for Value types

Users defining their own value types will notice that they can specify interfaces for their value types to implement.  Yes, this is a powerful corollary to the unification described previously.  When transferred to a context that requires an interface to be implemented, value types get boxed, and are then indistinguishable from reference types, to the interface consumers.  What I mean by indistinguishable is that consumers needn't worry if they're dealing with value types or reference types - but they can of course query if the object in question also extends from System.ValueType (e.g. in C#, using the "is"/"as" keyword).

I think that pretty well summarizes most of the important differences between value types and reference types.  In the queue of topics to cover in my future blog posts will be some best-practices for value types.

Posted Tuesday, June 28, 2005 1:31 PM by TheoY | 4 Comments

"Value" and "Reference" Confusion

While talking to someone yesterday, I witnessed yet another instance of "value" versus "reference" confusion.

What do I mean? This is particularly confusing in .NET, because of some probably mistaken jargon choices on Microsoft's behalf.  Commonly in .NET, the terms "value" and "reference" come up in these contexts:
(1) Discerning between "value types" and "reference types"
(2) Discerning between "pass by value" and "pass by reference"
(3) Referring to an object's "value" or "reference".

I don't blame anyone when they get confused by these terms, I mean - when someone discusses .NET with me, and mentions "value" or "reference", I often end up asking them to disambiguate in which context they are referring.  I'll have examples in C#, VB, and J# in this post, to help people associate what I'm discussing with the actual code that they've probably seen.

1. Referring to "value types" versus "reference types"

This is probably the most common need to actually discern between the two, and is greatly associated with other .NET concepts such as nullity, boxing, heap vs. stack allocation, virtual methods, and tons of other things.  For Java users, the term "primitive" is synonymous with .NET's "value type" term.  What this means, is that a value type is what the CLR/CPU actually end dealing with when it comes down to performing computations, and comparisons.

Users familiar with how a program works are probably also familiar with the term program "stack" versus "heap".  Unfamiliar users need only understand some basic distinctions between the two:
    (1) They're both sections of memory in a program, but are allocated and treated in different manners.
    (2) The program "stack" is a memory section that exists for the currently executing part of the program, and typically holds reserved space for local variables.
    (3) The program "heap" is a part that contains reserved memory that might persist past the current function, thread, and possibly persist the entire lifetime of the program.  In some programs, there are other parts of memory that persist throughout the program, but this is the one that you'll be dealing with the most in .NET.
    (4) Memory reserved in the program stack, for a particular function, is reclaimed / reused automatically when the function returns.  If the function A calls function B before returning, function A's stack memory will persist all the way through until function A finishes, including the portion of the time that function B is being executed.

Now "objects" and "classes" are all about two things: containing things in memory, and inheritance.  The characteristics of these memory sections are extremely important with deciding how an object needs to be treated.  Here're the differences now, between "value types" and "reference types".

Under the hood, "reference types" are always allocated on the program heap.  When the CLR decides to make one, it first chunks out the appropriate amount of memory on the heap before running the constructor.  Whoever called for the creation of an instance of this reference type will then get back the "pointer", or the address of the object's memory in the heap.  Everywhere that consumes this type will deal exclusively with addresses to heap memory.  Most of the classes/types in .NET are reference types.  You declare a new reference type in C#, VB.NET, and J# using the "class" keyword.  If I wanted to define a reference type called "MyReferenceType", I'd use the following syntaxes:

   C#/J#:
      class MyReferenceType
{

      }

   VB.NET:
      
Class MyReferenceType

      
End Class

The above three examples do / compile-to the exact same thing.  Now, value types differ in the way that you probably guessed... they're allocated out of the stack.  That means that when a function executes, all of the value types it uses are known before hand, and are laid out before execution actually begins in the function.  It also means that the memory allocated for them must go away when the function finishes (returns).  However, there are a couple of things that must be done in order to keep the CLR a safe/managed environment.

If you're using a value type in your function, how can you return it to your caller, if the memory allocated goes away/gets reused? Obviously that wouldn't be safe.  The way that this is resolved is that functions can only return a copy of that memory.  Likewise, when you pass a value type to a function, by default (I'll explain later in this post), it's copied.  This is a simpler allocation and reclamation process than heap objects (which are reclaimed by the garbage collector), so it's often faster.  However, it's only faster for small objects - otherwise all of the copying catches up with you.  In fact, your basic types are all value types - for example, the "int" in C#/J# and VB's "Integer" are value types.  You can declare your own custom value type in the following syntax:

   C#:
      struct MyValueType {

      }

   VB.NET: (requires all value types have at least one field)

      Structure MyValueType

         Private SampleField As Integer

      End
Structure

   J#: (requires all value types to explicitly extend from System.ValueType)

      import System.*;

      final
class MyValueType extends ValueType {
      }

The VS 2005 C# IDE provides the additional feature that people can invoke the "Go to Definition" command on any of the built-in types, as if they were defined by your source code.  If that's the case, you'll see a file that's generated on the fly, that's in a C#-like syntax.  For example, "Go to Definition" on "int", in C# for VS 2005, brings me to:

   namespace System {

      public
struct Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int> {
         ...
      }
   }

Which allows you to see that "int" is really an alias for "System.Int32", which is a value type since it uses the struct syntax.

So, this is just a starter on the difference between value types and reference types, but I'm taking a break.  Some more things that I'll cover in my next post, before finishing this point are:
   (1) Enums
   (2) Type unification, boxing/unboxing
   (3) Interfaces and inheritance for value types

Posted Friday, June 24, 2005 1:29 PM by TheoY | 9 Comments

Comparing C# and VB.NET

A reader wrote me just now:

Hi,

I just came across your blog and seeing that you're mentioning random thoughs on .NET, I was hoping you'd be able to answer this question: Is there any real difference to coding in VB or in C# when it comes to the .NET framework? If there are differences, do they still exist when I narrow the topic down to .NET web applications?

Thanks,
Max

When it comes down to it, in my opinion, there aren't many significant language differences between VB.NET and C#.  Most of the constructs in those languages are achievable from the other language, which is why you'll often see samples online in both languages.  I think VB.NET includes more implicit conversion operators, as well as a bunch of other constructs if you disable option-strict compiling (such as late-binding).  C#, as a language, will generally be more explicit than VB. 

With VS 2005 (C# 2.0), C# includes anonymous methods, which are not a VB construct - VB users can workaround it by declaring new types/methods as necessary (which is what the C# compiler does under the hood).  C# 2.0 also supports new iterator methods (using the yield keyword), which I think is unsupported by VB.

VB includes a ton of "built-in" functions, which usually delegate to other .NET framework library functions that are accessible by C#.  Because of that, VB programs load several .NET framework DLL's that are not always needed in all programs, but are required for supporting VB built-in functions.  In C#, a lot of what the language does to supplement the .NET Framework isn't providing specific built-in functions per se, but more language features, that affect the way your code is compiled (instead of introducing other dependencies).

In regards to ASP.NET and web applications, I don't think that the above discussion applies any differently - the ASP.NET integration should be nearly identical for both languages.  Any preference towards choosing VB over C# or vice versa will probably be off of developer's taste.

I'm sure other folks out there will point out other important differences between C# and VB, but these are the ones that come to mind.

Posted Monday, June 20, 2005 2:05 PM by TheoY | 5 Comments

Re-commission

So after a super long hiatus, I've finally admitted that I'll end up posting far too infrequently if I restrict myself to writing a purely technical column.  I mean, for technical posts, there's a lot of vetting that I put myself through in order to be very confident in my posts (and still trying to maintain as semblance of working full-time as a developer).

Therefore, it's probably best that I re-commission this blog for more than just covering OO and .NET ideas, but also covering my perspective on working at MS / Developer Division / C#.  I've also been solicited by some friends that are interested in programming, that maybe I begin a blog that covers programming 101, similar to a computer science course, and of course, using C# :)

So here goes - and I hope you guys like the new feel of my blog.  Oh, the explanation of the new title - you've probably guessed that's it's a reference to music in some way... the music theory nerds out there will probably know that the only accidental (sharp or flat note) in the ascending D melodic minor scale is the C# accidental.  I guess the esoteric title is partly a rejection, on my behalf, over the need for titles :)

Posted Monday, June 20, 2005 12:07 PM by TheoY | 0 Comments

Transitioning

Some personal news:

I've recently accepted an offer to develop for the C# IDE team (exact switch-date TBD).  This would have me working on the same dev team with some of your likely familiar bloggers:

and of course, there's Anson (http://blogs.msdn.com/ansonh), a trusty IDE program manager. 

Things are still TBD on exactly what I'd be working on within the IDE, but I'm looking forward to the change of scenery and with working with these great people :)

Posted Thursday, November 18, 2004 7:58 PM by TheoY | 0 Comments

Filed under:

.NET Framework SP's Available!

For those who haven't gotten their hands on an Windows XPSP2 CD, new .NET Framework SP's are now available, for versions 1.0 and 1.1 (the first version of 2.0, or "Whidbey" is still yet to be released).

Here are the links to Microsoft's download center, the related "Knowledge Base" links may not become active on the web for a couple hours.  When they become active, you'll be able to see a list of fixes included in these service packs.  Rest assured, these patches are a culmination of a ton of work (by the .NET Framework team, and my team).  In a couple of days, they should also become available via Windows Update.

.NET Framework Version 1.1
Service Pack 1 for All OS's other than Windows Server 2003
Service Pack 1 for Windows Server 2003

.NET Framework Version 1.0
Service Pack 3 for All OS's other than XP for Tablet PC / Media Center

Notice there are two links for the 1.1 version: it's because the .NET Framework is installed via Windows Installer technology on most operating systems, but is incorporated as an OS component for Windows Server 2003.

Likewise, 1.0 .NET Framework was incorporated as part of the XP version for Tablet PC / Media Center.  So those users will actually get SP3 for the 1.0 .NET Framework by simply installing XPSP2.

If you're running Windows Server 2003, you should reboot after installing the 1.1 Framework SP in case some files (e.g. DLL's in the CLR and base class libraries) were in use during installation.  The patch on Windows Update will always ask for reboot for the 1.1 SP1 patch.

Posted Monday, August 30, 2004 5:00 PM by TheoY | 11 Comments

More Singleton

Ok, so I lied: I'm not moving on to unions quite yet.  Cyrus brought up a great point on the last post about .NET serialization, as well as the lack of thread safety in my third example.  Due to the shared nature of singletons, I have to agree that thread-safety is an important enough requirement to mandate an expansion of the singleton story...

In addition, Andrew provided a great link about some other thoughts on implementing singletons in .NET.

http://www.yoda.arachsys.com/csharp/singleton.html

It introduces a neat way to resolve the thread safety by relying on the lazy loading of types in .NET.  Although the article from arachsys.com doesn't mention serialization, if you read the MSDN reference on System.Runtime.Serialization.SerializationInfo, its example includes a way to control reinstantiation during deserialization in order to obtain the shared instance instead of the default serialization behavior of invoking a constructor.  In doing so, you have to create a type that proxies for you during serialization -- but there's no reason why it shouldn't be the same nested type used for delay loading of the lazy-shared instance.  Thus, whip in some explicit interface implementations (comment if you really want me to cover this topic), and voila!, you get the following:

[Serializable]

sealed class Foo : ISerializable {

      // change the default constructor to private

      private Foo() { }

 

      public static Foo Only {

            get { return SerializationProxy.sharedOnly; }

      }

 

      public object DoFunctionality();

 

      [Serializable]

      private class SerializationProxy : IObjectReference {

            internal static readonly Foo sharedOnly = new Foo();

            object IObjectReference.GetRealObject(StreamingContext context) {

                  // When deserializing this object, return a reference to

                  // Foo's singleton object instead.

                  return sharedOnly;

            }

      }

 

      [SecurityPermission(SecurityAction.Demand,SerializationFormatter=true)]

      void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {

            info.SetType(typeof(Foo.SerializationProxy));

      }

}

The example differs from both the MSDN example and the arachsys.com article, but I'm pretty convinced it's the right thing to do.  Creating a new type for serialization proxying is pretty much necessary unless you want to change the constructor semantics for the singleton type itself.  Consider the following:

Assume type Foo is its own serialization proxy.  During deserialization, the proxy instance of Foo is deserialized by default serialization means -- which involves invoking some constructor (either compiler provided default constructor, or user-coded).  Thus you lose the invariant that any instance constructor is only invoked once, since some instance constructor has to be invoked at every proxy deserialization before GetRealObject() is invoked on the proxy.

 

It seems better to “de-singleton” the proxy type and hide it away, and a private nested type comes natural to my mind.  Since it's nested, it allows us to also follow the arachsys.com and change the loading of the actual singleton instance to a form of "lazy loading", without ever having to introduce a synchronization keyword (e.g. "lock") or use the synchronization API.  Albeit, the code doesn't really reflect in its structure that it's particularly both threadsafe and lazy-loading.

 

So, why do we really have to worry about serialization? Mostly because any of these implementations only guarantee one instance per AppDomain, which is somewhat like a process-like abstraction for .NET, except you can have more than one AppDomain per process.  Each AppDomain has its own copies of static data though, so you can shield the effects on one against the other.  Sometimes this is what you want to do (say you're running some untrusted code).  However, this also prevents them from really sharing singleton instances.  Also, when you have two .NET programs communicating across different processes (either concurrently, or different invocations using saved state), or on different computers, serialization becomes key.

 

I still probably use, in practice, the first or second simplistic singleton implementation -- with the addition of serialization support if necessary... but covering this topic has definitely brought new light to my own design toolbox -- I'll probably opt for this nested-lazy-serializable implementation a lot more in the future.

Posted Friday, May 21, 2004 3:29 AM by TheoY | 5 Comments

Filed under:

Singleton Pattern

In the beginning, there was...

the singleton

Everything's got to start somewhere.  Just like there's only one object type to “rule them all”, the singleton represents cases where there's only one.

A pair of examples are the TextWriter instances that represents Standard Out and Standard Error.  You only need one instance for each of those, for your entire program.  It makes sense for all the code in your program, all the threads, all of ___(insert something here)_____, to share.  Since there's only one for the entire process, then you might as well represent it that way in your library or codebase.

Like the proverbial skinning of the cat, there are a bunch of ways to do this.  Here's a common one, say our type is Foo.

class Foo {

      // change the default constructor to private

      private Foo() { }

 

      public static readonly Foo Only = new Foo();

 

      public object DoFunctionality();

}

The above method is short and simple.  Here are the important things to take away:
(1) no public constructors: The point is to share instances, not to let people create their own.  The lack of public constructors indicates to developers that this is not your “run of the mill” type.
(2) immutable, immutable, immutable! nine times out of ten you don't want anything you do to this object to affect other code, threads, etc., in some inadvertent manner.  Another word for this is to make your type a functional type (no new ideas to functional programmers, who are used to dealing with singletons all the time). 

A more common thing that people will find in the .NET libraries is this implementation:

class Foo {

      // change the default constructor to private

      private Foo() { }

 

      private static readonly Foo sharedOnly = new Foo();

     

      public static Foo Only {

            get { return sharedOnly; }

      }

 

      public object DoFunctionality();

}

It hides the shared instance of Foo behind a property.  Library developers may choose this implementation since allows them to decide later exactly how to return their singleton instance.  In fact, in the gang of four design patterns book, the template they outlined is more similar to this, since their examples are in C++.

Another point to take in mind in regards to hiding your instance behind a property (or a method call) is that the compiler can no longer prove that two different accesses will always return the same instance of the object.  It's then up to users of this type to trust the implementation, but then again, it's another possible “bug” if your design explicitly wants only ONE instance.

Yet another common thing to do, if you've decided to abstract out the singleton behind a property is to delay its creation until needed, like so:

class Foo {

      // change the default constructor to private

      private Foo() { }

 

      private static Foo sharedOnly = null;

     

      public static Foo Only {

            get {

                  return (sharedOnly != null) ? sharedOnly :

                        (sharedOnly = new Foo());

            }

      }

 

      public object DoFunctionality();

}

Some people may not like the ternary (? :) expression, or the assignment used as an expression, but I think it's perfectly legit in something this simple.  What you'll notice changed is the removal of the readonly attribute, since you're instantiating on demand.  Although you're arguably gaining since you don't instantiate objects that you don't need for sure, you're also still opening yourself up for bugs by removing the readonly attribute (such as accidentally setting that field).

 

If you don't care about getting back the exact same instance, you may wish to statically refer to something similar to the lazy loader posted to JayBaz's blog, written by Cyrus, before he got his own blog.  But stay tuned to why I think IOptional<T> should be implemented differently.  It's been a little over the 48 hours Cyrus promised me to write this all up, but I've since then gotten an extension until morning :-P.

Others may point out that using either of the examples that employ the use of properties may slow down the program since you're actually executing code whenever you reference a property -- but this is usually trivial overhead, and one can probably assume that the JIT will optimize out the function call.

I bet you're probably thinking that I'm beating a dead horse, but I wanted to make sure to cover a lot of possible design choices and the pros and cons of each.  Next concept in the slate: unions.

Posted Thursday, May 20, 2004 11:50 PM by TheoY | 22 Comments

Filed under:

Coming up: Design Patterns

Quick detour (not so much of a detour). 

Cyrus has challenged me to 48 hours in order to expound on how he could've written is IOptional<T> better.  Actually, I started to explain some of my suggestions, but now he's imposed this limit, since he's too antsy for me to really finish writing out my entire rationale. 

So instead of writing real code, we're going to talk more about design and theory for a while... but I have a couple of caveats.

(1) I'm going to assume that you're already familiar with programming in .NET, and my samples will mostly be in C# (though they certainly can be ported to other .NET flavors).
(2) I'm also going to assume that you're comfortable with the semantics for single class-inheritance, as well as virtual methods.  Most of the material won't be directed towards explaining the semantics of the .NET language features, but more along the line of the question, “How do I use this the right way?”.
(3) Virtual methods are prolific throughout abstracted/generalized object oriented programs.  These are slower than “non-virtualmethods, but they also buy a lot of abstraction and scalability in design.  Most people will also agree that the “performance hit is marginal, and the payoff is quite valuable in development time, code complexity, and sustainability.
(4) Most of the examples I'll be writing will not consider thread-safety, which is usually its own can of worms.  The main reason is that for most of the upcoming examples, you can workaround thread-safety by giving each thread separate copies (unless they're supposed to share), or you can wrap synchronization logic using decorators.

With that in mind, let's begin with the singleton pattern.

Singleton Pattern: http://blogs.msdn.com/theoy/archive/2004/05/20/136528.aspx

Posted Thursday, May 20, 2004 10:07 PM by TheoY | 0 Comments

Filed under:

Introduction

Greetings online visitors!

So yes, this is yet another online blog, in fact a [hopefully] technical blog.  Fittingly, I should do a bit of a self-introduction to at least establish some history. 

So, to start off “professionally”, I'm a developer (a.k.a., SDE, or Software Design Engineer) at Microsoft, based in the Puget Sound area.  I'm on the Developer Division Sustained Engineering team, or DevDiv SE for short.  Or DDSE for even shorter.  At work, I work a lot on hotfixes for Visual C++ (versions 7.1, 7.0, and yes, even 6.0), which encompasses the editor, as well as MFC (Microsoft Foundation Classes), and the Microsoft C Runtime.  For my team, I also work on internal tools, as well as some “current” components of Visual Studio, or other things such as the Microsoft script engine (JScript, VBScript), used for the Windows scripting host, Internet Explorer, and tons of other products.  My main languages that I use at work are C++ and C#, and assorted scripting languages as necessary.

My team also touches the entire rest of Developer Division, which means we're responsible for issuing hotfixes and service packs for the .NET Framework, nearly every Visual Studio product, MSDN documentation, etc. -- so I'm one of many “firefighters” that try to come to the rescue when a problem is discovered in an already-shipped product in DevDiv.

Academically, I hold a Bachelors of Science in Computer Science from Rice University -- where I had a programming languages focus.  I really have a passion for object-oriented (OO) design, as well as effective programming languages.  This naturally makes me inclined towards interpreters and compilers, but I also enjoy just writing a good OO app.  Probably the only other random CS-interest that I have is in network-based programs (i.e. programming for the internet).

Most likely I think my next intention is to eventually begin a slow, but extensive project online with everyone, and being verbose about design decisions, and trying to show maybe some insightful / elegant (or sometimes just nifty) things you can do with the .NET platform.

Alright, until next time!  Theo, signing out.

This posting is provided "AS IS" with no warranties, and confers no rights.

Posted Sunday, April 11, 2004 1:05 AM by TheoY | 4 Comments

Filed under:

Page view tracker