Getting Started with C# 7

James Montemagno

The releases of Visual Studio 2017 and Visual Studio for Mac introduced two spectacular new IDEs to develop mobile applications, cloud workloads, and introduced us to a world of powerful new C# features with the release of C# 7. I recently blogged about my favorite new feature, expression bodied members, and even recorded an entire podcast about how awesome C# 7 is. In this blog post, I’ll show you how to get started with C# 7 and some features that you can take advantage of right away in your mobile apps.

Tuples!

When you want to return multiple values from a function, Tuples are the way to go. C# 7 provides rich syntax and functionality that make Tuples a first class citizen with the introduction of the System.ValueTuple NuGet package. After installing the NuGet, we’re ready to start using Tuples as lightweight data structures with full IntelliSense.

Tuple Declaration

We can now create Tuples in several ways:

var names = ("James", "Montemagno");

As you can see, this automatically creates a Tuple with members of Item1 and Item2, but we can do better!

(string First, string Last) names = ("James", "Montemagno");

Or…

var names = (First: "James", Last: "Montemagno");

// accessed with:
var first = names.First;

Returning Tuples

Now that we know how to declare tuples, we can use them in a method:

static (string First, string Last) GetName(int index)
{
   var first = string.Empty;
   var last = string.Empty;

   // Go to database and get names
   var person = GetPersonFromDatabase(index);
   first = person.FirstName;
   last = person.LastName;

   return (first, last);
}

Then we can simply call the method:

var name = GetName(1);
Console.WriteLine($"My name is {name.First} {name.Last}.")

Or…

(string first, string last) = GetName(1);
Console.WriteLine($"My name is {first} {last}.")

You can also use full async/await support with Tasks!

static async Task GetName(int index)
{
   var first = string.Empty;
   var last = string.Empty;

   // Go to database and get names
   var person = await GetPersonFromDatabaseAsync(index);
   first = person.FirstName;
   last = person.LastName;

   return (first, last);
}

More Expression-Bodied Members

I can’t talk about C# 7 without mentioning my favorite feature, expression-bodied members, which were introduced in C# 6 and greatly enhanced in C# 7. Here’s how they improved our code in C# 6, using our good friend OnPropertyChanged as an example.

public void OnPropertyChanged(string name)
{
  var changed = PropertyChanged;
  if(changed == null)
    return;

  changed(this, new PropertyChangedEventArgs(name));
}

Now, with expression-bodied members we can write this:

public void OnPropertyChanged(string name)=>
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

Amazing! However, in C# 7 things get even better. Take a look at the standard get and set accessors that I use all the time:

public string Subtitle
{
  get { return subtitle; }
  set { SetProperty(ref subtitle, value); }
}

Look at all of those { and }, well no more! Here is some C# 7 for you:

public string Subtitle
{
    get => subtitle;
    set => SetProperty(ref subtitle, value);
}

They can now also be applied to constructors, finalizers, and indexers!

public ExpressionMembers(string label) => this.Label = label;

Pattern Matching

I love expression-bodied members, but I have to admit Pattern Matching is an absolutely delightful feature when using switch and is expressions. At its core, it enables us to inspect an object and determine if it satisfies a specific pattern that we’re expecting.

The most simple example is when you receive an Object type and need to figure out what it is. Let’s say we have a base class of Animal with several derived classes from it for specific animal types:

bool LikesBananas(object item)
{
   var monkey = item as Monkey;
   if(monkey != null)
      return monkey.LikesBananas;

   // or perhaps this way:
   if(item is Animal)
   {
      var animal = (Animal)item;
      return animal.FavoriteFood == "Banana";
   }

   return false;
}

Now, we can simplify this by combining pattern matching and the code expression and casting the item in line:

bool LikesBananas(object item)
{
   if(item is Monkey monkey)
      return monkey.LikesBananas;

   if(item is Animal animal)
     return animal.FavoriteFood == "Banana";

   return false;
}

Pattern Matching doesn’t stop there, as we can use it in switch cases as well:

int TotalAnimalsThatLikeBananas(IEnumberable values)
{
   int count = 0;
   foreach(var item in values)
   {
      switch(item)
      {
         case Monkey monkey:
            count += (monkey.LikesBananas ? 1 : 0);
            break;
         case IEnumberable subList:
            count += TotalAnimalsThatLikeBanans(subList);
            break;
         case Animal animal:
            count += (animal.FavoriteFood == "Banana" ? 1 : 0);
            break;
         case null:
            // maybe throw an exception?
            break;
         case default:
            break;
      }
   }
   return count;
}

Awesome out variables

This one is pretty straight-forward, but also extremely powerful. When using a method that has an out variable, you always have to declare it ahead of time, as such:

int result = 0;
if (!int.TryParse(input, out result))
{
    return null;
}

return result;

Not anymore! Now we can simply declare the variable inline and use it anywhere!

if (!int.TryParse(input, out int result))
{
    // result can be accessed here if we needed to
    return null;
}

return result;

Learn More

These are just a few of the new features that can be found in C# 7, which you can start using today in Visual Studio 2017 and Visual Studio for Mac. Be sure to read through the entire C# 7 documentation to learn more about all of the other exciting new features available to you right now.

0 comments

Discussion is closed.

Feedback usabilla icon