when (C# Reference)

You can use the when contextual keyword to specify a filter condition in two contexts:

when in a catch statement

Starting with C# 6, When can be used in a catch statement to specify a condition that must be true for the handler for a specific exception to execute. Its syntax is:

catch ExceptionType [e] when (expr)

where expr is an expression that evaluates to a Boolean value. If it returns true, the exception handler executes; if false, it does not.

The following example uses the when keyword to conditionally execute handlers for an HttpRequestException depending on the text of the exception message.

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
   static void Main()
   {
      Console.WriteLine(MakeRequest().Result);
   }

   public static async Task<string> MakeRequest()
   { 
       var client = new System.Net.Http.HttpClient();
       var streamTask = client.GetStringAsync("https://localHost:10000");
       try {
           var responseText = await streamTask;
           return responseText;
       } 
       catch (HttpRequestException e) when (e.Message.Contains("301")) {
           return "Site Moved";
       }
       catch (HttpRequestException e) when (e.Message.Contains("404")) {
           return "Page Not Found";
       }
       catch (HttpRequestException e) {
           return e.Message;
       }
   }
}

when in a switch statement

Starting with 7, case labels no longer need be mutually exclusive, and the order in which case labels appear in a switch statement can determine which switch block executes. The when keyword can be used to specify a filter condition that causes its associated case label to be true only if the filter condition is also true. Its syntax is:

case (expr) when (when-condition):

where expr is a constant pattern or type pattern that is compared to the match expression, and when-condition is any Boolean expression.

The following example uses the when keyword to test for Shape objects that have an area of zero, as well as to test for a variety of Shape objects that have an area greater than zero.

using System;

public abstract class Shape
{
   public abstract double Area { get; }
   public abstract double Circumference { get; } 
}

public class Rectangle : Shape
{
   public Rectangle(double length, double width) 
   {
      Length = length;
      Width = width; 
   }

   public double Length { get; set; }
   public double Width { get; set; }
   
   public override double Area
   { 
      get { return Math.Round(Length * Width,2); } 
   } 
   
   public override double Circumference 
   {
      get { return (Length + Width) * 2; }
   }
}

public class Square : Rectangle
{
   public Square(double side) : base(side, side) 
   {
      Side = side; 
   }

   public double Side { get; set; }
}

public class Example
{
   public static void Main()
   {
      Shape sh = null;
      Shape[] shapes = { new Square(10), new Rectangle(5, 7),
                         new Rectangle(10, 10), sh, new Square(0) };
      foreach (var shape in shapes)
         ShowShapeInfo(shape);
   }

   private static void ShowShapeInfo(Object obj)
   {
      switch (obj)
      {
         case Shape shape when shape.Area == 0:
            Console.WriteLine($"The shape: {shape.GetType().Name} with no dimensions");
            break;
         case Rectangle r when r.Area > 0:
            Console.WriteLine("Information about the rectangle:");
            Console.WriteLine($"   Dimensions: {r.Length} x {r.Width}");
            Console.WriteLine($"   Area: {r.Area}");
            break;
         case Square sq when sq.Area > 0:
            Console.WriteLine("Information about the square:");
            Console.WriteLine($"   Length of a side: {sq.Side}");
            Console.WriteLine($"   Area: {sq.Area}");
            break;
         case Shape shape:
            Console.WriteLine($"A {shape.GetType().Name} shape");
            break;
         case null:
            Console.WriteLine($"The {nameof(obj)} variable is uninitialized.");
            break;
         default:
            Console.WriteLine($"The {nameof(obj)} variable does not represent a Shape.");
            break;   
      }
   }
}
// The example displays the following output:
//       Information about the rectangle:
//          Dimensions: 10 x 10
//          Area: 100
//       Information about the rectangle:
//          Dimensions: 5 x 7
//          Area: 35
//       Information about the rectangle:
//          Dimensions: 10 x 10
//          Area: 100
//       The obj variable is uninitialized.
//       The shape: Square with no dimensions

See also

switch statement
try/catch statement
try/catch/finally statement