DEV Community

Cover image for Hidden Gems of C#: Exploring lesser known C# Language Features Part I
Volkan Alkılıç
Volkan Alkılıç

Posted on • Updated on

Hidden Gems of C#: Exploring lesser known C# Language Features Part I

C# is a powerful and popular programming language, with a rich set of features that allow developers to build a wide range of applications. However, like any language, C# has a number of lesser-known features that can be useful in certain situations. In this article, we'll explore some of these hidden gems and see how they can be used in practice.

Volatile

The volatile keyword is used to indicate that a field can be modified by multiple threads simultaneously. When a field is marked as volatile, the compiler and runtime will take extra steps to ensure that its value is always up-to-date, even in the presence of concurrent access.

Here's an example of how to use volatile:

public class Counter
{
    private volatile int _count;

    public int Count
    {
        get { return _count; }
        set { _count = value; }
    }
}

Enter fullscreen mode Exit fullscreen mode

extern alias

The extern alias keyword is used to specify an alias for a namespace when using a type from another assembly. This can be useful when you have multiple assemblies that contain types with the same names, and you want to disambiguate them.

Here's an example of how to use extern alias:

extern alias MyLibrary;

using System;
using MyLibrary::MyNamespace;

public class Program
{
    static void Main()
    {
        Console.WriteLine(typeof(MyNamespace.MyType));
    }
}

Enter fullscreen mode Exit fullscreen mode

__arglist

The __arglist keyword is used to specify a variable number of arguments in a method declaration. It allows you to pass a variable number of arguments to a method, without using the params keyword.

Here's an example of how to use __arglist:

public static void PrintNumbers(__arglist)
{
    var args = new ArgIterator(__arglist);
    while (args.GetRemainingCount() > 0)
    {
        Console.WriteLine(__refvalue(args.GetNextArg(), int));
    }
}

Enter fullscreen mode Exit fullscreen mode

__makeref and __reftype

The __makeref and __reftype keywords are used to work with managed object references in an unsafe context. The __makeref keyword creates a reference to an object, while the __reftype keyword returns the type of an object that is being referenced.

Here's an example of how to use __makeref and __reftype:


unsafe void ModifyString(string s)
{
    TypedReference tr = __makeref(s);
    if (__reftype(tr) == typeof(string))
    {
        // Modify the string through the typed reference
    }
}

Enter fullscreen mode Exit fullscreen mode

as and is keywords

The as and is keywords are used to perform type conversions and type checks, respectively. The as operator performs a type conversion, and returns null if the conversion fails. The is operator returns a boolean indicating whether an object is of a specific type.

Here's an example of how to use as and is:

object obj = "hello";
string s = obj as string;
if (s != null)
{
    Console.WriteLine(s.Length); // 5
}

if (obj is string)
{
    Console.WriteLine(((string)obj).Length); // 5
}

Enter fullscreen mode Exit fullscreen mode

Coalesce Nulls

The coalesce nulls operator, represented by the ??= operator, is used to assign a value to a nullable type only if it is currently null. This can be useful when you want to set a default value for a nullable type, without overwriting any existing values.

Here's an example of how to use the coalesce nulls operator:

int? x = null;
x ??= 42; // x is now 42
x ??= 24; // x is still 42

Enter fullscreen mode Exit fullscreen mode

where T: new

The where T: new constraint is used to specify that a type parameter must have a public parameterless constructor. This can be useful when you want to ensure that a type can be instantiated using the default constructor.

Here's an example of how to use the where T: new constraint:

public class MyClass<T> where T: new()
{
    public T CreateInstance()
    {
        return new T();
    }
}

Enter fullscreen mode Exit fullscreen mode

global::

The global:: prefix is used to specify that a type or member refers to the global namespace, rather than a namespace with the same name in the current context. This can be useful when you want to disambiguate types or members that have the same name as a namespace.

Here's an example of how to use global::

namespace MyNamespace
{
    class MyClass
    {
        global::System.Int32 x; // refers to the Int32 type in the global namespace
    }
}

Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, we explored some of the lesser-known features of C#, including volatile, extern alias, __arglist, __makeref and __reftype, as and is, coalesce nulls, where T: new, and global::. While these features may not be used frequently, they can be useful in certain situations and are worth knowing about. Understanding these features can help you write more efficient and effective code in C#, and can also deepen your understanding of the language as a whole.

Join Me

Follow me on Twitter and Linkedin for more content.

Top comments (1)

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

It's a funny thing, volatile. Back 14 or so years ago when I was doing C++ heavily, I learned that volatile in non-Microsoft compilers was simply meant as a hint for the compiler to avoid code optimization around variables that may not seem to have assignments. It was used for variables that were set from DLL's or similar.

The funny thing is: Out of all C++ compilers, Microsoft's compiler was the only one to also add synchronization around the variable, making it thread-safe. No other C++ compiler would do this, only these guys'.

I suppose they carried their decision in C++ all the way into C#.

BTW, it would have been nice to start with unsafe and unchecked before __makeref and __reftype. Now people that don't know these ones will remain scratching their heads about the whole thing, hehe. 😄