Nifty and useful features in C# 7

in #csharp7 years ago (edited)

The seventh version of the enjoyable programming language C# is not a big release, but it comes with some nifty features and some really sweet syntax lollies. This post will be an overview of the most useful features in my opinion.

Tuples

Tuples have been around for quite some time, but it has not been integrated into the language before now. A tuple is a data structure that has a specific number and sequence of elements. You can now declare methods that have multiple return values.

If you think you have to pass in sum and count into GetFoo, you're not alone. The syntax is sure a little strange in first sight.

Example:

public (int sum, int count) GetFoo()
{
    return (1, 2);
}

Deconstructing

You can deconstruct a tuple into separate parts. There is various way to achieve the same though.

Example:

// Explicit
(int sum, int count) = GetFoo();

// var
(var s, var c) = GetFoo();

// var shorthand
var (s, c) = GetFoo();

// Existing variables
int sum, count;
(sum, count) = GetFoo();

// Deconstructing objects also works
class Student
{
    public string Name { get; set; }
    public int Age { get; set; }

    public void Deconstruct(out string name, out int age)
    {
        name = Name;
        age = Age;
    }
}

var student = new Student { FirstName = "Peter", Age = 22 };
var (name, age) = person;

Tuple initialization

var student = ("Peter", 22);
Console.WriteLine($"Name: {student.Item1}, Age: {student.Item2}");

// Assign item names
var student = (name: "Peter", age: 22);
Console.WriteLine($"Name: {student.name}, Age: {student.age}");

Local functions

Local functions are functions that are defined inside a method and have access to all local variables in that method. Before C#7 you could declare a Func to achieve this, but that is unnecessarily expensive and it looks quite ugly. The nice thing about local functions is that the compiler transforms it to a regular private static method, so there will be literally no overhead.

Example:

static void Main(string[] args)
{
    int Sum(int x, int y)
    {
        return x + y;
    }
    
    Console.WriteLine(Sum(10, 20));
    Console.ReadKey();
}

It's worth knowing that local functions support delightful lambda syntax and you can also declare a local function with the same name as an existing private method.

Out variables

The out var declaration is syntax sugar to improve readability when using TryParse.

Example:

Before:

int value;
if (int.TryParse(input, out value)) 
{
    Foo(value);
} 
else 
{
    Foo(value);
}
Foo(value);

Now:

if (int.TryParse(input, out var value)) 
{
    Foo(value);
}
else 
{
    Foo(value);
}
Foo(value); // Value is still in scope

Digit separators

In C#7 we have the underscore _ as digit separators. This is purely syntax sugar but it does improve readability in large numbers.

Example:

int bin = 0b1001_1010_0001_0100;
int num = 1_2__2_3_4_5_6_3; // Separators is simply ignored

Pattern Matching

In C#7 we get pattern matching. No doubt C# is getting a little more functional with every new release.

is

The is operator is used to checking if an object is compatible with a specific type, e.g. if a specified interface is implemented. In C#7 you can use is to check for patterns.

Example:

Before:

string s = o as string;
if(s != null)
{
    // Do something with s
}

Now:

if(o is string s)
{
    // Do something with s
};

switch

The switch statement has been enhanced as well. Using case, you can check for a const pattern (this was possible before), a type pattern to immediately declare a variable of the specified type, and the var pattern.

You could also use the when keyword to enhance the pattern filter to only apply when a specific condition is fulfilled. This is the same keyword already used with exception filters in C#6.

Example:

public static void SwitchPattern(object o)
{
    switch (o)
    {
        case null:
            Console.WriteLine("It's a constant pattern");
            break;
        case int i:
            Console.WriteLine("It's an int");
            break;
        case Person p when p.FirstName.StartsWith("An"):
            Console.WriteLine($"a An person {p.FirstName}");
            break;
        case Person p:
            Console.WriteLine($"Any other person {p.FirstName}");
            break;
        case var x:
            Console.WriteLine($"it's a var pattern with the type {x?.GetType().Name}");
            break;
        default:
            break;
    }
}

Learn more

If you want to dig deeper into the neat new features in C#7, there are quite some material you can read.

Sort:  

c#7 was a nice improvement although the pattern matching is too verbose for my liking. Would have been nice to have something like ML/Haskell. But guess it fits better with the language as it stands.

C# 8 will be interesting depending on which way they jump with non nullable reference types.

Yes, I agree, it's somewhat verbose. There is always F# if you want the sleeker syntax :D

There will be interesting to see how they solve it, non nullable reference types is a really welcoming addition to the language.

It looks like the breaking change is winning, which I prefer

Not nullable
MyObjVar var = new MyObjVar();

Nullable
MyObjVar? var = null;

This needs to be enabled though to work that way for backwards compatibility. It is also a comppile layer, behind the scene they will still be nullable

Yep F# is epic

Same syntax as nullable value types is great.

Congratulations @kleinrein! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

You got a First Reply
Award for the number of upvotes

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

super interesting updates and discussion thanks!

Coin Marketplace

STEEM 0.26
TRX 0.20
JST 0.038
BTC 95291.25
ETH 3590.41
USDT 1.00
SBD 3.78