#520 – Choosing Between a struct and a Class

struct and a class both encapsulate data and methods in a new type.  When you are creating a new type, you’ll generally create a new class.  But there are cases when a struct is the better choice.

Create a struct, rather than a class, when all of the following is true:

  • You want value type semantics, that is–a variable of this type directly contains the data and a copy is made whenever you assign the value to a new variable or pass the variable to a method
  • Data stored in the struct won’t be modified after an instance is created or does not change very often
  • You don’t need to inherit from another type (a struct inherits only from System.ValueType)
  • You need to store only a small amount of data in the type

#519 – Differences Between structs and classes

There are a number of differences between a struct and a class, including:

  • A struct is a value type (instance created on the stack); a class is a reference type (instance created on the heap)
  • A variable defined as a struct type contains the actual data in the struct; a variable defined as a class type references or points to the data stored in the instance of the class
  • Memory for a struct is released when its variable goes out of scope; memory for a class instance is released when the object is garbage collected
  • When a struct is assigned to a new variable, a copy is made (changes to the original are not reflected in the copy); when an instance of a class is assigned to a new variable, the new variable references the existing instance
  • When a struct is passed to a method, a copy is made

#510 – Declaring More than One Local Variable On the Same Line

You typically declare a local variable by specifying its type, the name of the local variable and an optional initial value.

int j;
int i = 42;

You can declare more than one variable on the same line, as long as the variables all have the same type.  Each variable can optionally include an initialization.

int j, i = 42;      // Only i is assigned
string name = "Sean", motto = "Carpe Libri";
Dog d1, d2, d3;
Dog kirby = new Dog("Kirby", 12), jack = new Dog("Jack", 14);
dynamic thing1, thing2;

You can’t, however, declare multiple implicitly-typed variables on the same line.

            var i = 12, s = "Sean";   // Error: Implicitly-typed local variables cannot have multiple declarators

#477 – Full List of Escape Sequences for Character Literals

You can use one of several escape sequences within a character literal to represent a character that you can’t include directly in the literal.

The full list of character literals includes:

  • \’ – Single quote (U+0027)
  • \” – Double quote (U+0022)
  • \\ – Backslash (U+005C)
  • \a – Alert (U+0007)
  • \b – Backspace (U+0008)
  • \f – Form feed (U+000c)
  • \n – New line (U+000A)
  • \r – Carriage return (U+000D)
  • \t – Horizontal tab (U+0009)
  • \v – Vertical tab (U+000B)

            char single = '\'';
            char dquote = '\"';
            char backslash = '\\';
            char alert = '\a';
            char backspace = '\b';
            char formFeed = '\f';
            char newLine = '\n';
            char cr = '\r';
            char horizTab = '\t';
            char vertTab = '\v';

You can also use a backspace followed by 0 to indicate a null character.

            char nullChar = '\0';

#466 – Explicitly Assigning Only Some Enumerated Values

When defining an enumerated type, you can explicitly assign values to some of the enumerators and let the compiler implicitly assign values to others.

Any enumerated values that you do not explicitly assign a value to will automatically receive a value one greater than the previous value (whether explicitly or implicitly assigned).

For the following enumerated type:

        public enum Moods
        {
            NOMOOD = 0,
            Ambivalent,
            Happy,
            Elated,
            Grouchy = 10,
            Crabby,
            Irate
        }

The Ambivalent enumerator will have a value of 1, Happy will be 2, Elated will be 3, Crabby will be 11 and Irate will be 12.

#465 – Dumping All Names and Values for an Enumerated Type

You can use the Enum.GetValues method to iterate through all values of an enumerated type.  You can use this method to dump out the name and value of each enumeration value in the enumerated type.

        public enum Moods
        {
            NOMOOD = 0,
            Ambivalent = 1,
            Crabby = 10,
            Grouchy = Crabby - 1,
            Happy = 42,
            SuperHappy = 2 * Happy
        }

foreach (Moods mood in Enum.GetValues(typeof(Moods)))
    Console.WriteLine("{0} - {1}", mood, (int)mood);

#464 – Getting an Enumeration’s Underlying Type at Runtime

You can use the Enum.GetUnderlyingType static method to find out what the underlying type is that is being used to store an enumerated type’s enumerated values.

        public enum Moods : byte
        {
            NOMOOD = 0,
            Ambivalent = 1,
            Crabby = 10,
            Grouchy = Crabby - 1,
            Happy = 42,
            SuperHappy = 2 * Happy
        }

        static void Main()
        {
            Type moodStorageType = Enum.GetUnderlyingType(typeof(Moods));
            var min = moodStorageType.GetField("MinValue").GetValue(null);
            var max = moodStorageType.GetField("MaxValue").GetValue(null);

            Console.WriteLine("Underlying type for Moods is: {0}", moodStorageType.FullName);
            Console.WriteLine("Values can range from {0} to {1}", min, max);
        }

#463 – Enumerated Values Can Be Any Constant Expression

When you define an enum, the individual values can be implicitly defined (one greater than the previous value), assigned to a constant, or assigned to any constant expression.

In the definition of the Moods enumerated type below, constant expressions are used for some of the values.

        public const int HappyFactor = 42;

        public enum Moods
        {
            NOMOOD = 0,
            Ambivalent = 1,
            Crabby = 10,
            Grouchy = Crabby - 1,
            Happy = HappyFactor,
            SuperHappy = 2 * Happy
        }

#462 – Duplicate Enumerators in an Enumerated Type

When defining a new enumerated type, you can define multiple enumerators that have the same underlying value.  You might do this when you have a finite set of enumerated values and you want to map them to a smaller finite set of internal values.

In the example below, we have six different MovieRatings values, internally.  But we define 10 different enumerators for the type, so some of them end up mapping to the same value.

        public enum MovieRatings
        {
            DidntSeeIt = 0,
            NONE = 0,
            Crappy = 1,
            Horrible = 1,
            Watchable = 2,
            Average = 3,
            Good = 4,
            SeeIt = 4,
            Great = 5,
            MustSee = 5
        };

#461 – Enumeration Elements Don’t Need to Be Sequential

Enumeration elements are implicitly set to consecutive integers, starting at 0, as indicated in the comments below.

        // Default type is int
        public enum Mood
        {
            Crabby,      // 0
            Happy,       // 1
            Petulant,    // 2
            Elated       // 3
        };

You can also assign any values you like to the constants.

        public enum Mood
        {
            Crabby = -50,
            Happy = 80,
            Petulant = -20,
            Elated = 99
        };

You can define these constants in any order. They don’t have to be sequential.

        public enum Days
        {
            Friday = 5,
            Monday = 1,
            Saturday = 6,
            Sunday = 0,
            Thursday = 4,
            Tuesday = 2,
            Wednesday = 3
        };

Follow

Get every new post delivered to your Inbox.

Join 37 other followers