#523 – The using Directive Allows Omitting Namespace

A typical C# program will use types that are defined in a variety of namespaces.  Specifying the fully qualified type name that includes the namespace can become tedious.

using directive tells the compiler what namespaces to look for types in, avoiding the need for fully qualified type names.

Assume that we have a Dog type, defined in the DogLibrary namespace.  The fully qualified type name is DogLibrary.Dog.  But in the code fragment below, we can just use Dog as the type name, because of the using directive.

using DogLibrary;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            Dog kirby = new Dog();
            kirby.Bark();
        }
    }
}

So you can use a type name without its namespace if:

  • The type is defined in the same namespace as the current code
  • using directive for the type’s namespace is present
Advertisements

#522 – The Fully Qualified Name for a Type Includes the Namespace

If we define a Dog type in the DogLibrary namespace, the fully qualified name for the new type is DogLibrary.Dog.  You can use this full name when working with the type.

            DogLibrary.Dog kirby = new DogLibrary.Dog();
            kirby.Bark();

If you’re writing code that exists in the same namespace as a type, you can omit the namespace and just use the short version of the type name.

namespace DogLibrary
{
    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public void Bark()
        {
            Console.WriteLine("WOOOOOF!");
        }
    }

    public static class DogFactory
    {
        public static Dog MakeDog(string name, int age)
        {
            // Can just use "Dog" as type name
            Dog d = new Dog();
            d.Name = name;
            d.Age = age;
            return d;
        }
    }
}

#521 – Namespaces Help Organize Types

In C#, a namespace is a collection of related types.  The fully qualified name of every type actually includes the namespace that it’s defined in.

You use the namespace keyword to define a namespace.  All types defined within the pair of braces that follow the namespace name then belong to that namespace.

In the example below, the Dog class belongs to the DogLibrary namespace.

namespace DogLibrary
{
    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public void Bark()
        {
            Console.WriteLine("WOOOOOF!");
        }
    }
}

Because Dog is defined within the DogLibrary namespace, the fully qualifed name of the Dog type is DogLibrary.Dog.

#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

#518 – Splitting the Implementation of a Class Across Multiple Files

It is sometimes convenient to split the source code for a class across more than one source file.  You can do this using the partial keyword.

In the example below, we split the implementation of the Dog class between Dog.cs and Dog-IBark.cs.  The latter file contains the implementation of the IBark interface.  The class definition in both files is marked with the partial keyword.

    // Dog.cs
    public partial class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        /// <summary>
        /// Create new Dog with specified name
        /// </summary>
        /// <param name="name"></param>
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }
    }

 

    partial class Dog : IBark
    {
        public bool CanBark { get; set; }

        public void Bark()
        {
            Console.WriteLine("WOOOOOF!");
        }
    }

Notice that we don’t specify IBark inheritance in the first file, because it does not implement any IBark methods.

#517 – Static Classes

A static class is a class that contains only static members and cannot be instantiated.  You declare a class as static using the static keyword.

A static class:

  • Can only have static members (can’t contain instance members)
  • Cannot be instantiated
  • Cannot serve as the type of a variable
  • Cannot serve as a parameter type
  • Cannot inherit from another class
  • Cannot serve as a parent of another class
    public static class DogMethods
    {
        private static int NumBarks = 5;

        public static void BarkALot(Dog d)
        {
            for (int i = 1; i <= NumBarks; i++)
                d.Bark();
        }

        public static string MarriedName(Dog d1, Dog d2)
        {
            return d1.Name + d2.Name;
        }
    }
            Dog d1 = new Dog("Kirby", 12);
            Dog d2 = new Dog("Lassie", 47);

            DogMethods.BarkALot(d1);
            Console.WriteLine(DogMethods.MarriedName(d1, d2));