C#/.NET: for personally identifiable information, use Gaev.Blog.Examples/PiiString.cs at 3.1.1 · gaevoy/Gaev.Blog.Examples
Posted by jpluimers on 2023/10/12
A while ago [Wayback/Archive] Vladimir Gaevoy wrote a great blog post which I bumped into through his tweet [Wayback/Archive] “Blogged: .NET type for personally identifiable information (PII). Working with PII with the help of .NET String is painful. Let’s see the benefits of PiiString as explicit .NET type instead of .NET String #pii #dotnet #gdpr #security “
The tweet does not fully do justice to his blog post [Wayback/Archive] .NET type for personally identifiable information (PII), as the post not only discusses the background (GDPR and other requirements, for instance the [Wayback/Archive] GDPR compliance checklist – GDPR.eu) and the class, but also with examples how to use it for:
- conversion to/from user interface plain text
- hashing to pseudonymized/anonymized form
- encryption for more secure storage
In addition, more examples cover JSON, Entity Framework, [Wayback/Archive] NLog, and [Wayback/Archive] Serilog — simple .NET logging with fully-structured events.
So the PiiString class in [Wayback/Archive] Gaev.Blog.Examples/PiiString.cs at 3.1.1 · gaevoy/Gaev.Blog.Examples sets PII (Personally Identifiable Information) data apart making it is easier to decide where and when to encrypt/hash/anonymise.
The full examples amending the blog post are at [Wayback/Archive] Gaev.Blog.Examples/Gaev.Blog.Examples.PiiTypes at 3.1.1 · gaevoy/Gaev.Blog.Examples.
The PiiString class
In addition to the above, the PiiClass is also a great example of using C# features to write both concise and readable code.
Some examples:
- [Wayback/Archive]
=>operator: Expression body definition – C# reference | Microsoft Docs:
... public override int GetHashCode() => _string.GetHashCode(); ... - [Wayback/Archive] Pattern matching overview: Compare discrete values – C# guide | Microsoft Docs combined with the [Wayback/Archive]
switchexpression – C# reference | Microsoft Docs:
... private static bool AreEqual(PiiString a, PiiString b) => (a, b) switch { (null, null) => true, (null, _) => false, (_, null) => false, (_, _) => a._string.Equals(b._string) }; ... - [Wayback/Archive] Patterns: Declaration and type patterns – C# reference | Microsoft Docs also combined with the [Wayback/Archive]
switchexpression – C# reference | Microsoft Docs:
... public override bool Equals(object obj) => obj switch { PiiString other => AreEqual(this, other), string other => AreEqual(this, new PiiString(other)), _ => false }; ... - [Wayback/Archive] Patterns: Disccard pattern
_– C# reference | Microsoft Docs:
... private static bool AreEqual(PiiString a, PiiString b) => (a, b) switch { (null, null) => true, (null, _) => false, (_, null) => false, (_, _) => a._string.Equals(b._string) }; } ...
- [Wayback/Archive]
??and??=operators – C# reference | Microsoft Docs combined with the [Wayback/Archive]throw: Thethrowexpression – C# Reference | Microsoft Docs:
... public PiiString(string underlyingString) => _string = underlyingString ?? throw new ArgumentNullException(nameof(underlyingString)); ... - [Wayback/Archive] Member access operators and expressions: Null-conditional operators
?.and?[]– C# reference | Microsoft Docs:
... public static implicit operator string(PiiString piiString) => piiString?._string; ... - [Wayback/Archive]
?:operator – C# reference | Microsoft Docs:
... public static implicit operator PiiString(string underlyingString) => underlyingString == null ? null : new PiiString(underlyingString); ...
Some of these bits are more modern than others, but looking at recent C# code I have been seen written, many software developers are either not aware of them or reluctant in using them. Maybe past habits make that harder?
So please look at these links to see how C# has grown over the last 20+ years:
- [Wayback/Archive] The history of C# – C# Guide | Microsoft Docs
- [Wayback/Archive] C# language versioning – C# Guide | Microsoft Docs
- C Sharp (programming language): Versions – Wikipedia
Focus on one combination of things at a time, for instance the beauty of combining pattern matching and switch expressions live in the C# language:
- [Wayback/Archive] What’s new in C# 8.0 – pattern matching enhancements: switch expressions – C# Guide | Microsoft Docs
- [Wayback/Archive] C# 8.0 – Pattern Matching in C# 8.0: The Evolution of Pattern Matching in C# 8.0 | Microsoft Docs
The full class from [Wayback/Archive] https://github.com/gaevoy/Gaev.Blog.Examples/blob/3.1.1/Gaev.Blog.Examples.PiiTypes/PiiString.cs:
using System; namespace Gaev.Blog.Examples; public class PiiString { private readonly string _string; public PiiString(string underlyingString) => _string = underlyingString ?? throw new ArgumentNullException(nameof(underlyingString)); public override string ToString() => _string; public override int GetHashCode() => _string.GetHashCode(); public override bool Equals(object obj) => obj switch { PiiString other => AreEqual(this, other), string other => AreEqual(this, new PiiString(other)), _ => false }; public static bool operator ==(PiiString a, PiiString b) => AreEqual(a, b); public static bool operator !=(PiiString a, PiiString b) => !AreEqual(a, b); public static implicit operator string(PiiString piiString) => piiString?._string; public static implicit operator PiiString(string underlyingString) => underlyingString == null ? null : new PiiString(underlyingString); private static bool AreEqual(PiiString a, PiiString b) => (a, b) switch { (null, null) => true, (null, _) => false, (_, null) => false, (_, _) => a._string.Equals(b._string) }; }
–jeroen







Leave a comment