Featured image of post Use C# Records for your API Models

Use C# Records for your API Models

If you haven't started utilizing the new record types in C#, you should start using them for your API models right away! It's an area that offers a low barrier to entry and huge benefits.

When building an API, choosing the right data modeling approach can have a significant impact on the performance and maintainability of your code. One approach that we love is the use of C# records as API models. In this article, we’ll explore the benefits of using C# records for API models and also consider some of the performance considerations when using them.

Benefits of C# Records for API Models

C# records were released in C# 9 but we still have barely seen them in the wild. They provide a concise and efficient way to define data types. Records are similar to classes, but they are immutable by default, and they provide built-in equality and hashing implementations. Here are some of the benefits of using C# records for API models:

  1. Immutability: By default, C# records are immutable, which means that their values cannot be changed once they are created. This makes them ideal for modeling data that should not be modified, such as API input or output models. In real world scenarios, you should never change the data you receive(side effect) and you should make a new object for mutation. Immutable data is less prone to errors caused by accidental mutation. When returning your data, you’ll be building up a response which should not be modified either. If you need to make an object that is very similar, you can make a new copy using the with statement:
1
2
3
4
5
6
7
8
public UserDashCount AddToTotal(UserDashCount original, int toAdd)
{
  var newUserDashCount = original with
  {
    total = toAdd + original.total
  };
  return newUserDashCount;
}
  1. Conciseness: C# records can be defined with a single line of code, which makes them very concise and easy to read. This can help reduce the amount of boilerplate code required to define your API models, making your code more maintainable. Due this advantage, we love to colocate all of our API models for a feature in a single file:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
namespace HealthyYou.API.Modules.Analytics.Handlers.UserDashboard
{
  public record UserDashboardRequest(Guid userId, string timeZone): IRequest<ApiResponse<UserDashboardResponse>>;
  public record UserDashboardResponse(UserDashCount journalCount, UserDashCount symptomCount, UserDashCount productCount
  ,IEnumerable<UserDashQuickJournal> quickJournal, UserDashCount genericCounts, IEnumerable<UserDashSymptomOverTime> symptomTrend, UserDashJournalThisWeekCount userProgressThisWeek);
  public record UserDashCount(int total, int last7days);
  public record UserDashQuickJournal(string name, DateTime date, bool hadSymptom);
  public record UserDashSymptomOverTime(int count, int month);
  public record UserDashJournalThisWeekCount(int count);
}
  1. Built-in Equality and Hashing: C# records provide built-in equality and hashing implementations, which makes it easy to compare instances of the same record type. This can be very useful when working with collections of records, such as when deserializing API input models. No longer do you need to compare multiple properties or set up an IEqualityComparer:
1
2
3
   public record UserDashCount(int total, int last7days);
   public bool UserTotalsAndWeeklyMatch(UserDashCount userCount, UserDashCount otherUserDashCount)
          => userCount == otherUserDashCount;
  1. Support for Deconstruction: C# records support deconstruction, which allows you to easily extract the values of a record into separate variables. This can be useful when working with complex API input models that contain many fields.

Performance Considerations of C# Records for API Models

While C# records offer many benefits for API models, it’s important to consider the performance implications of using them. Here are some performance considerations to keep in mind:

  1. Memory Allocation: C# records are immutable by default, which means that they can result in less memory allocation than regular classes. However, this depends on how the records are used in the code. If a record is frequently created and discarded, it can result in more memory allocation than a regular class.

  2. Execution Speed: C# records can be more efficient than regular classes in some scenarios due to their reduced boilerplate code and built-in equality and hashing implementations. However, the actual performance benefits will depend on the specific use case and how the records are used. In some cases, using records instead of regular classes can result in slower performance, particularly when working with large, complex data structures.

Conclusion

C# records offer many benefits for API models, including immutability, conciseness, built-in equality and hashing, support for deconstruction, and interoperability with many serialization formats. If you’ve been using POCOs for your APIs we highly suggest trying out records. We can’t wait to see where Microsoft takes this awesome type in the future.

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy