Overview of Planned C# 7.0 Language Features
The article introduces the upcoming C# 7.0 language enhancements—including output variables, pattern matching, extended switch statements, tuples, deconstruction, local functions, numeric literal improvements, ref returns, new async return types, and throw expressions—explaining their syntax, usage, and current preview limitations.
This article presents the planned language features for C# 7.0 that will become active with Visual Studio "15" Preview 4, inviting feedback on the upcoming changes.
Output Variables – Previously an output parameter required a pre‑declared variable; C# 7.0 allows declaring the variable inline with out int x (or out var x ) directly in the argument list, reducing boilerplate and improving readability.
public void PrintCoordinates(Point p)
{
p.GetCoordinates(out int x, out int y);
WriteLine($"({x}, {y})");
}Output variables follow the same scoping rules as local variables; in Preview 4 their scope is limited to the statement that declares them.
Pattern Matching – C# 7.0 introduces patterns that test the shape of data and extract values. Three basic patterns are supported:
Constant pattern (e.g., case null )
Type pattern (e.g., is int i )
Var pattern (e.g., var x ) which always matches and binds the value.
Existing constructs gain pattern support: the is expression can now include a pattern on the right‑hand side, and switch case labels can use patterns with optional when‑clauses.
if (o is int i || (o is string s && int.TryParse(s, out i)))
{
// use i
} switch (shape)
{
case Circle c:
WriteLine($"circle with radius {c.Radius}");
break;
case Rectangle r when (r.Length == r.Height):
WriteLine($"{r.Length} x {r.Height} square");
break;
case null:
throw new ArgumentNullException(nameof(shape));
}Tuples – C# 7.0 adds tuple types and literals, allowing methods to return multiple values without creating custom types.
(string first, string middle, string last) LookupName(long id)
{
// retrieve values
return (first, middle, last);
}Tuple elements can be accessed by default names ( Item1 ) or by giving them explicit names in the declaration or literal.
var names = LookupName(id);
WriteLine($"found {names.first} {names.last}.");Deconstruction – Tuples (and any type with a suitable Deconstruct method) can be split into separate variables.
(string first, string middle, string last) = LookupName(id1);
var (first, middle, last) = LookupName(id2);Wildcard discard ( * ) may be used in deconstruction to ignore values, though its presence in C# 7.0 is still uncertain.
Local Functions – Functions can be declared inside other functions, gaining access to the enclosing scope just like lambdas.
public int Fibonacci(int x)
{
if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x));
return Fib(x).current;
(int current, int previous) Fib(int i)
{
if (i == 0) return (1, 0);
var (p, pp) = Fib(i - 1);
return (p + pp, p);
}
}Local functions must be declared before use in Preview 4; this restriction will be relaxed later.
Numeric Literal Improvements – Underscores can be used as digit separators, and binary literals ( 0b... ) are now supported.
var d = 123_456;
var x = 0xAB_CD_EF;
var b = 0b1010_1011_1100_1101_1110_1111;Ref Returns and Locals – Methods can return a reference to a variable, allowing callers to modify the original storage directly.
public ref int Find(int number, int[] numbers)
{
for (int i = 0; i < numbers.Length; i++)
if (numbers[i] == number) return ref numbers[i];
throw new IndexOutOfRangeException($"{nameof(number)} not found");
}
int[] array = {1,15,-39,0,7,14,-12};
ref int place = ref Find(7, array);
place = 9; // array now contains 9 at the former position of 7Safety rules restrict which references can be returned.
Async Return Types – Beyond void , Task , and Task<T> , C# 7.0 will allow custom awaitable types such as ValueTask<T> to reduce allocations in high‑throughput async scenarios.
Throw Expressions – Exceptions can now be thrown as part of an expression, enabling concise null‑checking and conditional logic.
public Person(string name) => Name = name ?? throw new ArgumentNullException(nameof(name));
public string GetFirstName()
{
var parts = Name.Split(' ');
return parts.Length > 0 ? parts[0] : throw new InvalidOperationException("No name!");
}Many of these features are still pending full implementation in the final release; the article encourages readers to test the preview and provide feedback.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.