Top 7 Least Known but Important C# Features

Atul Sharma

We could be an experienced programmer and have been coding since long in C#. Still, there are few C# language features, which we don’t use frequently and probably know very little about them. I have listed down 7 most underutilized features of C#.

1. Yield Keyword

What is this?

In my list, Yield gets the first position in the list of unsung C# features.
It maintains the state in the loop and returns back to the calling method and resumes with the previous state i.e. Yield provides Stateful Iteration.

If you don’t understand this statement, don’t worry and don’t give up, you will be having a very good understanding of this in the next 2 minutes.

To understand that, let us explore this code and its explanation  –

Code Example –
Use Case –

Here I want to Print the employee names, who are having Salary more than 20,000. I am using the in-memory collection.


   class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
    }

   class Program
    {
       static List<Employee> Employees = new List<Employee>()
            {
                new Employee{ Name="Tom", Salary=12000},
                new Employee{ Name="Harry", Salary=15000},
                new Employee{ Name="Sam", Salary=10000},
                new Employee{ Name="Mike", Salary=25000},
                new Employee{ Name="Bob", Salary=22000},
                new Employee{ Name="Raj", Salary=18000},
            };

        static void Main(string[] args)
        {
                PrintData();
        }
 
        static void PrintData()
        {
            foreach (var emp in FilterWYield())
            {
                Console.WriteLine(emp.Name);
            }
 
            foreach (var emp in FilterSimple())
            {
                Console.WriteLine(emp.Name);
            }
        }
 
 
        static IEnumerable<Employee> FilterWYield()
        {
            foreach (var item in Employees)
            {
                if (item.Salary >= 20000)
                    yield return item;
            }
        }
 
        static IEnumerable<Employee> FilterSimple()
        {
            List<Employee> emps = new List<Employee>();
            foreach (var item in Employees)
            {
                if (item.Salary >= 20000)
                    emps.Add(item);
            }
            return emps;
        }
    }
 

Code Explanation –

Implementation –

For the simple implementation in FilterSimple() method, I have used a temporary collection (emps). When the condition (Salary >=20000) gets true, it adds that item to the this collection (emps) and at the end of execution of foreach loop, it returns that collection to caller methods PrintData() and prints the result.

See also  Title Insurance : Everything You Need to Know

Implementation with Yield is different. We do NOT need additional collection in FilterWYield(). In the foreach loop, it evaluates the condition and when the condition (Salary >=20000) is true, it returns the value to the caller method PrintData() and prints the result. Then again it comes back to FilterWYield() method and resumes the execution (Note here – it doesn’t start, rather remembers the position in collection and resumes from there only). That is why it is called as Stateful Iteration.

This diagram explains the scenario in a better way –

As you can see here, For Tom, Harry and Sam, Loop executes normally and checks from the condition which is false and execute next.

features of C#

For Mike, the condition evaluates to true and then it passes the value to PrintData() where it prints the name of the employee as Mike. Now it comes back to the collection and resumes where it had left i.e. now it will execute the condition for Bob and again it is true and take data to PrintData() method and prints the name Bob. It comes back to the collection and resumes execution of condition for Raj and condition fails and doesn’t go to the PrintData() method and loop ends.

I hope, with this you understand the working on Yield and why it provides Stateful Iteration. For more detail please refer to this MSDN article.

2. String Interning

What is this?

When we assign a value to string variable at run time, it creates a new instance of that. If we already have that value in memory, then also It will create a new instance, instead of using that.

With string interning, we can ask compiler to use the existing memory reference and abandon any other string variable having the same value.

In this article, I have explained everything from basic to the advanced level we need to know about string interning and how to use in your real time project. 

See also  ASP.NET MVC Request Life Cycle

3. Lazy<T>

What is this?

Lazy Instantiation enables object creation when it is used for the first time. It is used from performance and unnecessary computation, when they are not actually needed.

When to use?

This could be useful when large object is needed but they are accesses later.

Use Case –
A have one employee class which has information about his Project, Manager, Performance, Appraisal, Timesheet and other related data. For those values, it needs to call a few services and database as well. On my employee page, I need to show the Manager and Project information but not his Performance and timesheet related data, if the user wishes to open those sections only then we will show those data.

In this case we can enable Lazy instantiation for Timesheet, Performance and Appraisal related information. 

Code Implementation –
Lazy<TimeSheet> objTimeSheet = new Lazy<TimeSheet>();
Lazy<Appraisal> objAppraisal = new Lazy<Appraisal>();
Lazy<Performance> objPerformance  = new Lazy<Performance>();
if (TimeSheetRequested)
{
 ShowTimeSheet(objTimeSheet.Value.CurrentWeek)
}
More Study

Read this MSDN article to get more in depth and understanding of Lazy loading.

4. WeakReference –

What is this?

By default, in C#, all reference types are strong referenced i.e. When they are NOT being referenced in the program, they will be garbage collected. By definition, WeakRefernce allows object to be Garbage collected,

When to use WeakReference?

It is suitable for large memory using classes. If we are not using that part of the application, then we can make this class as WeakReference and later we can reclaim it. It has one risk involved when it has been garbage collected then it will NOT be possible to recreate the object.

Code Example
{
//Instatantiation of VeryLargeObject
      VeryLargeObject objLarge = new VeryLargeObject();
//Creating a weak reference for VeryLargeObject         
      var weakReference = new WeakReference(objLarge);
//Setting VeryLargeObject to null
      objLarge = null;       
//Checking if weak reference is garbage collected      
if(weakReference.IsAlive)
{
    // Reclaiming from weak Reference 
    VeryLargeObject objLargeNew  = weakReference.Target as VeryLargeObject;
}
}
More Study –

This is complete tutorial on MSDN about C# WeakRefernce

5. Immutable –

From C# language, we don’t get it as language feature but we can implement it using const and static. It is an important feature so I have included this to my list.

Immutable classes can be used as a class which doesn’t change its state at any point of existence.  They can be very useful in multithreaded environment which requires less validation. My article on immutable classes in C# has everything you need to know about it.

See also  All we Need to know about Electoral Bonds

 6. Where T: Type

What is this?

This constraint informs C# compiler about the type arguments. Without constrain, it may apply any type or by default System.Object.

When to use?

      When we want certain restriction on the implementation in our generic class or collection. This can be applied to Struct, class, Enum, Interface.

Code example-
class BlogContribution<T> where T : Article, Blog, IArticle, Videos System.IEnumerable<T>, new()
{
    // ...
}
 More Study –

 This MSDN article, has all the details we need to know about these constraints.

7.     Less Popular Operators –

7.1 – Null-Coalescing Operator (??)

It will return the left hand operand if that is not null else will return the right hand operand.

 String name = dbReader.Name?? “Not found”

It also supports chaining

string result = value1 ?? value2 ?? value3 ?? String.Empty;

7.2 – @ Operator –

It let us name the variable same as C# language reserved keywords, as it is shown here.

var @object = new object();
var @string = "";
var @if = isValidEmailId("atul@taagung.com"); 

7.3 – Properties initialization

This works as a short cut to assign default value to any property, as shown below

	private static int _age;
        	public static int Age
        	{
            		get { return _age = 10; }
            		set { value = _age; 
                }

above code segment is equivalent to

public static int age { get; set; } = 10;

7.4 – Namespace Aliasing

using win = System.Windows.Forms;
using web = System.Web.UI.WebControls;
using Validation = PC.Project.BusinessLogic.Validation;
    class A
    {
        void Method()
        {
            // Use the alias
            Validation.DataValidator dataValidator = new Validation.DataValidator();
        }
    }

7.5 – As and Is

Is operator is used to see if run-type of an object is compatible with another type. While as operator is used to convert one type to another.

        class ClassA { }
        class ClassB : ClassA { }
        class ClassC { }

        static void Main(string[] args)
        {
            ClassA objA = new ClassA();
            ClassB objB = new ClassB();
            ClassC objC = new ClassC();

            Console.WriteLine(objA is ClassB); // Output : False
            Console.WriteLine(objB is ClassA); // Output : True
            Console.WriteLine(objC is ClassA); // Output : False

            Console.WriteLine(objA as ClassB); // Output : True
            Console.WriteLine(objB as ClassA); // Output : True
            Console.WriteLine(objC as ClassA); // Output : Exception
       }

With this, I hope you understand the underrated features of C# and use them in your project.