Monday 23 May 2016

Feature List in C# 7.0

Feature List in C# 7.0
  1. Local functions – code available currently in github
  2. Tuple Types and literals
  3. Record Types
  4. Pattern matching
  5. Non Nullable reference types
  6. Immutable types
  7.  Local Functions
  1. Up to C# 6.0 Ability to declare methods and types in block scope as like variables. It is already possible in current version of C# using Funtion c and Action types with anonymous methods, but they lack these features.
  2. Generics
  3. Ref and out
  4. Params

We can’t utilize these three features while using Func and Action. 
In C# 7.0


Local functions would have the same capabilities as normal methods but they can be only accessed within the block they were declared in.

public int Foo(int someInput)  
{  
     int Bar()  
 {  
      Console.WriteLine(“inner function”);  
     }  
    return Bar();  
}  


Evolution
 Advantages over lambda expressions
  • The syntax is similar and more consistent with the methods.

  • Recursion and forward references would work for the local functions but not for the lambda.

  • The lambda causes one or two memory allocations (the frame object for holding the variables inside that function and a delegate); but local function causes no memory allocations.

  • A local function can be generic.

  • It can accept ref and out parameters.

  • The direct method invocation is indeed faster than a delegate invocation.
Tuple Types and literals


Multiple return types – up to C# 6.0

In our current version of C# for returning multiple values from a method we have follow on of these methods.

  1. Out parameters
  2. Tuple-Types
  3. Class/ Struct
The most common reason for grouping up of temporary variables is to return multiple values from a method. 


Out parameters

public void GetMultipleValues(string deptName, out double topGrossSalary, out string hrName) { ... }  double gross,   
string hrName;  
GetMultipleValues (name, out gross, out hrName);  
Console.WriteLine($"Gross: { gross }, Hr: { hrName }");   
The disadvantage of using out parameter is we can’t use it for async methods. And you have declare parameters upfront and you have specify the specific type. 


Tuple-Types



Currently, C# has tuple type in order to hold multiple non related values together. We can rewrite the same method to use tuples to achieve the same functionality.
public Tuple<double, string> GetMultipleValues(string name) { ... }  
  
var tupleSalary = GetMultipleValues (name);  
Console.WriteLine($"Gross: { tupleSalary.Item1 }, Hr: { tupleSalary.Item2 }");   
This does not have the disadvantages of out-parameters, but the resulting code is rather obscure with the resulting tuple having property names like Item1 and Item2.


Class / struct



You could also declare a new type and use that as the return type.
Struct TopSalaryAndHr { public double topGrossSalary; public string hrName;}  
public TopSalaryAndHr GetMultipleValues(string name) { ... }  
  
var tupleSalary = GetMultipleValues (name);  
Console.WriteLine($"Gross: { tupleSalary.topGrossSalary }, HR: { tupleSalary.hrName }");   
This has none of the disadvantages of out-parameters and the tuple type, but it’s rather verbose and it is meaningless overhead. Because, the properties inside a (class / struct) are not coming under one roof and not having any common base characteristics. For the purpose of creating temporary data structure C# has provided Tuples.


All three ways mentioned above has their own disadvantages, so they want to overcome these shortcomings by introducing a miracle. 



Multiple return types in C# 7.0


Tuple return types:

You can specify multiple return types for a function, in much the same syntax as you do for specifying multiple input types. These are supposed to be called Tuple Types.

Public (double topGrossSalary,string hrName) GetMultipleValues(string name) {……….. }  
The syntax (double topGrossSalary,string hrName) indicates an anonymous struct type with public fields of the given names and types. Note that this is different from some notions of tuple, where the members are not given names but only positions (i.e Tuple<double, string>). This is a common complaint, though, essentially degrading the consumption scenario to that of System.Tuple above. For full usefulness, tuples members need to have names. This is also fully compatible with async.
public async Task<(double topGrossSalary, string hrName)> GetMultipleValues Async(string name) { ... }  
  
var t = await GetMultipleValues (myValues);  
Console.WriteLine($"Sum: {t.sum}, count: {t.count}");   
Tuple literals



Tuple values could be created as,
var t = new (int sum, int count) { sum = 0, count = 0 };  
Creating a tuple value of a known target type, should enable leaving out the member names.
public (int sum, int count) Tally(IEnumerable<int> values)   
{  
var s = 0; var c = 0;  
foreach (var value in values) { s += value; c++; }  
return (s, c); // target typed to (int sum, int count)  
}  
In the above example we have created a method with return type of tuple type with known target type and constructed a tuple type inline using the previously declared individual variables (i.e. return(s, c)).


Using named arguments as a syntax analogy it may also be possible to give the names of the tuple fields directly in the literal:
public (int sum, int count) Tally(IEnumerable<int> values)   
{  
var res = (sum: 0, count: 0); // infer tuple type from names and values  
foreach (var value in values) { res.sum += value; res.count++; }  
return res;  
}  
Tuple deconstruction


We don’t need to the tuple object as a whole because it doesn’t represent a particular entity or a thing, so the consumer of a tuple type doesn’t want to access the tuple itself, and instead he can access the internal values of the tuple. 



Instead of accessing the tuple properties as in the example of Tuple Return Types, you can also de-structure the tuple immediately:
(var sal, var hrName) = GetMultipleValues("some address");  
Console.WriteLine($"Salary: { sal }, Hr Name: {hrName}");  
Pattern Matching


Is Expression

The “is” operator can be used to test an expression against a pattern. As part of the pattern-matching feature repurposing the “is” operator to take a pattern on the right-hand-side.

relational_expression : relational_expression 'is' pattern;  
It is a compile-time error if the relational_expression to the left of the “is” token does not designate a value or does not have a type. Every identifier of the pattern introduces a new local variable that is definitely assigned after the “is” operator is true (i.e. definitely assigned when true).


Pattern

Patterns are used in the is operator and in a switch_statement to express the shape of data against which incoming data is to be compared.



There are many areas where we can use patterns in c#. You can do pattern matching on any data type, even your own, whereas if/else you always need primitives to match. Pattern matching can extract values from your expression.



For ex: I am having handful of types 
class Person(string Name);  
  
class Student(string Name, double Gpa) : Person(Name);  
  
class Teacher(string Name, string Subject) : Person(Name);  
  
//This sample uses the latest c# feature record type to create objects  
I wanted to perform some operations by type specific.
static string PrintedForm(Person p)  
{  
Student s;  
Teacher t;  
if ((s = p as Student) != null && s.Gpa > 3.5)  
{  
return $"Honor Student {s.Name} ({s.Gpa})";  
}  
else if (s != null)  
{  
return $"Student {s.Name} ({s.Gpa})";  
}  
else if ((t = p as Teacher) != null)  
{  
return $"Teacher {t.Name} of {t.Subject}";  
}  
else  
{  
return $"Person {p.Name}";  
}  
}  
Below is the client application which consumes the printed form function,
static void Main(string[] args)  
{  
Person[] oa = {  
new Student("Einstein", 4.0),  
new Student("Elvis", 3.0),  
new Student("Poindexter", 3.2),  
new Teacher("Feynmann", "Physics"),  
new Person("Anders"),  
};  
foreach (var o in oa)  
{  
Console.WriteLine(PrintedForm(o));  
}  
Console.ReadKey();  
}  
In the above sample for holding the objects, I need to create temporary variables s and t. So if I have n number of objects I need to create N temporary variables with distinct names unnecessarily, which make my code more verbose. And also the temporary variables are only need for a particular code block but it is having scope throughout the function. Note the need to declare variables s and t ahead of time even though it is used in one of the code blocks. 


As part of the pattern-matching feature we are repurposing the “is” operator to take a pattern on the right-hand-side. And one kind of pattern is a variable declaration. That allows us to simplify the code like this,
static string PrintedForm(Person p)  
{  
if (p is Student s && s.Gpa > 3.5) //!  
{  
return $"Honor Student {s.Name} ({s.Gpa})";  
}  
else if (p is Student s)  
{  
return $"Student {s.Name} ({s.Gpa})";  
}  
else if (p is Teacher t)  
{  
return $"Teacher {t.Name} of {t.Subject}";  
}  
else  
{  
return $"Person {p.Name}";  
}  
}  
Now you can see that the temporary variables s and t are only declared and scoped just to the place they need to be. The switch statement is also repurposed like the case branches can also have patterns instead of just constants.
static string PrintedForm(Person p)  
{  
switch (p) //!  
{  
case Student s when s.Gpa > 3.5 :  
return $"Honor Student {s.Name} ({s.Gpa})";  
case Student s :  
return $"Student {s.Name} ({s.Gpa})";  
case Teacher t :  
return $"Teacher {t.Name} of {t.Subject}";  
default :  
return $"Person {p.Name}";  
}  
}  
You can see in the above example that the case statements with patterns. Please note the new when key word in switch statement.


Record Types

Record Types is concept used for creating a type with only properties. By using that we can embed the constructor declaration with the class declaration. 



For ex:


Class Student(string Name, int Age);  
This simple statement would automatically generate the following code inbuilt.
Class Student   
{  
string _name;  
int _age;  
  
public Person(string Name, int Age)  
{  
this.Name = Name;  
this.Age = Age;  
}  
public string Name {get{ return this._name;}}  
public int Age {get{ return this._age;}}  
}   
  • Read-only properties, thus creating it as immutable type.

  • The class will automatically implement Equality implementations like (such as GetHashCode, Equals, operator ==, operator != and so forth).

  • A default implementation of ToString() method.
Non-Nullable reference types:


Non- nullable reference option will let you create a reference type that is guaranteed not to be null. NullReference expections are too common in a project. Often we developers forgot to check a reference type for null before accessing the properties of it, thus paving way to problems.


Either we forget check for it making our code vulnerable to runtime exceptions or we will check for it which makes our code more verbose.



Instead of using the “?” for identifying the nullable value type we are going to use “!”.The currently proposed syntax is as follows:
int a; //non-nullable value type  
int? b; //nullable value type  
string! c; //non-nullable reference type  
string d; //nullable reference type  
  
MyClass a; // Nullable reference type  
MyClass! b; // Non-nullable reference type  
  
a = null; // OK, this is nullable  
b = null; // Error, b is non-nullable  
b = a; // Error, a might be null, b can't be null  
  
WriteLine(b.ToString()); // OK, can't be null  
WriteLine(a.ToString()); // Warning! Could be null!  
  
if (a != null) { WriteLine(a.ToString); } // OK, you checked  
WriteLine(a!.Length); // Ok, if you say so  
  
It would be quite problematic using the same syntax for generic types and collections. For example  
// The Dictionary is non-nullable but string, List and MyClass aren't  
Dictionary<string, List<MyClass>>! myDict;   
  
// Proper way to declare all types as non-nullable  
Dictionary<string!, List<MyClass!>!>! myDict;  
For specifying all the arguments in a collection is non- nullable, there is a shortcut syntax has been proposed,
// Typing ! in front of the type arguments makes all types non-nullable  
Dictionary!<string, List<MyClass>> myDict;  
Immutable Types
Types of modelling in c#


An immutable object is an object whose state cannot be changed after its creation, which means Immutable objects are objects which once loaded cannot be changed / modified by any way external or internal.



Immutable objects offer few benefits, 
  • Inherently thread-safe.
  • Easier to parallelize.
  • Makes it easier to use and reason about code.
  • Reference to immutable objects can be cached, as they won’t change.
Currently it is also possible to create immutable classes. Create a class with properties only with get and read-only and constant private variables.
Public class Point  
{  
public Point(int x, int y)  
{  
x = x;  
Y = y;  
}  
public int X { get; }  
public int Y { get; }  
}  
Code in the above example is definitely an immutable class, but the intent of the class is not clearly stated as immutable. Because, in future any one can add setters to any of the properties thus making it as mutable. 


The proposed syntax for creating an immutable class will force the developer to strictly adhere the rules hence will make the class an immutable. Below is the proposed syntax,
public immutable class Point  
{  
public Point(int x, int y)  
{  
x = x;  
Y = y;  
}  
  
public int X { get; }  
public int Y { get; }  
}  


No comments:

Post a Comment