C# 7.0

Out variables

When calling methods with out parameters, you can declare variables inline

int.TryParse ("100", out int output);

If you don't need the value of an out parameter, you can discard it with an underscore

if (int.TryParse (numberString, out _)) 
{
   Console.Writeline("Valid number");
}

'is' expression

We can now test for type and introduce a variable at the same time

object mydata = 100;

if(mydata is int mynumber)
{
  mynumber++;
}

switch

We can now switch on *type*

void Main()
{
 Demo (new TextBox());
 Demo (new ComboBox());
 Demo (null); 
}


void Demo (Control control)
{
 switch (control)
 {
  case TextBox t:              // Switch on type
   //Your code here
   break;
  
  case ComboBox c:             
   //Your code here
   break;
   
  case null:                   // The 'null' literal is legal here
   //Your code here
   break;

  default:
   //Your code here
   break;
 }
}

TUPLES

Tuple is a data structure that contains a sequence of elements of different data types. It can be used where you want to have a data structure to hold an object with properties, but you don't want to create a separate type for it. The advantages include a simpler syntax, rules for conversions based on number (referred to as cardinality) and types of elements, and consistent rules for copies, equality tests, and assignments.

            var tuple = ("three", 3);
            Console.WriteLine(tuple.Item1);
            Console.WriteLine(tuple.Item2);

            //assigning with explicit typing. 
            (string, int) tuple2 = tuple;

            //named tuples.
            var namedTuple = (word: "three", number: 3);
            Console.WriteLine(namedTuple.word);
            Console.WriteLine(namedTuple.number);

TUPLES IN METHODS

With tuples, you can easily write a method that returns more than one value

(string, DateTime) Foo() => ("Now", DateTime.Now);
(string name, DateTime time) NamedFoo() => ("Now", DateTime.Now);
// You can discard a tuple member with an underscore:

  var (s, _) = Foo();

lOCAL FUNCTIONS

You can now declare a function within a function.

We can't do method overloading with local functions.

Local functions are also allowed inside iterators.

        public int Calculate(int x)
        {
            return Sum(x).sum;
            
            (int sum, int count) Sum(int i)
            {
                return (100, 1);
            }            
        }

Ref locals and returns


More expression-bodied members

C# 6 introduced expression-bodied members for member functions, and read-only properties.

C# 7.0 expands the allowed members that can be implemented as expressions. In C# 7.0, you can implement constructors, finalizers, and get and set accessors on properties and indexers.

// Expression-bodied constructor
public ExpressionMembersExample(string label) => this.Label = label;

// Expression-bodied finalizer
~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");

private string label;

// Expression-bodied get / set accessors.
public string Label
{
    get => label;
    set => this.label = value ?? "Default label";
}

throw expressions

You can now throw expressions in expressions clauses.

public string Foo() => throw new NotImplementedException();
string result = new Random().Next(2) == 0 ? "Good" : throw new Exception ("Bad");