Thursday, November 2, 2017

C# 6

1. Defining a Parameterless Constructor for a struct

In C# 5.0, every struct had a default parameterless constructor that you couldn’t override. Using the new operator invoked this constructor and all members of the struct were assigned default values.

public struct MyPoint
{
   public double X;
   public double Y;
}


class Program
{
   static void Main(string[] args)
   {
      MyPoint pt = new MyPoint(); // default values for X, Y (0.0)
      Console.WriteLine("{0}, {1}", pt.X, pt.Y);
   }
}


In C# 6.0, you can explicitly define a parameterless constructor for a struct, giving non-default values to the members of the struct

public struct MyPoint
{
   public double X;
   public double Y;


   public MyPoint()
   {
      X = 100.0;
      Y = 100.0;
   }
}

static void Main(string[] args)
{
   MyPoint pt = new MyPoint(); // 100.0, 100.0
   Console.WriteLine("{0}, {1}", pt.X, pt.Y);
}



2. Filtering Exceptions

C# 6.0 will include support for exception filters, that is–only catching a particular type of exception if an associated expression evaluates to true.
You can filter exceptions by including an if statement after the catch expression. If the result of evaluating the expression supplied is true, the exception is caught. If not, the behavior is as if you didn’t supply a catch block.
In the example below, we don’t catch divide by zero exceptions on Saturdays


int denom;
try
{
   denom = 0;
   int x = 5 / denom;
}
// Catch /0 on all days but Saturday
catch (DivideByZeroException xx) if (DateTime.Now.DayOfWeek != DayOfWeek.Saturday)
{
   Console.WriteLine(xx);
}



3. Using Lambda Expressions for Function Members

In C# 5.0, you could use a lambda expression wherever a delegate instance was expected. For example:

Func doubleMyNumber = (i) => 2 * i;

In C# 6.0, you can also use a lambda expression as the body of a function member. This simplifies the syntax for simple methods. For example:

public class Dog
{
   public Dog(string name, int age)
   {
      Name = name;
      Age = age;
   }

   public string Name { get; protected set; }
   public int Age { get; set; }

   public void AgeIncrement() => Age++;
   public int AgeInDogYears() => Age * 7;
}



4. Using Lambdas for Getter-Only Auto-Properties

In addition to using lambda expressions for method bodies in C# 6.0, you can use a lambda expression to implement the getter of a read-only auto-property.

public string Name { get; protected set; }
public int Age { get; set; }

public string BackwardsName => new string(Name.Reverse().ToArray());


The presence of the lambda expression tells the compiler that this is a property with a getter, rather than a field


5. Auto-property initializers

In early C# times there was only one way to declare them – very explicit:

private string _name = "Joe"; // backing field
public string Name
{
   get { return _name; }
   set { _name = value; }
}


The C# 6 release serves well here. You can now initialize property inline. It’s concise and readable.

public string Name { get; protected set; } = "Joe"
public string Name { get; set; } = "Joe";
public List Ingredients { get; } = new List { "dough", "sauce", "cheese" };


All of the initializers you’ve seen so far evaluate to a static expression. Non-static expressions, like the ones below, will generate compiler errors:

// compiler errors //public string Name2 { get; set; } = Name; //public decimal Price4 { get; set; } = InitMe();

decimal InitMe() { return 5m; }


The code tries to initialize Name2 with the value of Name, another property, which won’t work. Similarly, InitMe() is an instance method that won’t compile when used as the initializer for Price4. It doesn’t matter that InitMe() returns a numeric literal. Both of these situations generate a compiler error. Here's the error message for Price4

A field initializer cannot reference the non-static field, method, or property 'PizzaBase.InitMe()'

A virtual auto-property can be initialized too. Here’s an example:

A virtual auto-property can be initialized too. Here’s an example:

During initialization of the containing type, Price initializes before the constructor executes. It initializes like a field, meaning that a Price property override isn’t called during auto-property initialization. If you wanted the polymorphic initialization, you should initialize Price in the base class constructor, like this:

public abstract class PizzaBase
{
   public string Name { get; protected set; } = "Cheeze";

   public virtual decimal Price { get; set; } = 3.00m;

   public PizzaBase(IEnumerable extraIngredients)
   {
      Price = 2.95m;
   }
}


The abstract PizzaBase class is a base class for the PepperoniPizza class shown below. This class overrides the Price property:

public class PepperoniPizza : PizzaBase
{
   public decimal ExtraPrice { get; set; } = 0.25m;

   decimal price;
   public override decimal Price
   {
      get
      {
         return price;
      }

      set
      {
         price = value + .50m;
      }
   }

   public PepperoniPizza(decimal extraFees) : base(new List { "pepperoni" })
   {
      ExtraPrice += extraFees;
      Name = "Pepperoni";
   }
}