Expression-bodied members in C#

gpeipman
1,416 views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

Expression-bodied members

C# supports expression-bodied members that allow us to write more compact code by using expressions directly instead of wrapping them into properties. To get better idea about expression-bodied members take a look at the following code sample where Distance is expression-bodied member.

public double A { get; set; }
public double B { get; set; }
 
public double Distance => Math.Sqrt(X * X + Y * Y);

Expression-bodied members in action

Now let's see some real stuff where expression-bodied members can be of great help. Here is the InvoiceLine class with some properties that perform calculations.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System;
public class InvoiceLine
{
public decimal Amount { get; set; }
public decimal UnitPrice { get; set; }
public decimal DiscountRate { get; set; }
··· public decimal VatRate { get; set; }
·
// …
·
public decimal NetTotal
{
get
{
return Amount * UnitPrice * (1 - DiscountRate);
}
}
·
public decimal Total
{
get
{
return NetTotal * (1 + VatRate);
}
}
·
public decimal Discount
··· {
get
{
return Amount * UnitPrice * DiscountRate;
}
}
}
public class Program
{
static void Main()
{
var invoiceLine = new InvoiceLine { Amount = 2, UnitPrice = 4, DiscountRate = 0.5m, VatRate = 0.2m };
Console.WriteLine("Net total: " + invoiceLine.NetTotal);
Console.WriteLine("Total: " + invoiceLine.Total);
Console.WriteLine("Discount: " + invoiceLine.Discount);
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

We can turn calculating properties to expression-bodied members like show below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
public class InvoiceLine
{
public decimal Amount { get; set; }
public decimal UnitPrice { get; set; }
public decimal DiscountRate { get; set; }
public decimal VatRate { get; set; }
·
// …
·
public decimal NetTotal => Amount * UnitPrice * (1 - DiscountRate);·
public decimal Total => NetTotal * (1 + VatRate);
public decimal Discount => Amount * UnitPrice * DiscountRate;
}
public class Program
{
static void Main()
{
var invoiceLine = new InvoiceLine { Amount = 2, UnitPrice = 4, DiscountRate = 0.5m, VatRate = 0.2m };
Console.WriteLine("Net total: " + invoiceLine.NetTotal);
Console.WriteLine("Total: " + invoiceLine.Total);
Console.WriteLine("Discount: " + invoiceLine.Discount);
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Client code that uses InvoiceLine class doesn't need any changes due to this change in InvoiceLine class

foreach(var line in invoice.Lines)
{
    invoiceTotal += line.Total;
}

Using expressions with arguments

Expression-bodied members can be also expressions with arguments like shown in following example. There is simple task with worklogs collection. Collection is initialized when class is created and after this some worklogs are added to task. Then time spent on task today and yesterday is calculated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using System;
using System.Collections.Generic;
using System.Linq;
public class Worklog
{
public Guid Id { get; set; }
public DateTime Date { get; set; }
public long TimeSpent { get; set; }
public string UserName { get; set; }
}
·
public class Task
{
public Guid Id { get; set; }
public string Title { get; set; }
public IList<Worklog> Worklogs { get; set; }
·
public Task()
{
Worklogs = new List<Worklog>();
}
// …
·
public long TimeSpentThru(DateTime begin, DateTime end) =>
Worklogs.Where(w => w.Date >= begin.Date &&
w.Date <= end.AddDays(1).Date)
.Sum(w => w.TimeSpent);
}
public class Program
{
static void Main()
{
var now = DateTime.Now.Date;
var task = new Task();
task.Worklogs.Add(new Worklog { Date = now.Date.AddDays(-3), TimeSpent = 600 });
task.Worklogs.Add(new Worklog { Date = now.Date.AddDays(-2), TimeSpent = 300 });
task.Worklogs.Add(new Worklog { Date = now.Date.AddDays(-1), TimeSpent = 400 });
task.Worklogs.Add(new Worklog { Date = now.Date, TimeSpent = 100 });
Console.WriteLine("Time spent: " + task.TimeSpentThru(now.AddDays(-1), now));
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Be careful with more complex expression-bodied members and make sure they don't grow too big and doesn't form bad mess or spaghetti code.

Open Source Your Knowledge: become a Contributor and help others learn. Create New Content