Separating functions and Data
Expressions over statements
Immutable state
It's already there
You're already using it
Not hard at all
More power
Cleaner code
It's already there & you're using it
list
.Select(number => number + " - Chickens")
.Where(word => word.Contains('1'))
.Where(string.IsNullOrEmpty)
.GroupBy(word => word.Length)
.ToList();
It's already there & you're using it
private static bool IsValid(int input)
...
list
.Where(IsValid)
.ToList();
private bool Validate(string input, params Func<string, bool>[] validations)
...
var isValid = Validate(value, IsNotEmpty, IsAllUppercase);
It's already there & you're using it
return a ? b : c
var message = number switch
{
> 5 => "Too much",
< 0 => "Cannot be negative",
< 1 => "Too low",
_ => "It's ok"
};
It's already there & you're using it
int, string, Guid, DateTime, Tuple<> ...
It's already there & maybe you're using it
public record Response
{
public DateOnly From { get; init; }
public DateOnly To { get; init; }
public int Duration { get; init; }
}
It's already there & maybe you're using it
var x = response with
{
Duration = 20
};
Embrace your inner lambda
public static Risk CalculateRisk(int age, Gender gender)
{
var treshold = 0;
if (gender == Gender.Female)
treshold = 62;
else
treshold = 60;
if (treshold > age)
return Risk.Low;
return Risk.Medium;
}
public static Risk CalculateRisk(int age, Gender gender) =>
Treshold(age, gender) > age ? Risk.Low : Risk.Medium;
private static int Treshold(int age, Gender gender) =>
gender == Gender.Female ? 62 : 60;
public static int? CalculateSalary()
{
var employee = GetEmployee();
if (employee == null)
return null;
return employee.Name == "Tom"
? 0
: int.MaxValue;
}
public static int? CalculateSalary() =>
GetEmployee()
.Map(employee => employee.Name == "Tom"
? 0
: int.MaxValue);
public static TOut? Map<TIn, TOut>(this TIn? input, Func<TIn, TOut> map) =>
input == null ? null : map(input);
public static int? CalculateSalary() =>
GetEmployee().Map(ToSalary);
public static int[] CalculateSalaries() =>
GetEmployee().Select(ToSalary).ToArray();
private static int ToSalary(Employee employee) =>
employee.Name == "Tom" ? 0 : int.MaxValue;
public static TOut? Map<TIn, TOut>(this TIn? input, Func<TIn, TOut> map) =>
input == null ? null : map(input);
public static TOut? Map<TIn, TOut>(this TIn? input, Func<TIn, TOut> map) =>
input == null ? null : map(input);
public static TOut? Map<TIn, TOut>(this TIn? input, Func<TIn, TOut> map)
where TOut : struct
=> input == null ? null : map(input);
public static async Task<int?> CalculateSalary()
{
var employee = await GetEmployee();
if (employee == null)
return null;
return employee.Name == "Tom"
? 0
: int.MaxValue;
}
public static async Task<int?> CalculateSalary()
{
var employee = await GetEmployee();
return employee.Map(employee => employee.Name == "Tom" ? 0 : int.MaxValue);
}
public static async Task<int?> CalculateSalary() =>
await GetEmployee().Map(ToSalary);
public static async Task<TOut?> Map<TIn, TOut>(this Task<TIn?> input,
Func<TIn, TOut> map)
await input switch
{
null => null,
var value => map(value)
};
public static async Task<(int, string)?> CalculateSalary()
{
var employee = await GetEmployee();
return employee == null
? null
: (ToSalary(employee), ToSomethingElse(employee));
}
public static async Task<(int, string)?> CalculateSalary() =>
await
from employee in GetEmployee()
from salary in ToSalary(employee)
from somethingElse in ToSomethingElse(employee)
select (salary, somethingElse);
public static async Task<(int, string)?> CalculateSalary() =>
await
from employee in GetEmployee()
from salary in ToSalary(employee)
from somethingElse in ToSomethingElse(employee)
select (salary, somethingElse);
public static async Task<T3> SelectMany<T1, T2, T3>(this Task<T1> source,
Func<T1, T2> bind,
Func<T1, T2, T3> project) =>
await source switch
{
var t1 => project(t1, bind(t1))
};
void
public static async Task Store(Employee employee)
{
if (employee.Id > 10)
await SaveToDatabase(employee);
else
await SaveToMemory(employee);
}
public static async Task SaveToDatabase(Employee employee)
public static async Task SaveToMemory(Employee employee)
public static async Task Store(Employee employee) =>
employee.Id > 10
? await SaveToDatabase(employee)
: await SaveToMemory(employee);
public static async Task SaveToDatabase(Employee employee)
public static async Task SaveToMemory(Employee employee)
global using Unit = System.ValueTuple;
public static async Task<Unit> Store(Employee employee) =>
employee.Id > 10
? await SaveToDatabase(employee)
: await SaveToMemory(employee);
public static async Task<Unit> SaveToDatabase(Employee employee)
// Do something
return new Unit();
public static async Task<Unit> SaveToMemory(Employee employee)
// Do something
return new Unit();
Be more functional
https://github.com/Tomas-Juri/Functional-programming-in-csharp