I flew to Seattle via Sydney and San Francisco. It is a long way to come, and I didn’t sleep very much (hard to get comfortable, plus we had quite a bit of turbulence), though I did end up in a row all to myself (so at least I could stretch out a bit!)
Narelle kindly lent me her Sony WH1000XM4 noise-cancelling headphones for the trip, and they were brilliant. Air travel can be quite noisy, and they did a great job reducing the background noise and were comfortable to wear for extended periods. Do not fear, I will return them when I get home though!
One hiccup on the trip apparently happened while I was recharging my phone at the San Francisco airport while waiting for my connecting flight. The boarding gate opened and I grabbed my phone and charger and jumped in line. It was only later after I’d landed in Seattle and unpacked at the hotel that I discovered that my US to Australian power adapter was missing. It must still be sitting in that power point back in the San Francisco airport lounge. I put a call for help out to my fellow MVPs and not only got offers of spare adapters (huge thanks to Aussie MVP Benjamin Elias), but also some suggestions as to where I might buy a replacement (The Container Store at Bellevue had this adapter, though it is quite a bit more expensive than the $AU6.50 you’d pay for one from Bunnings). Lesson learned: Next time I travel, I’ll pack some spare adapters!
I’m staying at The Residence Inn Seattle Bellevue. It’s really close to the Microsoft campus at Redmond (a nice walk for me when weather permits, and Seattle does have a reputation for inclement weather). Rather than a big multistory hotel, the rooms here are in one of 15 cute houses. Your space is self-contained with cooking facilities included. In previous years I stayed in downtown Bellevue (right near all the shops and services), but I like the change.
Today (Monday) there were some pre-summit sessions on AI (they weren’t under NDA so I can tell you that!), but tomorrow the summit proper begins and by default, all content will be private.
I’m looking forward to learning a heap, catching up with MVP friends and making new connections.
A big thanks to SixPivot for supporting my attendance at the MVP Summit this year.
I’ll start the homeward journey on Friday evening. As nice as it is to be here, it will be good to get home again too.
Amazon affiliate links
]]>This is an experimental feature that is disabled by default. It is an enhancement that source generators will be able to take advantage of. It allows source generators to modify (replace) existing code, rather than just adding new code.
Being an experimental feature, the implementation details are likely to change over time, and there’s no guarantee that it will necessarily ship as a regular feature in the future.
https://github.com/dotnet/roslyn/blob/main/docs/features/interceptors.md
https://github.com/flcdrg/csharp-12/tree/main/08-interceptors
]]>Mark a type, method, or assembly with the ExperimentalAttribute
and the compiler will generate a warning. You will need to explicitly suppress this warning to consume the experimental code.
[Experimental("DAVID01")]
public class ExperimentalClass
{
public void Thing()
{
//
}
}
In some ways, this feels to me like the opposite of the ObsoleteAttribute
.
https://github.com/flcdrg/csharp-12/blob/main/07-experimental/ExperimentalClass.cs
]]>Super-niche, but I guess if you need it, you’ll appreciate it. Previously you’d probably need to resort to using unsafe
code to deal with this.
[System.Runtime.CompilerServices.InlineArray(10)]
public struct InlineArray
{
public int Thing;
}
The compiler now knows this is an array of 10 contiguous elements.
https://github.com/flcdrg/csharp-12/blob/main/06-inline-arrays/InlineArrays.cs
]]>Now you can create aliases for any type - it doesn’t need to have a name. Tuple
s are a great example, but also arrays.
using P = Tuple<string, string, int>;
using C = char[];
https://github.com/flcdrg/csharp-12/blob/main/05-alias/Aliases.cs
]]>A pretty simple addition to the language - you can now provide default values for lambda expression parameters.
var IncrementBy = (int source, int increment = 1) => source + increment;
In the lambda defined above, if you don’t supply the increment
parameter, it defaults to 1
.
Again, interesting, but I’ve not come across a need to use this yet.
https://github.com/flcdrg/csharp-12/blob/main/04-optional-params-lambda/LambdaParameters.cs
]]>ref readonly
modifierA bit more of a niche feature - if you have code that is passing structs by ref
, but you don’t need to (or want to) allow modification of the parameter, you can now indicate it is readonly.
public static void ByRefReadonly(ref readonly Point p)
{
//p = new Point(2, 3);
Console.WriteLine(p);
}
In the code sample above, Point
is a struct or record type. If you uncommented the line then the compiler will emit an error.
Interesting, but I’ve not come across a need to use this yet.
https://github.com/flcdrg/csharp-12/blob/main/02-collection-expressions/CollectionExpressions.cs
]]>You can now use square brackets []
to initialise a collection! Usually square brackets indicate an array, but the collection expression can be assigned to other collection types too.
You can use them to assign values to fields or in method bodies.
private List<int> numbersList = [1, 2, 3, 4, 5];
Like primary constructors, I’ve also found these quite useful in new .NET 8 projects.
https://github.com/flcdrg/csharp-12/blob/main/02-collection-expressions/CollectionExpressions.cs
]]>C# has had primary constructors for records, but now we can use them for classes and structs!
The parameters can be used anywhere within the class - methods, local functions as well as initialising fields and properties.
A primary constructor guarantees that the named parameters have been supplied when an instance is created. You can optionally add other conventional constructors, but they must all call back to the primary constructor using the this(...)
syntax.
public class PrimaryConstructorClass(string name)
{
private string Name { get; init; } = name;
private string Name2 => name;
public void Thing()
{
Console.WriteLine(name);
}
}
I’ve made regular use of these whenever I’ve been working on a .NET 8 project. I’ve found them very useful.
https://github.com/flcdrg/csharp-12/tree/main/01-primary-constructors
]]>Western Digital differentiates its Red NAS drives into three groups/recommended workloads: Red (lighter SOHO), Red Plus (write-intensive), and Red Pro (highest-intensity).
Model number | Product Number | Capacity (TB) | Internal rate (MB/s) | Cache (MB) | RPM | Recording Technology | Approx. Date | Spec sheet | Price (AUD) | Price (USD) |
---|---|---|---|---|---|---|---|---|---|---|
Red | WD40EFAX | 4 | 180 | 256 | 5400 | SMR | Aug-20 | Link | 230 | n/a |
Red Plus | WD40EFZX | 4 | 175 | 128 | 5400 | CMR | Jan-21 | Link | 257 | 111 |
Red Plus | WD40EFPX | 4 | 180 | 256 | 5400 | CMR | Sep-22 | Link | 202 | n/a |
Red Plus | WD60EFPX | 6 | 180 | 256 | 5400 | CMR | Sep-22 | Link | 289 | n/a |
Red Plus | WD80EFZZ | 8 | 185 | 128 | 5640 | CMR | Jan-22 | Link | 313 | n/a |
Red Plus | WD80EFPX | 8 | 215 | 256 | 5640 | CMR | Nov-23 | Link | 308 | 179 |
Red Plus | WD101EFBX | 10 | 215 | 256 | 7200 | CMR | Jan-20 | Link | 398 | 199 |
Red Plus | WD120EFBX | 12 | 196 | 256 | 7200 | CMR | Jan-21 | Link | 515 | n/a |
Red Plus | WD140EFGX | 14 | 210 | 512 | 7200 | CMR | Jan-20 | Link | 658 | n/a |
Red Pro | WD4003FFBX | 4 | 217 | 256 | 7200 | CMR | Sep-20 | Link | 212 | n/a |
Red Pro | WD6003FFBX | 6 | 238 | 256 | 7200 | CMR | Feb-18 | Link | 339 | 204 |
Red Pro | WD8003FFBX | 8 | 235 | 256 | 7200 | CMR | Apr-18 | Link | 404 | 229 |
Red Pro | WD102KFBX | 10 | 256 | 256 | 7200 | CMR | Jan-20 | Link | 465 | 269 |
Red Pro | WD121KFBX | 12 | 240 | 256 | 7200 | CMR | May-19 | Link | 491 | 285 |
Red Pro | WD161KFGX | 16 | 259 | 256 | 7200 | CMR | Sep-20 | Link | 554 | 308 |
Red Pro | WD181KFGX | 18 | 272 | 512 | 7200 | CMR | Sep-20 | Link | 583 | 342 |
Red Pro | WD221KFGX | 22 | 256 | 512 | 7200 | CMR | Jul-22 | Link | 849 | 419 |
I’ve previously bought 4TB drives, but I’m thinking this time I might go for something larger. Because of the RAID configuration I am using, I’ll only be effectively using 4TB of the new drive. But this is planning for the future, as when I buy a subsequent larger drive I’ll then get access to the full capacity of both drives. The ‘Red Plus’ models look fine for my purposes. I don’t need the extra features offered by the ‘Red Pro’ line.
As I write this, the 10G Red Plus WD101EFBX has a discounted price on Amazon US (plus I have some Amazon US gift card credit waiting to be used), so that looks like a good deal. I was originally looking at the 8TB drives, but for only USD20 extra you get another 2TB, so why not?
As a side note, I collated the information in the table above using Excel. Initially, I was going to use a Visual Studio Code extension to paste the Excel content into a Markdown table format, but then formatting the links was not going to be easy. I then realised I could use PowerShell to manage the formatting if I saved the spreadsheet as a .CSV format. PowerShell automation for the win!
eg.
$data = (get-content 'C:\Users\david\OneDrive\Documents\Western Digital Hard disk costs.csv') | ConvertFrom-Csv
$data | ForEach-Object { "| " + $_.'Model number' + " | " + $_.'Product Number' + " | " + $_.'Capacity (TB)' + " | " + $_.'Internal rate (MB/s)' + " | " + $_.'Cache (MB)' + " | " + $_.RPM + " | " + $_.'Recording Technology' + " | " + $_.'Approx. Date' + " | [Link](" + $_.'Spec sheet' + ") | [" + $_.'Price (AUD)' + "](" + $_.'Amazon AU'+ ") | [" + $_.'Price (USD)' + "](" + $_.'Amazon US' + ") |" } | clip
]]>