The State of Csharp Whitepaper
The State of Csharp Whitepaper
The State of Csharp Whitepaper
By Kevin Griffin
Progress.com
Progress.com
Progress.com
Progress.com
Platforms
What have we covered so far? C# is a standards-based language that has grown exponentially in its feature
set over the past 15 years. Combine that with a series of world-class development tools, and you are setting
yourself up for a great career of development focused solely on Windows, correct?
Not at all! Given an investment of time and energy into C#, there is no limit to the number of platforms you
will be able to develop for. Next, we will cover a few of the most common environments C# developers can
deploy to.
Desktop
Building applications for Windows has always been
a staple for the C# developer. In the beginning, our
applications were written using Windows Forms
(WinForms). WinForms, combined with the powerful
designer tools within Visual Studio, allows a developer
to quickly scaffold the look and feel of an application.
Business logic for control interactions was simply done
through the use of event handlers.
Progress.com
Web
Progress.com
Mobile
Progress.com
Progress.com
Out Variables
Using the out keyword within C# is nothing new. If you declare a variable within
a method called with out, you are instructing the compile that you are expecting
the method to set the values of those at runtime.
public void TestMethod()
{
string fullName;
GetPersonName(Kevin, Griffin, out fullName);
}
Commonly, the problem is that you have to declare the variable before the
method call using out. In C# 7.0, there is the concept of out variables, which will
save you a couple keystrokes by allowing you to declare the variable inline.
The above example can be quickly refactored:
public void TestMethod()
{
GetPersonName(Kevin, Griffin, **out string fullName**);
}
In parallel, if you do not know the type of the parameter, you can substitute the
type of the parameter with var.
Progress.com
10
Pattern Matching
In C# 7.0, there is a heavy emphasis on pattern matching. Simply described, C#
7.0 will have the ability to see if data follows in a certain pattern or shape. As
you will see in the next section, C# 7.0 will also have the ability to automatically
extract a value if a pattern matches successfully.
The next example shows pattern matching in action with a Switch statement:
switch(person)
{
case CEO ceo:
CallCeo(ceo);
break;
case Manager salesManager when (salesManager.Department ==
Sales):
CallSalesManager(salesManager);
break;
case Manager other
CallManager(other);
break;
default:
WriteLine(Standard employee);
break;
case null:
throw new ArgumentNullException(nameof(person));
}
Progress.com
11
There are two fallback scenarios. Most commonly, the default case is that we
passed an object that doesnt match any of the previous patterns. Finally, there is
also a null case that will ensure the object passed in has a value, and throw a null
reference exception when a null is passed instead.
Is-Expressions
Building slightly on the above explanation of out variables, we can use pattern
variables to create variables on demand within a block of code.
public void LoadPerson(object age)
{
if (age is int ageInt || (age is string ageString &&
int.TryParse(ageAsString, out ageInt)))
{
// ageInt contains a value.
}
}
Looking at the code example, we have a case where the age of a person might
come into our application as either a string or an integer. The If statement is an
integer, immediately dropped into the if statement body. However, if age is a
string, we will need to perform a conversion using the int.TryParse method.
Previously, the biggest issue with TryParse has been the need to define the
variable outside of the TryParse method call. In C# 7.0, this is no longer the case.
You can create the variable on demand if the TryParse method returns True.
Tuples
In C# 3.0, the Tuple<> reference type was added. What is a Tuple? Simply put, a
Tuple is a collection of values.
Imagine our above example for loading a persons information. There are several
ways we can return data from a method:
public Person LoadPerson(){}
Progress.com
12
The first example returns a fully qualified type. Depending on your use case, this
is perfectly acceptable. However, what if the type Person was throwaway? You
are going to retrieve the data, use it and throw it away. Creating the Person type
to simply support a single method is rather cumbersome.
The second example uses the Tuple<> generic type to retrieve the same
information. What does a call to LoadPerson look like?
public void Foo()
{
var person = LoadPerson();
var fullName = ${person.Item1} {person.Item2};
}
For a simple, two-value Tuple, we are starting to veer off the road of readability.
What is Item1 or Item2 supposed to reflect? Is it first name and last name,
respectfully? Could it be name and address? City or state? There isnt much of a
way to know because Item1 and Item2 are as explanatory as a or b.
With C# 7.0, we are going to have access to real Tuples in a way that reflects
closer to functional languages such as F#. Our LoadPerson() method signature
would refactor as:
public (string firstName, string lastName) LoadPerson(){};
Notice the new syntax for the return type. The Tuple return type acts similar
to the pattern you use for declaring function parameters. Lastly, if you want to
create a Tuple inline, that can be done by using the new keyword.
return new (string firstName, string lastName) { firstName = Kevin,
lastName = Griffin};
Progress.com
13
Digit Separators
File this feature under crazy useful. How many times have you created a
numeric literal and had to count the number of digits to ensure you entered the
correct number?
For example:
long Gigabyte = 1048576;
Seemingly harmless number, unless you forget a digit. Normally, if someone wrote
this number longhand, it would be represented as 1,048,576. The commas help
dictate the position of the digits.
New digit separators in C# 7.0 allow you to do the same thing, except, instead of
using a comma, you can use an underscore.
long Gigabyte = 1_048_576;
Throw Exceptions
Writing defensive code often means throwing a lot of exceptions. In C# 7.0, there
are new adjustments to where you can throw an exception.
For example, take this existing method:
public string GetName(Person person)
{
if (person.Name == null)
throw new Exception(Name not found);
return person.Name;
}
Progress.com
14
With the new changes to where we can throw exceptions, that method can be
quickly refactored to:
public string GetName(Person person)
{
return person.Name ?? throw new Exception(Name not found.);
}
DateTime? nullableDateTime;
What if the designers of C# simply changed the defaults? All reference types
were non-nullable by default, and you explicitly had to set a variable are nullable.
That would break 15 years of C# code already out in the wild.
As an alternative, what if we could explicitly declare that a value type was nonnullable? In C# 7.0, the ! operator is used to dictate that a variable is nonnullable.
string! nonNullableString;
Person! nonNullablePerson;
Progress.com
15
Progress.com
16
About Progress
Progress (NASDAQ: PRGS) is a global leader in application development, empowering the digital
transformation organizations need to create and sustain engaging user experiences in todays evolving
marketplace. With offerings spanning web, mobile and data for on-premise and cloud environments,
Progress powers startups and industry titans worldwide, promoting success one customer at a time.
Learn about Progress at www.progress.com or 1-781-280-4000.
Worldwide Headquarters
Progress, 14 Oak Park, Bedford, MA 01730 USA Tel: +1 781 280-4000 Fax: +1 781 280-4095
On the Web at: www.progress.com
Find us on
facebook.com/progresssw
twitter.com/progresssw
youtube.com/progresssw
For regional international office locations and contact information, please go to www.progress.com/worldwide
Progress is trademark or registered trademark of Progress Software Corporation
and/or one of its subsidiaries or affiliates in the U.S. and/or other countries. Any other
trademarks contained herein are the property of their respective owners.
2016 Progress Software Corporation and/or its subsidiaries or affiliates.
All rights reserved.
Rev 16/10 | 160928-0051
Progress.com
17