I have completed viewing this talk titled “Change your habits: Modern techniques for modern C#” by Bill Wagner (TIL: Bill authored Effective C#). I list down below, all that I have learned from this talk. You can watch the full video at the end of this post (with privacy enabled).
1. Using Tuples in Constructor
Assume we have a Point struct:
public struct Point
{
public double X
{
get;
private set;
}
public double Y
{
get;
private set;
}
private double? distance;
public double Distance
{
get
{
if (!distance.HasValue)
distance = Math.Sqrt(X * X + Y * Y);
return distance.Value;
}
}
public Point(double x, double y)
{
X = x;
Y = y;
distance = default; // default only available in C# 7.1
}
}
Instead of this constructor:
public Point(double x, double y)
{
X = x;
Y = y;
distance = default; // default is only available in C# 7.1
}
We use:
public Point(int x, int y) => (this.x, this.y, this.distance) = (x, y, default);
2. Tuples in Operator Overloading
We are still in the Point struct context. Instead of:
public static operator ==(Point left, Point right) => left.x == right.x && left.y == right.y; public static operator !=(Point left, Point right) => left.x != right.x || left.y != right.y;
Use
public static operator !=(Point left, Point right) => (left.x, left.y) != (right.x, right.y);
3. Using Tuples to Swap Values
Remember that interview question where you supposed to swap two values without introducing a third variable? Tuples can easily help you do that. Bill’s sample below is to swap the X,Y coordinates of Point struct.
public void SwapCoords() => (X,Y) = (Y,X);
Based on above example, I created below to help me understand Tuples more.
static void Main(string[] args)
{
var originalTuple = (10, 20);
var swappedTuple = SwapValue(originalTuple);
Console.WriteLine("Original:" + originalTuple); // Original:(10, 20)
Console.WriteLine("Swapped:" + swappedTuple); // Swapped:(20, 10)
Console.ReadLine();
}
public static (int, int) SwapValue((int, int) t) => (t.Item2, t.Item1);
4. Immutable Struct Using Readonly
Below is the completely immutable Point struct
public readonly struct Point
{
public double X
{
get;
}
public double Y
{
get;
}
public double Distance
{
get;
}
public Point(double x, double y) =>
(X, Y, Distance) = (x, y, Math.Sqrt(x * x + y * y));
}
5. Throw ArgumentNullException on null parameter
Below is a Person class which will throw ArgumentNullException upon null parameter. The example also using new keyword nameof, which was introduced in C# 6.0.
public class Person
{
private string _firstName;
private string _lastName;
public string FirstName
{
get => _firstName;
set =>
_firstName = value ??
throw new ArgumentNullException(paramName: nameof(value), message: "cannot set name to null");
}
public string LastName
{
get => _lastName;
set =>
_lastName = value ??
throw new ArgumentNullException(paramName: nameof(value), message: "cannot set name to null");
}
public string HypenatedForPartner(Person partner)
{
// _ is a discard variable so we can do the null checking
// without using "if" statement
_ = partner ?? throw new ArgumentNullException(paramName: nameof(partner), message: "Partner should not be null");
return $"{partner.LastName} - {this.LastName}";
}
}
6. Using Tuples in Switch Pattern Matching
Similar to what I have covered before, but now Bill have shown me that we can use Tuples in pattern-matching switch statement.
Take a look at PeakTimePremium method. Read and understand the business requirements in the comment above it. And now imagine how would you implement it using if-else statements. Then now compares it with the how it is actually implemented using pattern-matching switch statement. The pattern-matching switch statement is very much clearer and easier to understand!
public static class TollCalculations
{
private static bool IsWeekDay(DateTime timeOfToll) =>
timeOfToll.DayOfWeek switch
{
DayOfWeek.Saturday => false,
DayOfWeek.Sunday => false,
_ => true
};
private enum TimeBand
{
MorningRush,
DayTime,
EveningRush,
Overnight
}
private static TimeBand GetTimeBand(DateTime timeOfToll)
{
int hour = timeOfToll.Hour;
if (hour < 6)
return TimeBand.Overnight;
else if (hour < 10)
return TimeBand.MorningRush;
else if (hour < 16)
return TimeBand.DayTime;
else if (hour < 20)
return TimeBand.EveningRush;
else
return TimeBand.Overnight;
}
// Calculate a peak time multiplier:
// weekend multiplier is 1.0
// late night / early morning is a discount, 0.75
// daytime during any weekday is 1.5
// morning rush inbound is double (2.0)
// morning rush outbound is 1.0
// evening rush inbound is 1.0
// evening rush outbound is double (2.0)
public static decimal PeakTimePremium(DateTime timeOfToll, bool inbound) =>
(IsWeekDay(timeOfToll), GetTimeBand(timeOfToll), inbound) switch
{
(true, TimeBand.MorningRush, true) => 2.0m,
(true, TimeBand.EveningRush, false) => 2.0m,
(true, TimeBand.DayTime, _) => 1.5m,
(_, TimeBand.Overnight, _) => 0.75m,
(_, _, _) => 1.0m
};
}
After learning all these new features in C#, my only gripe is that it only works in Visual Studio 2019. Visual Studio 2017 is only supporting up to .NET Core 2.1.
That’s all guys. I hope it somehow helps you. Below is the full video of Bill’s talk:
loading...
About Hardono
Incoming Search
.net, c#
