Singleton Design Pattern In C# – Part Three (Static vs Singleton)


Introduction

In this series on learning singleton pattern, we learned lazy initialization and eager initialization with practical examples. We also learned why it is necessary to make the singleton class sealed with the sealed keyword. In this article, I’ll try to explain the differences between static and singleton class. We will also see where to use static class and where to use singleton classes.

Continue reading “Singleton Design Pattern In C# – Part Three (Static vs Singleton)”

Advertisements

Learning C#: Custom Collection Classes in C#


Introduction

Being a .NET developer, we all are familiar with collections and generics. We know ArrayLists, Arrays, List and Dictionary etc. as collection classes through which we can iterate. This article will explain on how one can create their own custom collection class, which can be iterated through. The article follows step by step process to create a custom collection class to know what actually it takes to create a collection class. The purpose of the article is to learn the concept of collection classes through step by step practical implementations.

Continue reading “Learning C#: Custom Collection Classes in C#”

Learning C# (Day 11) – Events In C# (A Practical Approach)


Introduction

This article of the “Diving into OOP” series will explain all about events in C#. The article focuses more on practical implementations and less on theory.

Events (The definition)

Let’s start with the definition taken from MSDN.

“Events enable a class or object to notify other classes or objects when something of interest occurs. The class that sends (or raises) the event is called the publisher and the classes that receive (or handle) the event are called subscribers.”

Continue reading “Learning C# (Day 11) – Events In C# (A Practical Approach)”

Learning C# (Day 10): Delegates in C# (A Practical Approach)

This article of the series “Diving into OOP” will explain all about delegates in C#. The article focuses more on practical implementations and less on theory. The article explains the concept in-depth.


Introduction

This article of the series “Diving into OOP” will explain all about delegates in C#. The article focuses more on practical implementations and less on theory. The article explains the concept in-depth.

Delegates (The definition)

Let’s start with the definition taken from MSDN

“A delegate declaration defines a reference type that can be used to encapsulate a method with a specific signature. A delegate instance encapsulates a static or an instance method. Delegates are roughly similar to function pointers in C++; however, delegates are type-safe and secure.”

Continue reading “Learning C# (Day 10): Delegates in C# (A Practical Approach)”

Diving into OOP (Day 8): Indexers in C# (A Practical Approach)


Introduction

In my last article of this series we learnt about properties in c#. This article of the series “Diving into OOP” will explain all about indexers in C#, its uses and practical implementation. We’ll follow the same way of learning i.e. less theory and more practical. I’ll try to explain the concept in-depth.

Indexers in C# (The definition)

Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.”

Roadmap

Let’s recall our road map,

  1. Diving in OOP (Day 1): Polymorphism and Inheritance(Early Binding/Compile Time Polymorphism)
  2. Diving in OOP (Day 2): Polymorphism and Inheritance (Inheritance)
  3. Diving in OOP (Day 3): Polymorphism and Inheritance (Dynamic Binding/Run Time Polymorphism)
  4. Diving in OOP (Day 4): Polymorphism and Inheritance (All about Abstarct classes in C#)
  5. Diving in OOP (Day 5): All about access modifiers in C# (Public/Private/Protected/Internal/Sealed/Constants/Readonly Fields)
  6. Diving in OOP (Day 6): Understanding Enum in C# (A Practical Approach)
  7. Diving into OOP (Day 7): Properties in C# (A Practical Approach)
  8. Diving into OOP (Day 8): Indexers in C# (A Practical Approach)
  9. Diving into OOP (Day 9): Understanding Events in C# (An Insight)

 

Indexers (The explanation)

Like definition says, indexers allow us to leverage the capability of accessing the class objects as an array.
For better understanding, create a console application named Indexers and add a class to it named Indexer. We’ll use this class and project to learn Indexers. Make the class public, do not add any code for now and inProgram.cs add following code,

Lab 1

namespace Indexers
{
    class Program
    {
        static void Main(string[] args)
        {
            Indexer indexer=new Indexer();
            indexer[1] = 50;
        }
    }
}
Compile the code. We get,
Error Cannot apply indexing with [] to an expression of type ‘Indexers.Indexer’
I just created an object of Indexer class and tried to use that object as an array. Since actually it was not an array, it resulted as a compile time error.

Lab 2

Indexer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Indexers
{
public class Indexer
{
public int this[int indexValue]
{
set
{
Console.WriteLine(I am in set : Value is “ + value + and indexValue is “ + indexValue);
Console.ReadLine();
}
}
}
}

Program.cs

namespace Indexers
{
    class Program
    {
        static void Main(string[] args)
        {
            Indexer indexer=new Indexer();
            indexer[1] = 50;
        }
    }
}

Output

Here we just made a use of indexer to index my object of the class Indexer. Now my object can be used as an array to access different object values.
Implementation of indexers is derived from a property known as “this”. It takes an integer parameter indexValue. Indexers are different from properties. In properties when we want to initialize or assign a value, the “set” accessor if defined automatically gets called. And the keyword “value” in “set” accessor was used to hold or keep track of the assigned value to our property. In above example, indexer[1] = 50;
calls the “set” accessor of “this” property i.e. an indexer therefore 50 becomes value and 1 becomes index of that value.

Lab 3

Indexer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Indexers
{
public class Indexer
{
public int this[int indexValue]
{
set
{
Console.WriteLine(I am in set : Value is “ + value + and indexValue is “ + indexValue);
}
get
{
Console.WriteLine(I am in get and indexValue is “ + indexValue);
return 30;
}
}
}
}

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
Indexer indexer=new Indexer();
Console.WriteLine(indexer[1]);
Console.ReadKey();
}
}
}

Output

In the above code snippet, I used get as well, to access the value of indexer. Properties and Indexers work on same set of rules. There is a bit difference on how we use them. When we do indexer[1] that means “get” accessor is called, and when we assign some value to indexer[1] that means “set” accessor is called. While implementing indexer code we have to take care that when we access indexer it is accessed in the form of a variable and that too an array parameter.

Data-Types in Indexers

Lab 1

Indexer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Indexers
{
public class Indexer
{
public int Index;
public int this[string indexValue]
{
set
{
Console.WriteLine(I am in set : Value is “ + value + and indexValue is “ + indexValue);
Index = value;
}
get
{
Console.WriteLine(I am in get and indexValue is “ + indexValue);
return Index;
}
}
}
}

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
Indexer indexer=new Indexer();
indexer[name”]=20;
Console.WriteLine(indexer[name”]);
Console.ReadKey();
}
}
}

Output

The “this” property i.e. indexers have return value. In our example the return value was integer. The square brackets along with “this” can also hold other data types and not only integer in the above mentioned example I tried to explain this using string parameter type for “this” : public int this[string indexValue],
The string parameter “indexValue” has a value “name”, like we passed in Main method of Program.cs. So one can have more than one indexers in a class deciding what should be the data type of the parameter value of array. An indexer, like properties follow same rules of inheritance and polymorphism.

Indexers in interfaces

Like Properties and Methods, Indexers can also be declared in Interfaces.
For practical implementation, just create an interface named IIndexers having following code,
namespace Indexers
{
    interface IIndexers
    {
        string this[int indexerValue] { get; set; }
    }
}
Here, an indexer is declared with an empty get and set accessor, that returns string values.
Now we need a class that implements this interface. You can define a class of your choice and implement that through IIndexers interface,

Indexer.cs

using System;

namespace Indexers
{
public class IndexerClass:IIndexers
{
readonly string[] _nameList = { AKhil”,Bob”,Shawn”,Sandra” };

public string this[int indexerValue]
{
get
{
return _nameList[indexerValue];
}
set
{
_nameList[indexerValue] = value;
}
}
}
}

The class has a default array of strings that hold names. Now we can implement interface defined indexer in this class to write our custom logic to fetch names on the base of indexerValue. Let’s call this in our main method,

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
IIndexers iIndexer=new IndexerClass();
Console.WriteLine(iIndexer[0]);
Console.WriteLine(iIndexer[1]);
Console.WriteLine(iIndexer[2]);
Console.WriteLine(iIndexer[3]);
Console.ReadLine();

}
}
}

Run the application. Output,
In main method, we took Interface reference to create an object of IndexerClass, and we accessed that object array through indexer values like an array. It gives the names one by one.
Now if I want to access “set” accessor as well, I can easily do that. To check this, just add two more lines where you set the value in indexer,
            iIndexer[2] = "Akhil Mittal";
            Console.WriteLine(iIndexer[2]);
I set the value of 2nd element as a new name, let’s see the output,

Indexers in Abstract class

Like we used indexers in Interfaces, we can also use indexers in abstract class. I’ll use the same logic of source code that we used in interfaces, so that you can relate how it works in abstract class as well. Just define a new class that should be abstract and should contain an abstract indexer with empty get and set,

AbstractBaseClass

namespace Indexers
{
    public abstract class AbstractBaseClass
    {
        public abstract string this[int indexerValue] { get; set; }
    }
}
Define derived class, inheriting from abstract class,

IndexerClass

We here use override in indexer to override the abstract indexer declared in abstract class.
using System;

namespace Indexers
{
public class IndexerClass:AbstractBaseClass
{
readonly string[] _nameList = { AKhil”,Bob”,Shawn”,Sandra” };

public override string this[int indexerValue]
{
get
{
return _nameList[indexerValue];
}
set
{
_nameList[indexerValue] = value;
}
}
}
}

Program.cs

We’ll use reference of abstract class to create an object of Indexer class.
using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
AbstractBaseClass absIndexer=new IndexerClass();
Console.WriteLine(absIndexer[0]);
Console.WriteLine(absIndexer[1]);
Console.WriteLine(absIndexer[2]);
Console.WriteLine(absIndexer[3]);
absIndexer[2] = Akhil Mittal”;
Console.WriteLine(absIndexer[2]);

Console.ReadLine();

}
}
}

Output:
All of the above code is self-explanatory. You can explore more scenarios by yourself for more detailed understanding.

Indexer Overloading

Indexer.cs

using System;

namespace Indexers
{
public class Indexer
{
public int this[int indexerValue]
{
set
{
Console.WriteLine(Integer value “ + indexerValue + + value);
}
}

public int this[string indexerValue]
{
set
{
Console.WriteLine(String value “ + indexerValue + + value);
}
}

public int this[string indexerValue, int indexerintValue]
{
set
{
Console.WriteLine(String and integer value “ + indexerValue + + indexerintValue + + value);
}
}
}
}

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
Indexer indexer=new Indexer();
indexer[1] = 30;
indexer[name”]=20;
indexer[address”,2] = 40;
Console.ReadLine();
}
}
}

Output

In above example, we see that an indexer’s signature in actually count of actual parameters and data types irresepective of the names of the arguments/parameters or return value of the indexers. This allows us to overload indexers like we do in method overloading. You can read more about method over loading inhttp://www.codeproject.com/Articles/771455/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Ear. Here now we have overloaded indexers that takes integer, string integer and string combined as actual parameters. Like methods cannot be overloaded on the base of return types, so indexers follow the same methodology of overload like methods do.

Point to remember

Like indexers, we cannot overload properties. Properties are more like knowing by name and indexers on the other hand is more like knowing by signature.

Static Indexers?

In the example that we discussed in last section, just add a static keyword to the indexer signature,
      public static int this[int indexerValue]
        {
            set
            {
                Console.WriteLine("Integer value " + indexerValue + " " + value);
            }
        }
Compile the program; we get a compile time error,
Error The modifier ‘static’ is not valid for this item
The error clearly indicates that an indexer cannot be marked static. An indexer can only be a class instance member but not static, on the other hane a property can be static too.

Point to remember

Properties can be static but indexers cannot be.

Inheritance/Polymorphism in Indexers

Indexer.cs

using System;

namespace Indexers
{
public class IndexerBaseClass
{
public virtual int this[int indexerValue]
{
get
{
Console.WriteLine(Get of IndexerBaseClass; indexer value: “ + indexerValue);
return 100;
}
set
{
Console.WriteLine(Set of IndexerBaseClass; indexer value: “ + indexerValue + set value “ + value);
}

}
}
public class IndexerDerivedClass:IndexerBaseClass
{
public override int this[int indexerValue]
{
get
{
int dValue = base[indexerValue];
Console.WriteLine(Get of IndexerDerivedClass; indexer value: “ + indexerValue + dValue from base class indexer: “ + dValue);
return 500;
}
set
{
Console.WriteLine(Set of IndexerDerivedClass; indexer value: “ + indexerValue + set value “ + value);
base[indexerValue] = value;
}

}
}
}

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
IndexerDerivedClass indexDerived=new IndexerDerivedClass();
indexDerived[2] = 300;
Console.WriteLine(indexDerived[2]);
Console.ReadLine();

}
}
}

Output

The example code taken above explains run time polymorphism and inheritance in indexers. I created a base class named IndexerBaseClass having an indexer with its own get and set like we discussed in prior examples. There after a derived class is created named IndexerDerivedClass, this derives from IndexerBaseClass and overrides “this” indexer from base class, note that base class indexer is marked virtual, so we can override it in derived class by marking it “override” in derived class.The example makes call to indexer of base class. Sometimes when we need to override code in derived class in the derived class, we may require the base class indexer should be called first. This is just a situation. The same rule of run time polymorphism applies here , we declare base class indexer and virtual and derived class one as override. In “set” accessor of derived class, we can call base class indexer as base[indexerValue]. Also this value is used to initialize the derived class indexer as well. So the value is stored in “value” keyword too. So, indexDerived[2] in Main() method of Program.cs gets replaced to base[2] in “set” accessor. Whereas In “get” accessor it is vice versa, we require to putbase[indexerValue] to right hand side of equal sign. The “get” accessor in base class returns a value, i.e. 100, which we get in dValue variable.

.NET Framework and Indexers

Indexers play a crucial role in .NET framework. Indexers are widely used in .NET Framework inbuilt classes, libraries such as collections and enumerable. Indexers are used in collections that are searchable like Dictionary, Hashtable, List, Arraylist etc.

Point to remember

Dictionary in C# largely uses indexers to have a staring parameter as an indexer argument.
Classes like ArrayList and List use indexers internally to provide functionality of arrays for fetching and using the elements.

Properties vs Indexers

I have already explained a lot about properties and indexers, to summarize, let me point to an MSDN link for better understanding,
Property Indexer
Allows methods to be called as if they were public data members. Allows elements of an internal collection of an object to be accessed by using array notation on the object itself.
Accessed through a simple name. Accessed through an index.
Can be a static or an instance member. Must be an instance member.
get accessor of a property has no parameters. A get accessor of an indexer has the same formal parameter list as the indexer.
set accessor of a property contains the implicit value parameter. A set accessor of an indexer has the same formal parameter list as the indexer, and also to the value parameter.
Supports shortened syntax with Auto-Implemented Properties (C# Programming Guide). Does not support shortened syntax.

Conclusion

With this article we completed almost all the scenarios related to an indexer. We did a lot of hands-on lab to clear our concepts. I hope my readers now know by heart about these basic concepts and will never forget them. These may also help you in cracking C# interviews.
Keep coding and enjoy reading
Also do not forget to rate/comment/like my article if it helped you by any means, this helps me to get motivated and encourages me to write more and more.

Read more:

Other Series

My other series of articles:

For more informative articles visit my Blog.

For more technical articles you can reach out to CodeTeddy.

Diving into OOP (Day 7): Properties in C# (A Practical Approach)


Introduction:

My article of the series “Diving into OOP” will explain all about properties, its uses and indexers in C#. We’ll follow the same way of learning i.e. less theory and more practical. I’ll try to explain the concept in-depth.

Properties (The definition):

Let’s start with the definition taken from MSDN
A property is a member that provides a flexible mechanism to read, write, or compute the value of a private field. Properties can be used as if they are public data members, but they are actually special methods called accessors. This enables data to be accessed easily and still helps promote the safety and flexibility of methods.
 

Roadmap:

Let’s recall our road map,
  1. Diving in OOP (Day 1): Polymorphism and Inheritance(Early Binding/Compile Time Polymorphism)
  2. Diving in OOP (Day 2): Polymorphism and Inheritance (Inheritance)
  3. Diving in OOP (Day 3): Polymorphism and Inheritance (Dynamic Binding/Run Time Polymorphism)
  4. Diving in OOP (Day 4): Polymorphism and Inheritance (All about Abstarct classes in C#)
  5. Diving in OOP (Day 5): All about access modifiers in C# (Public/Private/Protected/Internal/Sealed/Constants/Readonly Fields)
  6. Diving in OOP (Day 6): Understanding Enum in C# (A Practical Approach)
  7. Diving into OOP (Day 7): Properties in C# (A Practical Approach)
  8. Diving into OOP (Day 8): Indexers in C# (A Practical Approach)
  9. Diving into OOP (Day 9): Understanding Events in C# (An Insight)

Properties (The explanation):

Being a C# programmer, I must say that properties are something a C# programmer is blessed to use in his code. If we analyze properties internals, they are very different from normal variables; properties are internally methods that do not have their own memory like variables have. We can leverage property to write our custom code whenever we access a property. We can access the code when we call/execute properties or at the time of declaration too, but this is not possible with variables. A property in easy language is a class member and is encapsulated and abstracted from the end developer who is accessing the property. A property can contain lots of code that an end user does not know. An end user only cares to use that property like a variable.
Let’s start with some coding now.
Note: Each and every code snippet in this article is tried and tested.

Lab1

Create a simple console application and name it “Properties”. Add a class named “Properties” to it. You can choose the names of project and class as per your wish. Now try to create a property in that class like shown below,

Properties.cs

namespace Properties
{
    public class Properties
    {
        public string Name{}
    }
}
Try to run/build the application, what do we get?

Output

Error ‘Properties.Properties.Name’: property or indexer must have at least one accessor
In above example, we created a property named Name of type string. The error we got is very self-explanatory; it says a property must have an accessor, i.e. a get or a set. This means we need something in our property that gets accessed, whether to set the property value or get the property value, unlike variables, properties cannot be declared without an accessor.

Lab2

Let’s assign a get accessor to our property and try to access that property in Main method of program.cs file.

Properties.cs

Properties.cs:

namespace Properties
{
public class Properties
{
public string Name
{
get
{
return I am a Name property”;
}
}
}
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
Console.WriteLine(properties.Name);
Console.ReadLine();
}
}
}

Try to run/build the application, what do we get?

Output

It says “I am a Name property”. This signifies that our get successor got called when I tried to access the property or tried to fetch the value of a Property.

Get accessor

Now declare one more property in Properties.cs class, and name it Age that returns an integer. It calculates the age of a person by calculating the difference between his date of birth and current date,

Properties.cs

using System;

namespace Properties
{
public class Properties
{
public string Name
{
get
{
return I am a Name property”;
}
}

public int Age
{
get
{
DateTime dateOfBirth=new DateTime(1984,01,20);
DateTime currentDate = DateTime.Now;
int age = currentDate.Year – dateOfBirth.Year;
return age;
}
}
}
}

Call the “Age” property in the same way as done for Name.

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
Console.WriteLine(properties.Name);
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Try to run/build the application, what do we get?

Output

It returns the correct age subjective to date of birth provided. Did you notince something here? Our property contains some code and logic to calculate age, but the caller i.e. Program.cs is not aware of the logic it only cares about using that Property. Therefore, we see that a property encapsulates and abstracts its functionality from the end user, in our case it’s a developer.

Point to remember

Get accessor is only used to read a property value. A property having only “get” cannot be set with any value from the caller.
This means a caller/end user can only access that property in read mode.

Set accessor

Let’s start with a simple example.

Lab1

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        public string Name
        {
            get { return "I am a Name property"; }
        }

public int Age
{
get
{
DateTime dateOfBirth = new DateTime(1984, 01, 20);
DateTime currentDate = DateTime.Now;
int age = currentDate.Year – dateOfBirth.Year;
Console.WriteLine(Get Age called”);
return age;
}
set
{
Console.WriteLine(Set Age called “ + value);
}
}
}
}

Call the “Age” property in the same way as done for Name.

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Run the application,

Output

In the above given example, I made few minor changes in get accessor, i.e. just printing that control is in “Get accessor” and introduced a “Set” in Age property too. Everything else remains same. Now when I call Name property, it works as was working earlier.Since we used “Set” so now we are allowed to set the value of a property. When I do properties.Age = 40; that means I am setting value 40 to that property. We can say a property can also be used to assign some value.In this case Set accessor is called, as soon as we set a value to property. Later on when we access that same property, again our get accessor gets called which returns value with some custom logic. We have a drawback here, as we see, whenever we call get we get the same vale and not the value that we assigned to that property i.e. because get has its custom fixed logic. Let’s try to overcome this situation.

Lab2

The example I am about to explain makes use of a private variable. But you can also use Automatic Properties to achieve same. I’ll purposely make use of variable to have a better understanding.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;
        private int age;

public string Name
{
get { return name; }
set
{
Console.WriteLine(Set Name called “);
name = value;
}
}

public int Age
{
get { return age; }
set
{
Console.WriteLine(Set Age called “);
age = value;
}
}
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
properties.Name = Akhil”;
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Run the application,

Output

Now you see, we get the same value that we assigned to Name and Age property .When we access these properties get accessor is called and it returns the same vale as we set them for. Here properties internally make use of local variable to hold and sustain the value.
In day to day programming, we normally create a Public property that can be accessed outside the class. However the variable it is using internally could be a private.

Point to remember

The variable used for property should be of same data type as the data type of the property.
In our case we used variables, name and age, they share same datatype as their respective properties do. We don’t use variables as there might be scenarios in which we do not have control over those variables, end user can change them at any point of code without maintaining the change stack. Moreover one major use of properties is user can associate some logic or action when some change on the variable occurs, therefore when we use properties, we can easily track the value changes in variable.
When using Automatic Properties, they do this internally, i.e. we don’t have to define an extra variable to do so,like shown below,

Lab3

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;
        private int age;

public string Name { get; set; }

public int Age { get; set; }
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
properties.Name = Akhil”;
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Run the application,

Output

Here
    public string Name { get; set; }
    public int Age { get; set; }
are automatic properties.
I hope now you know how to define a property and use it.

Readonly

A property can be made read-only by only providing the get accessor. We do not provide a set accessor, if we do not want our property to be initialized or to be set from outside the scope of class.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name="Akhil";
        private int age=32;

public string Name
{
get { return name; }
}

public int Age { get { return age; } }
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
properties.Name = Akhil”;
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Build the application, we get following output
Error Property or indexer ‘Properties.Properties.Age‘ cannot be assigned to — it is read only
Error Property or indexer ‘Properties.Properties.Name‘ cannot be assigned to — it is read only
In main method of Program class, we tried to set the value of Age and Name property by,
            properties.Name = "Akhil";
            properties.Age = 40;
But since they were marked read-only i.e. only with get accessor, we encountered a compile time error.

Write-Only

A property can also be made write-only i.e. vice versa to read-only. In this case you’ll be only allowed to set the value of the property but can’t access it because we don’t have get accessor in it.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;
        private int age;

public string Name
{
set { name=value; }
}

public int Age { set { age = value; } }
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
properties.Name = Akhil”;
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Build the application, we get following output
Error The property or indexer ‘Properties.Properties.Age’ cannot be used in this context because it lacks the get accessor
Error The property or indexer ‘Properties.Properties.Name’ cannot be used in this context because it lacks the get accessor
In the above mentioned example, our property is marked only with set accessor, but we tried to access those properties in our main program with,
            Console.WriteLine(properties.Name);
            Console.WriteLine("My age is " + properties.Age);
That means we tried to call get accessor of property which is not defined, so we again ended up in a compile time error.

Insight of Properties in C#

Lab1

Can we define properties as two different set of pieces? The answer is NO.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;

public string Name
{
set { name=value; }
}

public string Name
{
get { return name; }
}
}
}

Build the project, we get compile time error,
Error The type ‘Properties.Properties’ already contains a definition for ‘Name’
Here I tried to create a single property segregated in two different accessor. Compile treats a property name as a single separate property, so we cannot define a property with two names having different accessor.

Lab2

Can we define properties same as an already defined variable? The answer is NO.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;

public string name
{
set { name=value; }
get { return name; }
}
}
}

Build the project; we get compile time error,
Error The type ‘Properties.Properties’ already contains a definition for ‘name’
Again, we cannot have a variable and a property with the same name. They may differ on the grounds of case sensitivity, but they cannot share a same common name with the same case because at the time of accessing them, compiler may get confused that whether you are trying to access a property or a variable.

Properties vs Variables

It is a conception that variables are faster in execution that properties. I do not deny about this but this may not be true ion every case or can vary case to case. A property, like I explained internally executes a function/method whereas a variable uses/initializes memory when used. At times properties are not slower than variables as the property code is internally rewritten to memory access.
To summarize, MSDN explains this theory better than me,
Point of difference Variable Property
Declaration Single declaration statement Series of statements in a code block
Implementation Single storage location Executable code (property procedures)
Storage Directly associated with variable’s value Typically has internal storage not available outside the property’s containing class or moduleProperty’s value might or might not exist as a stored element 1
Executable code None Must have at least one procedure
Read and write access Read/write or read-only Read/write, read-only, or write-only
Custom actions (in addition to accepting or returning value) Not possible Can be performed as part of setting or retrieving property value

Static Properties

Like variables and methods, a property can also be marked static,

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        public static int Age
        {
            set
            {
                Console.WriteLine("In set static property; value is " + value);
            }
            get
            {
                Console.WriteLine("In get static property");
                return 10;
            }
        }
    }
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties.Age = 40;
Console.WriteLine(Properties.Age);
Console.ReadLine();
}
}
}

Output

In above example, I created a static Age property. When I tried to access it, you can see it is accessed via class name, like all static members are subjected to. So properties also inherit the static functionality like all c# members, no matter it is variable or a method. They’ll be accessed via class name only.

Properties return type

Lab1

Properties.cs

using System;

namespace Properties
{
public class Properties
{
public void AbsProperty
{
get
{
Console.WriteLine(Get called”);
}
}
}
}

Compile the program.
Output is a compile time error,
Error ‘AbsProperty’: property or indexer cannot have void type

Point to remember

A property cannot have a void return type.

Lab2

Just try to return a value from “set” accessor,

Properties.cs

using System;

namespace Properties
{
public class Properties
{
public int Age
{
set { return 5; }
}
}
}

Compile the program,
Error Since ‘Properties.Properties.Age.set’ returns void, a return keyword must not be followed by an object expression
Here compiler understands “set” accessor as a method that returns void and takes a parameter to initialize the value. So set cannot be expected to return a value.
If we just leave return statement empty, and remove 5, we do not get any error and code compiles,
using System;

namespace Properties
{
public class Properties
{
public int Age
{
set { return ; }
}
}
}

Value Keyword

We have a reserved keyword named value.
using System;

namespace Properties
{
public class Properties
{
public string Name
{
set { string value; }
}
}
}

Just compile the above given code, we get a compile time error as follows,
Error A local variable named ‘value’ cannot be declared in this scope because it would give a different meaning to ‘value’, which is already used in a ‘parent or current’ scope to denote something else
This signifies that “value” is a reserved keyword here. So one cannot declare a variable named value in “set” accessor as it may give different meaning to already reserved keyword value.

Abstract Properties

Lab1

Yes, we can also have abstract properties; let’s see how it works,

Properties.cs

using System;

namespace Properties
{
public abstract class BaseClass
{
public abstract int AbsProperty { get; set; }
}

public class Properties : BaseClass
{
public override int AbsProperty
{
get
{
Console.WriteLine(Get called”);
return 10;
}
set { Console.WriteLine(set called,value is “ + value); }
}
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties prop=new Properties();
prop.AbsProperty = 40;
Console.WriteLine(prop.AbsProperty);
Console.ReadLine();
}
}
}

Output

In above example, I just created a base class named “BaseClass” and defined an abstract property namedAbsproperty. Since the property is abstract it follows the rules of being abstract as well. I inherited my “Properties” class from BaseClass and given the body to that abstract property. Since the property was abstract I have to override it in my derived class to add functionality to it. So I used override keyword in my derived class.
In base class, abstract property has no body at all, neither for “get” and nor for “set”, so we have to implement both the accessor in our derived class, like shown in “Properties” class.

Point to remember

If one do not mark property defined in derived class as override, it will by default be considered as new.

Lab2

Properties.cs

using System;

namespace Properties
{
public abstract class BaseClass
{
public abstract int AbsProperty { get; }
}

public class Properties : BaseClass
{
public override int AbsProperty
{
get
{
Console.WriteLine(Get called”);
return 10;
}
set { Console.WriteLine(set called,value is “ + value); }
}
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties prop=new Properties();
prop.AbsProperty = 40;
Console.WriteLine(prop.AbsProperty);
Console.ReadLine();
}
}
}

Output

Compile time error,
Error ‘Properties.Properties.AbsProperty.set’: cannot override because ‘Properties.BaseClass.AbsProperty’ does not have an overridable set accessor
In above lab example, I just removed “set” from AbsProperty in Base class. All the code remains same. Now here we are trying to override the set accessor too in derived class, that is missing in base class, therefore compiler will not allow you to override a successor that is not declared in base class, hence resulted into a compile time error.

Point to remember

You cannot override an accessor that is not defined in a base class abstract property.

Properties in Inheritance

Just follow the given code,

Properties.cs

using System;

namespace Properties
{
public class PropertiesBaseClass
{
public int Age
{
set {}
}
}

public class PropertiesDerivedClass:PropertiesBaseClass
{
public int Age
{
get { return 32; }
}
}
}

Program.cs

namespace Properties
{
    class Program
    {
        static void Main(string[] args)
        {
            PropertiesBaseClass pBaseClass=new PropertiesBaseClass();
            pBaseClass.Age = 10;
            PropertiesDerivedClass pDerivedClass=new PropertiesDerivedClass();
            ((PropertiesBaseClass) pDerivedClass).Age = 15;
            pDerivedClass.Age = 10;
        }
    }
}
As you can see in above given code, in Properties.cs file I created two classes one is Base i.e.PropertiesBaseClass and second in Derived i.e. PropertiesDerivedClass. I purposely declared set accessor in Base class and get in Derived class for the same property name i.e. Age. Now this case may give you the feeling that when compiled, our code of property Age will become one, i.e. it will take set from Base class and get from derived class and combine it into a single entity of Age property.But this is practically not the case. The compiler treats both these properties differently, and does not consider them to be same. In this case the property in derived class actually hides the property in base class , they are not the same but independent properties.The same concept of method hiding applies here too. You can read about hiding inhttp://www.codeproject.com/Articles/774578/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Dyn.
To use the property of base class from a derived class object, you need to cast it to base class and then use it.
When you compile the above code, you get a compile time error as follows,
Error Property or indexer ‘Properties.PropertiesDerivedClass.Age’ cannot be assigned to — it is read only
i.e. we can do ((PropertiesBaseClass) pDerivedClass).Age = 15;
but we cannot do pDerivedClass.Age = 10; because derived class property has no “set” accessor.

Summary

Let’s recall all the points that we have to remember,
  • The variable used for property should be of same data type as the data type of the property.
  • A property cannot have a void return type.
  • If one do not mark property defined in derived class as override, it will by default be considered as new.
  • You cannot override an accessor that is not defined in a base class abstract property.
  • Get accessor is only used to read a property value. A property having only get cannot be set with any value from the caller.

Conclusion

In this article we learnt a lot about properties in c#. I hope you now understand properties well. In my next article I’ll explain all about indexers in C#.
Keep coding and enjoy reading
Also do not forget to rate/comment/like my article if it helped you by any means, this helps me to get motivated and encourages me to write more and more.

Read more:

Other Series

My other series of articles:

For more informative articles visit my Blog.

For more technical articles you can reach out to CodeTeddy.

Diving in OOP (Day 6): Understanding Enums in C# (A Practical Approach)


Introduction

My article of the series “Diving in OOP” will explain enum datatype in C#. We’ll learn by doing hands on lab and not only by theory. We’ll explore the power of enum and will cover almost every scenario in which we can use enum. We’ll follow a practical approach of learning to understand this concept. We may come across complex examples to understand the concept more deeply.

Enums (The Definition)

Let’s start with the definition taken from MSDN:

“The enum keyword is used to declare an enumeration, a distinct type that consists of a set of named constants called the enumerator list.
Usually it is best to define an enum directly within a namespace so that all classes in the namespace can access it with equal convenience. However, an enum can also be nested within a class or struct.
By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1. For example, in the following enumeration, Sat is 0, Sun is 1, Mon is 2, and so forth.”

Pre-requisites

I expect that my readers of this article should have very basic knowledge of C# and I always wish that my readers should enjoy while reading this article. Also, keep writing programs by yourself that are given as examples in this article, to get hands on and understand the concept more deeply.

Roadmap

Let’s recall our road map.

A Practical Approach

Enum plays almost the same responsibility as the class does, i.e., creating a new data type, and it exists at the same level as class, interfaces or structs.
Just open your Visual Studio and add a console application named Enums. You’ll get Program.cs class.
Note: Each and every code snippet in this article is tried and tested.
Declare an enum at the same level as of Program class, call it as Color.

Program.cs

namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
        }
    }

enum Color
{
Yellow,
Blue,
Brown,
Green
}
}

In the above mentioned example, we created a new datatype with the help of enum. The datatype is Colorhaving four distinct values, Yellow,BlueBrown and Green. The text that we write inside the declared enum could be anything of your wish; it just provides a custom enumerated list to you.
Modify your main program as shown below:
using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
            Console.WriteLine(Color.Yellow);
            Console.ReadLine();
        }
    }

enum Color
{
Yellow,
Blue,
Brown,
Green
}
}

Run the program.
 
OutputYellow
 
Now just typecast Color.Yellow to int, what do we get?
using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
            Console.WriteLine((int)Color.Yellow);
            Console.ReadLine();
        }
    }

enum Color
{
Yellow,
Blue,
Brown,
Green
}
}

 
Output0
 
We see that enum is called as static variables, so an enum can be considered here as static objects. Thereforeother enums in the above example can be declared in the same way as Yellow, like Blue can be declared asColor.Blue. The output in the above two examples we see is when we typecast and Yellow without typecasting, hence we see here that its behaviour is very similar to an array where Yellow has a value 0, similarly Blue has a value 1Brown2Green3.
Therefore, when we do Color.Yellow, it’s like displaying a number 0, so from this can we infer that an enumrepresents a constant number, therefore an enum type is a distinct type having named constants.
Point to remember: An enum represents for a constant number, and an enum type is known as a distinct type having named constants.

Underlying Data type

Program.cs

using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
            Console.WriteLine((byte)Color.Yellow);
            Console.WriteLine((byte)Color.Blue);
            Console.ReadLine();
        }
    }

enum Color:byte
{
Yellow,
Blue,
Brown,
Green
}
}

Output

0
1
 
Note: Each and every code snippet in this article is tried and tested.
The only change we did here is that we specified the type to the underlying enum that we declared. The defaultdatatype for the enum is int, here we have specified the data type as byte and we get the result.
There are more data types that can be specified
for enum like longulongshortushortintuint,byte andsbyte.
Point to remember: We can’t declare char as an underlying data type for enum objects because char stores Unicode characters, but enum objects data type can only be number.

Inheritance in Enum

Program.cs

using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
            Console.WriteLine((byte)Color.Yellow);
            Console.WriteLine((byte)Color.Blue);
            Console.ReadLine();
        }
    }

enum Color:byte
{
Yellow,
Blue,
Brown,
Green

}

enum Shades:Color
{

}
}

Output

Compile time error: Type bytesbyteshortushortintuintlong, or ulong expected.
We clearly see here enums can’t be derived from any other type except that of mentioned in the error.
Point to rememberenum can’t be derived from any other type except that of type bytesbyteshortushort,intuintlong, or ulong.
Let’s derive a class from enum, call it class Derived, so our code.

Program.cs

class Program
    {
static void Main(string[] args)
        {
            Console.WriteLine((byte)Color.Yellow);
            Console.WriteLine((byte)Color.Blue);
            Console.ReadLine();
        }
    }

Enum

enum Color:byte
    {
        Yellow,
        Blue,
        Brown,
        Green
    }

Derived.cs

class Derived:Color
    {

}

Compile the code.

Output

Compile time error: ‘Enums.Derived’: cannot derive from sealed type ‘Enums.Color’
Point to remember: By default, enum is a sealed class and therefore sticks to all the rules that a sealed class follows, so no class can derive from enum, i.e., a sealed type.
Can System.Enum be a base class toenum?

Program.cs

using System;

namespace Enums
{
internal enum Color: System.Enum
{
Yellow,
Blue
}

internal class Program
{
private static void Main(string[] args)
{
}
}
}

Output

Compile time error: Type bytesbyteshortushortintuintlong, or ulong expected.
Point to remember: The enum type is implicitly derived from System.Enum and so we cannot explicitly derive it from System.Enum.
To add more,enum is also derived from three interfaces IComparableIFormattable and IConvertible.

A. IComparable

Let’s check,

Program.cs

using System;

namespace Enums
{
internal enum Color
{
Yellow,
Blue,
Green
}

internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine(Color.Yellow.CompareTo(Color.Blue));
Console.WriteLine(Color.Blue.CompareTo(Color.Green));
Console.WriteLine(Color.Blue.CompareTo(Color.Yellow));
Console.WriteLine(Color.Green.CompareTo(Color.Green));
Console.ReadLine();
}
}
}

Output

-1
-1
 1
 0
Sometimes, we may get into situations where we have large number of enums defined and we want to compare the values of enum to each other to check if they are smaller, larger or equal value to one another.
Since all enums implicitly derive from Enum class that implements the interface IComparable, they all have a methodCompareTo(), that we just used in the above example. The method being nonstatic has to be used through a member. Yellow has value 0, Blue as 1 and Green as 2. In the first statement, when Color.Yellow compared toColor.Blue, value of Yellow is smaller than Blue hence -1 returned, same applied for the second statement when Color.Blue compared to Color.GreenGreen has larger value, i.e., 2 than that of Color.Blue having value 1 only. In the third statement, i.e., vice versa of first statement, we get the result of camparisonas 1,becauseBlue is larger than Yellow. In the last statement where Color.Green compares to itself, we undoubtedly get the value 0.
So value -1 means the value is smaller, 1 means value is larger and 0 means equal values for both the enummembers.
Another comparison example is shown below:

Program.cs

using System;

namespace Enums
{
enum Color
{
Yellow,
Blue,
Green
}

internal class Program
{
private static void Main(string[] args)
{
int myColor = 2;
if(myColor== Color.Green)
{
Console.WriteLine(my color”);
}
Console.ReadLine();
}
}
}

Output

Compile time error : Operator '==' cannot be applied to operands of type 'int' and 'Enums.Color'
In the above example, we tried to compare an int type to Enum type and resulted in a compile time error. Sinceenum acts as an individual data type so it cannot be directly compared to an int, however, we can typecast the enumtype to int to perform comparison, like in the below example:

Program.cs

using System;

namespace Enums
{
enum Color
{
Yellow,
Blue,
Green
}

internal class Program
{
private static void Main(string[] args)
{
int myColor = 2;
if(myColor== (int)Color.Green)
{
Console.WriteLine(my color”);
}
Console.ReadLine();
}
}
}

 
Output: my color

B. IFormattable

Program.cs

using System;

namespace Enums
{
internal enum Color
{
Yellow,
Blue,
Green
}

internal class Program
{
private static void Main(string[] args)
{
System.Console.WriteLine(Color.Format(typeof(Color), Color.Green, X”));
System.Console.WriteLine(Color.Format(typeof(Color), Color.Green, d”));
Console.ReadLine();
}
}
}

Output

00000002
2
Format is the method derived from IFormatter interface. It’s a static method so can be used directly with theenum class defined as Color. It’sfirst parameter is the type of the enum class, second is the member that has to be formatted and third is the format, i.e., hexadecimal or decimal, like we used in the above example, and we got a positive result output too.

C. IConvertible

using System;

namespace Enums
{
enum Color
{
Yellow,
Blue,
Green
}

internal class Program
{
private static void Main(string[] args)
{
string[] names;
names = Color.GetNames(typeof (Color));
foreach (var name in names)
{
Console.WriteLine(name);
}
Console.ReadLine();
}
}
}

Output

Yellow
Blue
Green
 
Note: Each and every code snippet in this article is tried and tested.
GetNames is a static method that accepts Type, i.e., instance of type as a parameter and in return gives an array of strings. Like in the above example, we had array of 3 members in our enum, therefore their names are displayed one by one.
Another example is as follows:

Program.cs

using System;

namespace Enums
{
enum Color
{
Yellow,
Blue,
Green
}

internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine(Color.Blue.ToString());
Console.WriteLine(Color.Green.ToString());
Console.ReadLine();
}
}
}

Output

Blue
Green
As we see in the above example, we converted an enum type to staring type and got an output too, so, numerous predefined conversion methods can be used to convert enum from one data type to another.
 
Point to remember: Numerous predefined conversion methods can be used to convert enum from one data type to another.
Duplicity, default values and initialization:

Program.cs

using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
            Console.WriteLine((byte)Color.Yellow);
            Console.WriteLine((byte)Color.Blue);
            Console.ReadLine();
        }
    }

enum Color
{
Yellow,
Blue,
Brown,
Green,
Blue
}
}

Output

Compile time error: The type 'Enums.Color' already contains a definition for 'Blue'
In the above example, we just repeated the enum member Blue of Color, and we got a compile time error, hence we now know that an enum cannot contain two members having the same name. By default, if the first value is not specified, the first member takes the value and increments it by one to succeeding members.
Let’s take one more example.

Program.cs

using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
            Console.WriteLine((int)Color.Yellow);
            Console.WriteLine((int)Color.Blue);
            Console.WriteLine((int)Color.Brown);
            Console.WriteLine((int)Color.Green);

Console.ReadLine();
}
}

enum Color
{
Yellow =2,
Blue,
Brown=9,
Green,

}
}

Output

2
3
9
10
Surprised! We can always specify the default constant value to any enum member, here we see, we specified value 2to yellow, so as per law of enum, the value of blue will be incremented by one and gets the value 3. We again specified as a default value toBrown, and so its successor Green gets incremented by one and gets that value 10.
Moving on to another example.

Program.cs

using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {

}
}

enum Color:byte
{
Yellow =300 ,
Blue,
Brown=9,
Green,
}
}

Output

Compile time error: Constant value '300' cannot be converted to a 'byte'
We just derived ourenum from byte, we know we can do that? We then changed the value of yellow from 2 to300, and we resulted in a compile time error. Since here our underlying data type was byte, so it is as simple as that, that we cannot specify the value to enum members which exceeds the range of underlying data types. The value 300is beyond the range of byte. It is similar to assigning the beyond range value to a byte data type variable.
Another example:

Program.cs

using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
            Console.WriteLine((int)Color.Yellow);
            Console.WriteLine((int)Color.Blue);
            Console.WriteLine((int)Color.Brown);
            Console.WriteLine((int)Color.Green);

Console.ReadLine();
}
}

enum Color
{
Yellow = 2,
Blue,
Brown = 9,
Green = Yellow
}
}

Output

2
3
9
2
Here we initialized Green to Yellow, and we did not get any error, so we see, more than one enum members can be initialized a same constant value.
Point to remember: More than one enum members can be initialized a same constant value.

Program.cs

using System;
namespace Enums
{
class Program
    {
static void Main(string[] args)
        {
            Color.Yellow = 3;
        }
    }

enum Color
{
Yellow = 2,
Blue,
Brown = 9,
Green = Yellow
}
}

Output

Compile time error: The left-hand side of an assignment must be a variable, property or indexer
In the above example, we tried to initialize the enum member out of the scope of defined enum, i.e., in another class, and got a compile time error. We must not forget that an enum acts as a constant, which cannot change its value.
Point to remember: An enum acts as a constant, so its value cannot be changed once initialized.

Readability

Program.cs

using System;

namespace Enums
{
internal enum Color
{
Yellow,
Blue,
Brown,
Green
}

internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine(CheckColor(Color.Yellow));
Console.WriteLine(CheckColor(Color.Brown));
Console.WriteLine(CheckColor(Color.Green));
Console.ReadLine();
}

public static string CheckColor(Color color)
{
switch (color)
{
case Color.Yellow:
return Yellow”;
case Color.Blue:
return Blue”;
case Color.Brown:
return Brown”;
case Color.Green:
return Green”;
default:
return no color”;
}
}
}
}

Output

Yellow
Brown
Green
Here, in the above example, we have declared an enum Color containing various color members.There is a class named program that contains a static method named CheckColor, that has a switch statement checkingcolor on the basis of passed parameter to the method, i.e., Enum Color. In Main method, we try to access thatCheckColor method, passing various parameters. We see that the switch statement in CheckColor method can take any of the datatype passed and in return case statements use name of that type and not the plain intnumber to compare the result. We see that this made our program more readable. So enum plays an important role in making the program more readable and structured, easy to grasp.

Circular Dependency

Program.cs

using System;

namespace Enums
{
internal enum Color
{
Yellow=Blue,
Blue
}

internal class Program
{
private static void Main(string[] args)
{
}
}
}

Output

Compile time error: The evaluation of the constant value for 'Enums.Color.Yellow' involves a circular definition
Like constants, we also cannot have circular dependency in enums. We assigned valueBlue to Yellow, and Blue in turn is incremented by one as a next enum member, this results in a circular dependency of Blue to yellow, and resulted in error, C# is smart enough to catch these kind of tricks.

Diving Deep

Let’s take some complex scenarios:

Lab1

Program.cs

using System;

namespace Enums
{
enum Color
{

}

internal class Program
{
private static void Main(string[] args)
{
Color color = (Color) -1;
Console.ReadLine();
}
}
}

 
Note: Each and every code snippet in this article is tried and tested.

Output

Compile time error: 
To cast a negative value, you must enclose the value in parentheses
'Enums.Color' is a 'type' but is used like a 'variable'
In the above example, we are casting a negative value to enum, but the compiler says that while casting a negative value, we must keep that in parenthesis. It’s not strange, as C# knows that “-” is also a unary operator, that while using above code may create a confusion for compiler that we are using subtraction or typecasting a negative value. So always use parenthesis while typecasting negative values.

Lab2

Program.cs

using System;

namespace Enums
{
enum Color
{
value__
}

internal class Program
{
private static void Main(string[] args)
{

}
}
}

Output

Compile time error: The enumerator name 'value__' is reserved and cannot be used
We clearly see here that we have value__ as reserved member for the enumerator. C# compiler like this keyword has large number of reserved inbuilt keywords.
Image credit: www.vector.rs
It may keep this reserved keyword to keep track of the enum members internally but not sure.

Summary

Let’s recall all the points that we have to remember.
  1. An enum represents for a constant number, and an enum type is known as a distinct type having named constants.
  2. We can’t declare char as an underlying data type for enum objects because char stores Unicode characters, but enum objects data type can only be number.
  3. An enum can’t be derived from any other type except that of type bytesbyteshortushortintuint,long, or ulong.
  4. By default, enum is a sealed class and therefore sticks to all the rules that a sealed class follows, so no class can derive from enum, i.e., a sealed type.
  5. The enum type is implicitly derived from System.Enum and so we cannot explicitly derive it fromSystem.Enum.
  6. enum is also derived from three interfaces IComparableIFormattable and IConvertible.
  7. Numerous predefined conversion methods can be used to convert enum from one data type to another.
  8. More than one enum members can be initialized a same constant value.
  9. An enum acts as a constant, so its value cannot be changed once initialized.
  10. The enumerator name ‘value__‘ is reserved and cannot be used.

Conclusion

With this article, we completed almost all the scenarios related to enum. We did a lot of hands-on lab to clear our concepts. I hope my readers now know by heart about these basic concepts and will never forget them.
These may also help you in cracking C# interviews.
Keep coding and enjoy reading.
Also, do not forget to rate/comment/like my article if it helped you by any means, this helps me to get motivated and encourages me to write more and more.

Read more:

Other Series

My other series of articles:

For more informative articles visit my Blog.

For more technical articles you can reach out to CodeTeddy.

Read More

For more technical articles, you can reach out to A Practical Approach.