Over the past couple of previews, new C# language features have been trickling in, but Preview 4 marks a point where the majority of C# 7.0 are now available.
Here’s a code sample that uses a good number of these features, and that works in Preview 4 today:
class Program
{
static void Main(string[] args)
{
object[] numbers =
{ 0b1, 0b10, new object[] { 0b100, 0b1000 }, // binary literals
0b1_0000, 0b10_0000 }; // digit separators
var (sum, count) = Tally(numbers); // deconstruction
WriteLine($"Sum: {sum}, Count: {count}");
}
static (int sum, int count) Tally(object[] values) // tuple types
{
var r = (s: 0, c: 0); // tuple literals
void Add(int s, int c) { r = (r.s + s, r.c + c); } // local functions
foreach (var v in values)
{
switch (v) // switch on any value
{
case int i: // type patterns
Add(i, 1);
break;
case object[] a when a.Length > 0: // case conditions
var t = Tally(a);
Add(t.sum, t.count);
break;
}
}
return r;
}
}
For a full write-up about tuples, deconstruction, pattern matching, local functions, and the rest of C# 7.0, head over to the .NET Blog.
Earlier versions of some of these features were shown at Build 2016.
Happy hacking!
![]() |
Mads Torgersen, C# Language Program Manager @MadsTorgersen Mads leads the design of the C# language. During his 11 years at Microsoft he also contributed to Typescript, Roslyn, Visual Basic, and LINQ. Before that he was a professor at Aarhus University, doing research on programming languages and type systems. |
Yay tuples!
Tiny as they may be, featurewise, binary literals and digit separators will be very nice to finally have.
Are the digit separators coming for all inline number formats (hex, dec, long/decimal)?
/// todo: replace mutable c#-style code by array.reduce
let rec tally (values :obj array) =
let mutable r = 0,0
let add = fun s c -> r Array.iter(function
| 😕 int as i -> add i 1
| 😕 array as a when a.Length > 0 ->
tally(a) ||> add
| _ -> printfn “f# can’t leak by accident!”)
r
As the blog comments can’t accept code, here is the snippet:
http://www.fssnip.net/7QE
Anyways, the point is that even if C# now has the same features there are still the problems that C# doesn’t lead to good design by default: mutable code, possible thread-safety issues, leaking switch-clauses, imperative code and not declarative.
Now that you have had CLR modified to get named tuples it’s kind of funny that you use variable names like “c” and “s” to point out that it wasn’t worth it.
The add function can be simplified by removing the “fun” keyword:
let add s c = r <- s + fst r, c + snd r
Looks absolutely great. Juts a shame I’m unable to use VS2015 because of the extremely broken autoindenting engine 🙁
Pro-Tip: Turn autoindentation off
Are the value type tuples mutable? If so, is gethashcode safe?
With C# getting so many F# features is proof of just how well designed F# really is. The downside is that C# is approaching C++ in terms of complexity with every new release.
It’s not F# being well designed – it’s just characteristics of functional programming.
Every functional language has those features.
If you read https://en.wikipedia.org/wiki/Functional_programming , you will notice that those concepts were used back in 1950’s.
It’s very unfortunate that people award Microsoft for “designing” concepts that were used decades ago, but that’s just lack of knowledge.
Wow. Arrogant much?
Nice sugar, but things like non-nullable reference types would be far more useful.
var r = (s: 0, c: 0); // tuple literals
IntelliSense shows error: Predefined type ‘System.ValueType`2’ is not defined or imported.
get system.valtuetype from nuget. to see it turn pre-release.
C#7 has many useful features, but for now I’ll probably stick to Visual Studio 2015, because on Visual Studio Gallery there are almost 10 times more extensions for this version than for Visual Studio 15. Some extensions which I use frequently are not compatible with the new version, so using it doesn’t really make sense for me. This is the biggest issue with Visual Studio which should be solved. Please vote for this suggestion on uservoice: https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/10209516-newer-versions-of-visual-studio-say-2015-should
If you wan to run the code in VS 15 Preview 4, don’t forget to include the NuGet Package containing the ValueTuple type:
https://www.nuget.org/packages/System.ValueTuple/4.0.0-rc3-24212-01
Awesome. Looks foreign but very cool features.
Interesting that I have moved to Tuples as much better object references. If only WinDiv came up with stuff like this.
Binary is a big part of C programming, but it doesn’t have binary literals.
They are too long – you get too many misreads and typos.
Instead C programmers use hex, which works just fine.
As for tuples – they will mainly be used by people who are too lazy to write classes.
When I am being lazy, I want a language which forces me to do things properly instead.
The last thing we need is more anonymous code – datatype names are useful.
cool, now we can write swap in one line)
static (int a, int b) Swap(int a, int b) { return b, a; }
nice!
Great tools.
Awesome stuff! There is still on feature that I would really like to have in C# 7.0: the ability to use the ‘ref’ keyword for void extension methods.
Example:
public static void SetValue(ref this T value, T valueToSet)
{
value = valueToSet;
}
Hello!
Can this code be simplify?
static (int sum, int count) Tally(object[] values)
to…
static (int, int) Tally(object[] values)
Hello!
Can this code be simplify?
static (int sum, int count) Tally(object[] values)
to…
static (int, int) Tally(object[] values)
—————-
I have thought about it, variable name is necessary.
I have to agree with Sergey 100%.
The sugar is nice.
For some domains, the binary representation is extremely useful. And with the digits separator, become tractable, since otherwise would be too much of an eye chart.
Friendlier tuples is welcome.
The type patterns and case conditions brings a little more F# flavoring to C#.
However…
Non-nullable references would be far more useful. Even if it would be too much work (or too much of a breaking change) for .NET to utilize for itself. The lack of non-nullable references is C#’s trillion dollar mistake — fix this mistake.
And after that, immutability and transitive (deep) immutability.
Why use “when” when “where” was already there?!
Thank to Mads and the team for continually improving C#. These new features are welcome additions!
I’m a bit concerned about how these tuples will serialize, for instance, to JSON. What would that look like?
Just one observation only (other than that, this is awesome)
Why did you end up reserving a new keyword (“when”), when previously there was a “where” one already?
This might break existing code bases.
Thanks!
Ah, Tuples don’t have named arguments – an n-tuple simply has n positional elements – that’s what makes them tuples.
If these aren’t tuples, we should just call them something else to avoid confusion.
It seem like they should at least be optional so you can say
(int,int) Tally(…)
I see now that the names are optional — I’m not sure why such an atypical usage would be the single featured example, but glad to see this feature 🙂