crispbyte.dev-content.git

git clone https://git.crispbyte.dev/crispbyte.dev-content.git

commit
226b8ec
parent
8689853
author
cheddar
date
2025-08-29 03:24:06 +0200 CEST
Update repo URL
2 files changed,  +70, -1
M content/blog/2024-01-09-02-The_Heart_of_the_Code.md
+1, -1
1@@ -95,7 +95,7 @@ To decode we first read the version byte. If the version is the only version we
2 
3 We read the next two bytes to get the header length. We read that number of bytes to get the encoded headers. We decode the headers, extract `content-length`, and read that number of bytes as the data. Then we pack it up in our `Document` data structure and send it back.
4 
5-I left out the implementation of `unpackHeaders` here because it's mildly confusing if you're not familiar with old .NET patterns. You can find it with the complete [source for this implementation on GitHub](https://github.com/cheddarcrisp/sdbd-demo).
6+I left out the implementation of `unpackHeaders` here because it's mildly confusing if you're not familiar with old .NET patterns. You can find it with the complete [source for this implementation in my git repo](https://forge.crispbyte.dev/sdbd-demo/).
7 ## And now...
8 It's time for a break. I have successfully created a brand new data format. Or at least stitched one together like Frankenstein's monster. I have a working implementation that can encode and decode the format, albeit with only one header implemented.
9 
A content/blog/2025-05-09-New_CS_Patterns.md
+69, -0
 1@@ -0,0 +1,69 @@
 2+---
 3+date: 2025-05-09
 4+title: New C# Patterns
 5+---
 6+One of the reasons I like C# is that it is a constantly evolving language. There are always new patterns emerging that make things just a little easier, just a little more fun. Here's two that I like that I've learned recently.
 7+
 8+## Simpler null checks
 9+This one is a new-ish way to do null checks. Let's say you have this model:
10+```cs
11+public class Book
12+{
13+  public string? Description { get; set; }
14+}
15+```
16+
17+With code something like this:
18+```cs
19+Book? book = GetBookByTitle(title);
20+```
21+
22+You want to do something with the description, but of course only if there is a description to work with. An older way to do this might be:
23+
24+```cs
25+if (book?.Description != null)
26+{
27+  var description = book.Description;
28+
29+  // Use the description
30+}
31+```
32+
33+But because pattern matching works in `if()`, we can do this instead:
34+```cs
35+if (book?.Description is { } description)
36+{
37+  // Use the description
38+}
39+```
40+
41+That empty `{ }` pattern will match any value that is not null. You can combine it with a declaration all in one statement.
42+
43+## (Semi-)implicitly typed collection expression
44+If you use implicit type declarations, you probably write something like this at times:
45+```cs
46+var bookList = new List<Book> { new(...) };
47+```
48+
49+Collection expressions are a nice short way of creating collections. If you want to instantiate a list using a collection expression this is one way of doing it:
50+```cs
51+List<Book> bookList = [new(...)];
52+```
53+
54+But what if you really really want to keep your implicit type declarations? This won't work since the compiler has no idea what the target type should be:
55+```cs
56+var bookList = [new(...)];
57+```
58+
59+If you use this, it will work again:
60+```cs
61+var bookList = (List<Book>)[new(...)];
62+```
63+
64+That looks like casting, but what are we even casting? What's going on here? What's the benefit? It saves a few characters but is it worth using a construct that looks so strange and feels so wrong?
65+
66+_Note: This is as of .NET 9. Future behavior can obviously change._
67+
68+Yes it is. At least for lists, it turns out that `(List<T>)[]` is faster than `new List<T> { }`. For nano-second scale levels of faster. Even better, if you can use `(IReadOnlyCollection<T>)[]` it's a little faster still.
69+
70+Trust me. If you use this style long enough, it starts to look normal.