if (p is Point) Console.WriteLine("p is Point"); else Console.WriteLine("p is not Point or null");
null
if (p is object) Console.WriteLine("p is not null"); if (p is null) Console.WriteLine("p is null");
C# 7 pattern-matching
if (GetPoint() is Point p) Console.WriteLine($"X={p.X} Y={p.Y}"); else Console.WriteLine("It is not Point."); if (GetPoint() is var p) Console.WriteLine($"X={p.X} Y={p.Y}"); else Console.WriteLine("It is not Point.");
, , 'null'? ?
, , , ( JetBrains !) , 'GetPoint() is var p' , 'GetPoint() is AnyType p' .
'var' , , [type inference].
C# 7 , , 'var', - …
, , , , , , , , . , , , , , .
? .
public static class LanguageExtensions { public static bool IsNull(this object o) => o is null; public static bool Is<T>(this object o) => o is T; public static bool Is<T>(this T o) => o != null; /* or same 'o is T' */ public static bool Is<T>(this T o, out T x) => (x = o) != null; /* or same '(x = o) is T' */ /* .... */ public static T As<T>(this object o) where T : class => o as T; public static T Of<T>(this object o) => (T) o; } public Point GetPoint() => null; // new Point { X = 123, Y = 321 }; if (GetPoint().Is(out AnyType p) Console.WriteLine($"X={p.X} Y={p.Y}"); else Console.WriteLine("It is not Point."); if (GetPoint().Is(out var p) Console.WriteLine("o is Any Type"); else Console.WriteLine("It is not Point.");
, - .
, , !
if (GetPoint() is AnyType p) Console.WriteLine($"X={p.X} Y={p.Y}"); else Console.WriteLine("It is not Point."); if (GetPoint() is {} p) Console.WriteLine("o is Any Type"); else Console.WriteLine("It is not Point."); if (GetPoint() is var p) Console.WriteLine("Always true");
, , pattern-matching.
if (GetPoint() is AnyType p { X is int x, Y is int y}) Console.WriteLine($"X={x} Y={y}"); else Console.WriteLine("It is not Point."); if (GetPoint() is var p { X is int x, Y is int y}) Console.WriteLine($"X={x} Y={y}"); else Console.WriteLine("It is not Point."); if (GetPoint() is { X is int x, Y is int y}) Console.WriteLine($"X={x} Y={y}"); else Console.WriteLine("It is not Point.");
( )
if (GetPoint() is AnyType { X is int x, Y is int y} p) Console.WriteLine($"X={p.X} Y={p.Y}"); else Console.WriteLine("It is not Point."); if (GetPoint() is var { X is int x, Y is int y} p) Console.WriteLine($"X={p.X} Y={p.Y}"); else Console.WriteLine("It is not Point."); // but if (GetPoint() is var p) Console.WriteLine($"Always true"); if (GetPoint() is { X is int x, Y is int y} p) Console.WriteLine($"X={p.X} Y={p.Y}"); else Console.WriteLine("It is not Point.");
, -, «» '{ }'.
— 'x is var y' , breaking change, .
, , , breaking change, .
, C# 8 Null Reference Types. ,
public bool SureThatAlwaysTrue(AnyType item) => item is var x;
C# 8, , 'false', 'item == null', , C# 8 'AnyType item' , 'item != null' ( 'SureThatAlwaysTrue(null)' warning message 'SureThatAlwaysTrue(null)'). '!' 'SureThatAlwaysTrue(null!)'
public bool SureThatAlwaysTrue(AnyType? item) => item is var x;
breaking change Nullable Value Types, C# 7
public bool SureThatAlwaysTrue(int? item) => item is var x;
warning message [breaking change].
, , : breaking change ?
, , «» «». .
:
Question: what does 'var' mean?
«» «» :
Pattern-matching rethinking (at C# 8 Nullable Reference Types context)
P.S. :
- Allow to use single control flow statements into expression bodied members
- Allow type inference for class members with autoinitializers and methods (use «var»/«auto» keywords)
- Add operator «of» for right-side type casting to avoid "(item as Type).Member" anti-pattern and round bracket hell in some cases