C# 7 recently added features focuses on simplification of code, performance, and consumption of data. These features are fully functional in visual studio 2017 but some features can also be used in Visual Studio “15” Preview 4.
![](http://findnerd.s3.amazonaws.com/imagedata/7768/7768.png)
So without further ado, let's take a look at the new C# 7 features:
1. Out Variables
Out variables are used for returning multiple values from a function. Unlike the return statement which is capable of returning only one value from a function. Arguments are passed by reference throughout the keyword. Out variables were available prior to C# 7 but had following difference. Before C# 7, the Out variables were declared in a separate statement. Whenever there was a requirement of calling a method without parameters, then these variables were used as an out parameter in the method.
Example :
class Program
{
static void Main(string[] args)
{
//Out variable declaration in separate statement
int studentId;
string studentName;
GetDetails(out studentId, out studentName);
Console.WriteLine("studentId: {0}, studentName: {1}",studentId,studentName);
Console.ReadKey();
}
public static void GetDetails(out int studentId, out string studentName)
{
studentId = 10;
studentName = "Kapil";
Console.WriteLine("studentId: {0}, studentName: {1}", studentId, studentName);
}
}
Note :
- var keyword cannot be used to declare out keyword
- out keyword cannot be used with the async method
In C# 7, the usage of out variable is the same as it was before. The only difference is in the declaration. Out variables can now be declared at the point where it is passed as an out argument.
Example:
using System;
namespace CSharp7Features
{
class Program
{
static void Main(string[] args)
{
GetDetails(out int studentId, out string studentName); //Out variable declared where it is passed as an argument
Console.WriteLine($"studentId: { studentId }, studentName: { studentName }");
Console.ReadKey();
}
public static void GetDetails(out int studentId, out string studentName)
{
studentId = 10;
studentName = "Kapil";
Console.WriteLine($"studentId: { studentId }, studentName: { studentName }");
}
}
}
Note :
- var keyword can be used to declare out keyword
Following Statement
GetDetails(out int studentId, out string studentName);
Can be replaced by
GetDetails(out var studentId, out var studentName);
Both the above codes offer same results:-
Output :
![](http://findnerd.s3.amazonaws.com/imagedata/7746/7746.png)
2. Tuples
Tuple can be defined as a data structure containing specific number and sequence of elements. It has the ability to combine multiple values of different types in a single object without creating a custom class. Tuple allows returning multiple values from a function. Before the C# 7, Tuples were available but had limitations. Limitations like Item1, Item2, etc were treated as the name of the members of tuple i.e member name does not have a semantic meaning.
Example :
class Program
{
static void Main(string[] args)
{
Tuple<int, string, bool> tupleValues;
tupleValues = GetMultipleValue();
Console.WriteLine("Elements in tuple");
//Elements of Tuple can be accessed via Item1,Item2,Item3 having no semantic meaning
Console.WriteLine("First element:{0} Second element:{1} Third element:{2}", tupleValues.Item1, tupleValues.Item2, tupleValues.Item3);
Console.ReadKey();
}
static Tuple<int, string,bool> GetMultipleValue()
{
Tuple<int, string, bool> tupleValues = new Tuple<int, string, bool>(30, "abc", false);
return tupleValues; //through tuple multiple values can be returned from function
}
}
Output:
With the new C# 7 update, the usage of Tuple is similar but has semantic names that can be assigned to each member.
Example
A Tuple can be used to return multiple values from a function as well as the members of tuple have a semantic name they can now be accessed with this name. To use tuple as return type a reference to the System.ValueTuple package can be added from NuGet (pre-release).
Tuple as return type
using System;
namespace CSharp7Features
{
class Program
{
static void Main(string[] args)
{
var studetails = GetDetails();
Console.WriteLine($"studentId: {studetails.studentId}, studentName: {studetails.studentName}");
}
public static (int studentId, string studentName) GetDetails()
{
int studentId = 10;
string studentName = "Kapil";
return (studentId, studentName);
}
}
}
Output:
![](http://findnerd.s3.amazonaws.com/imagedata/7752/7752.png)
Tuple deconstruction
It provides the facility of directly accessing the Tuple internal values i.e instead of accessing Tuple members via above method, deconstruction of Tuple can be done immediately.
Referring to above example:
(var studentId, var studentName) = GetDetails();
Console.WriteLine($"studentId: {studentId}, studentName: {studentName}");
Inline Tuples:
var studetails = new (int studentId, string studentName) { studentId = 10, studentName = kapil };
3. Pattern Matching
The introduction to patterns in C# 7 helped the existing language operators and statements. It is not fully implemented in C# 7 and there is expectation that some more work will come in next version.
- Pattern matching can be performed on any type of data even if it is custom data type whereas for if/else statement there is a requirement of primitives to match.
- The values can be extracted from expressions via pattern matching.
- Since pattern matching is partially implemented in C# 7, it was introduced in C#7 for two cases "is" expressions and "switch" expressions.
Example of is expressions in pattern matching
using System;
namespace CSharp7Features
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student("Kapil", 23);
TestIsPattern(stu);
Console.ReadKey();
}
public class Student
{
public string Name { get; set; }
public int Id { get; set; }
public Student(string name, int id)
{
Name = name;
Id = id;
}
}
public static void TestIsPattern(Student ob)
{
if (ob is null) //Checking for constant pattern
Console.WriteLine("It is constant pattern ");
if (ob.Id is int i) //Checking for int type pattern
Console.WriteLine($"It is a type pattern with an int and the value: {i}");
if (ob is Student s) //Checking for object(Student) type pattern
Console.WriteLine($"It is a object(student) type pattern with name: {s.Name}");
if (ob is var b) //Checking for var pattern
Console.WriteLine($"It is a var pattern with the type: {b?.GetType()?.Name}");
}
}
}
Output:
![](http://findnerd.s3.amazonaws.com/imagedata/7748/7748.png)
Example of switch expressions in pattern matching
namespace CSharp7Features
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student("Kapil", 23);
TestSwitchPattern(stu);
Console.ReadKey();
}
public class Student
{
public string Name { get; set; }
public int Id { get; set; }
public Student(string name, int id)
{
Name = name;
Id = id;
}
}
public static void TestSwitchPattern(Student ob)
{
switch (ob)
{
case null:
Console.WriteLine("It is a constant pattern");
break;
case Student s when s.Name.StartsWith("Ka"):
Console.WriteLine($"Student with ka as starting letters: {s.Name}");
break;
case Student s:
Console.WriteLine($"Student with Name {s.Name}");
break;
default:
break;
}
}
}
}
Output:
![](http://findnerd.s3.amazonaws.com/imagedata/7749/7749.png)
4. Local Functions
Local functions can be defined inside a method, inside the class constructor or within the property (getter or setter) thereby promoting encapsulation. Previously, when an application was developed, there was a need of creating methods which were not reusable thereby, leading to a situation where there are many private methods with no reusability. In such circumstances, the newly added C# 7 feature "Local functions" can be used. The scope of local function is limited(local) to enclosing function scope. Lambda expressions, parameters and local variables of enclosing scope are available.
Before C# 7, whenever the helper function was required, it was achieved using func and action types with anonymous methods but helper function implementation with these constructs did not support the generics, params and ref and out parameters. With the evolution of C# 7 helping function can be defined inside the body of another function termed as local functions.
Example of local functions
using System;
namespace CSharp7Features
{
class Program
{
static void Main(string[] args)
{
int Sum(int x, int y)
{
return x + y;
}
Console.WriteLine("The sum of numbers passed to local function is:{0}",Sum(10, 20));
Console.ReadKey();
}
}
}
Output:
![](http://findnerd.s3.amazonaws.com/imagedata/7750/7750.png)
5. Expression Bodied Members
Expression-Bodied methods and properties were available to C# 6 and C# 7. In addition to this C# 7 introduced expression-Bodied constructors, destructors and property accessors
Prior to C# 6
Expression-Bodied Properties
public string FullName
{
get
{
return Fname + " " + Lname;
}
}
In C# 6 and C# 7, it can be replaced with the following expression
public string FullName => Fname + " " + Lname;
Expression-Bodied Methods
Prior to C# 6
public bool IsSquare(Rectangle rectangle)
{
return rectangle.height == rectangle.width;
}
In C# 6 and C# 7, it can be replaced by the following expression:
public bool IsSquare(Rectangle rectangle) => rectangle.height == rectangle.width;
You can see that both curly brackets and the return keyword are removed. Return is implicit with a lambda expression.
Introduction of expression-bodied constructors, destructors and property accessors in C# 7
Expression-Bodied Constructors
Prior to C# 7
public Test()
{
Console.WriteLine($"Constructor");
}
In C# 7
public Test() => Console.WriteLine($"Constructor");
Expression-Bodied Destructors
Prior to C# 7
public ~Test()
{
Console.WriteLine($"Destructor");
}
In C# 7
public ~Test() => Console.WriteLine($"Destructor");
Expression-Bodied Property Accessors
In C# 6
private int _x;
public X
{
get
{
return _x;
}
set
{
_x = value;
}
}
In C# 7
private int _x;
public X
{
get => _x;
set => _x = value;
}
6. Numeric literal syntax improvements
For writing the numeric literal in readable fashion for the intended use, C# 7 has introduced the two new features, binary literals, and digit separators. Now a number can be written in binary form with '0b' at the beginning of constant to indicate that the number provided is a binary number.
Example :
public const int x= 0b0001;
public const int y= 0b0010;
To make a number more readable digit separator(_) was introduced. This digit separator can be used with binary, decimal, double and float types.
Example :
public const int x= 0b0001_0000; //binary
public const long y= 100_000_000_000; //for base 10
public const double z= 7.082_170_546_392_209e21; //double
7. Throw expressions
Before C# 7, Throw was a statement and not an expression. It cannot be used with many of C# constructs like conditional expressions, null coalescing expressions, and some lambda expressions. C# 7 introduces throw expressions that can be used with the constructs. Introduction of expression bodied members made throw expression very useful.
Null-Coalescing operator: This (??) operator provides an alternative value. if the value is not null, it returns left-hand side value (for below example this will be value of x) and if the value is null, it returns rright-hand side value (for below example this will throw null exception)
For example, if the value is not null, it returns left-hand side value (for below example this will be value of x) and if the value is null, it returns right hand side value (for below example this will throw null exception)
Example of throw expressions with following constructs is as follows:
Null-Coalescing Operator
int? x = null;
var y = x ?? throw new ArgumentNullException();
Conditional Operator : ? :
int? x = null;
var y = x != null ? x : throw new ArgumentNullException();
Lambda
public Test(string name) => _name = name ?? throw ArgumentNullException();
For any questions, brickbats and comments, feel free to drop a comment below.
0 Comment(s)