The Curious Engineer

All blogs / C# / .NET

Jon Skeet's coding blog

codeblog.jonskeet.uk

C# / .NETSoftware / engineering practiceEngineering blogs

Posts
491 from 15 Sep 2005 to 14 Aug 2026
Posting
now and then (5 in the last year)
Kind
personal blog
Feed
https://codeblog.jonskeet.uk/feed/

2026 4

  1. Scratch a simple data model, find a complex one
  2. Forking an open source project
  3. Election 2029: Load Testing
  4. Election 2029: Models and Reality

2025 11

  1. Changing Immutable Collections
  2. Records and the ‘with’ operator, redux
  3. Unexpected inconsistency in records
  4. Election 2029: Postcodes
  5. Records and Collections
  6. Election 2029: Storage
  7. Election 2029: Data Models
  8. Election 2029: Technical overview
  9. Election 2029: Introduction
  10. Election 2029: The Impossible Exception – Solved
  11. Election 2029: An Impossible Exception

2024 7

  1. When Abstractions Break
  2. No, the bug is in your code (and mine)
  3. Abstraction: Introduction
  4. Lessons from election night
  5. Building an election website
  6. DigiMixer – the app
  7. DigiMixer: Protocols

2023 3

  1. Variations in the VISCA protocol
  2. SSC Protocol
  3. DigiMixer: Introduction to digital mixers

2022 8

  1. Handling times for an EV charger
  2. Introduction to DigiMixer
  3. Taking .NET MAUI for a spin
  4. What’s up with TimeZoneInfo on .NET 6? (Part 2)
  5. Diagnosing an ASP.NET Core hard crash
  6. Displaying NDI sources on Stream Decks
  7. Diagnosing a VISCA camera issue
  8. What’s up with TimeZoneInfo on .NET 6? (Part 1)

2021 4

  1. Book updates for July 2021
  2. New book: Software Mistakes and Tradeoffs
  3. Playing with an X-Touch Mini controller using C#
  4. OSC mixer control in C#

2020 8

  1. VISCA camera control in C#
  2. A Tour of the .NET Functions Framework
  3. Posting to wordpress.com in code
  4. Travis logs and .NET Core console output
  5. V-Drum Explorer: Blazor and the Web MIDI API
  6. V-Drum Explorer: Planning notes for MVVM
  7. V-Drum Explorer: Memory and 7-bit addressing
  8. New and improved JonSkeet.DemoUtil

2019 11

  1. Reducing my international speaking
  2. V-Drum Explorer: MIDI interface
  3. V-Drum Explorer: Introduction
  4. Options for .NET’s versioning issues
  5. Why I don’t start versions at 0.x any more
  6. Using “git bash” from AppVeyor
  7. Versioning limitations in .NET
  8. Lying to the compiler
  9. Storing UTC is not a silver bullet
  10. Hosting ASP.NET Core behind https in Google Kubernetes Engine
  11. NullableAttribute and C# 8

2018 5

  1. Farewell, Daisy Shipton
  2. First steps with nullable reference types
  3. Backward compatibility and overloading
  4. Stack Overflow Culture
  5. Implementing IXmlSerializable in readonly structs

2017 13

  1. NuGet package statistics
  2. Diagnosing a Linux-only unit test failure
  3. Diagnosing a VS-only build problem
  4. Diagnosing a corner-case tooling bug
  5. Diagnosing a single slow test
  6. Diagnosing slow tests (again)
  7. Diagnostics everywhere!
  8. Using .NET Core 2.0 SDK on Travis
  9. Upcoming speaking engagements
  10. Imposter Syndrome (part 2)
  11. Imposter syndrome (part 1)
  12. Surprise! Creating an instance of an open generic type
  13. All about java.util.Date

2016 6

  1. Diversity and speaking engagements
  2. Thoughts on privilege (moved!)
  3. Tracking down a performance hit
  4. Versioning conundrum for Noda Time – help requested
  5. Ultimate Man Cave: voice automation for my shed
  6. To base() or not to base(), that is the question

2015 7

  1. “Sideways overriding” with partial methods
  2. Backwards compatibility is (still) hard
  3. Common mistakes in date/time formatting and parsing
  4. Precedence: ordering or grouping?
  5. Backward compatibility pain
  6. Clean event handler invocation with C# 6
  7. C# 7 feature request #1… extension attributes

2014 19

  1. C# 6 in action
  2. When is an identifier not an identifier? (Attack of the Mongolian Vowel Separator)
  3. When is a string not a string?
  4. Writing and speaking update
  5. Violating the “smart enum” pattern in C#
  6. The mysteries of BCL time zone data
  7. When is a constant not a constant? When it’s a decimal…
  8. The BobbyTables culture
  9. Object pooling and thread safety
  10. New blog hosting
  11. Micro-optimization: the surprising inefficiency of readonly fields
  12. Anti-pattern: parallel collections
  13. Diagnosing Portable Class Libraries
  14. Extension methods, explicitly implemented interfaces and collection initializers
  15. Quick brainteaser
  16. C# 6: First reactions
  17. How many 32-bit types might we want?
  18. Diagnosing issues with reversible data transformations
  19. A tale of two puzzles

2013 9

  1. Career and skills advice
  2. Casting vs “as” – embracing exceptions
  3. Array covariance: not just ugly, but slow too
  4. But what does it all mean?
  5. Book Review: Async in C# 5.0
  6. New tool to play with: SemanticMerge
  7. The Open-Closed Principle, in review
  8. C# in Depth 3rd edition available for early access, plus a discount code…
  9. Fun with Object and Collection Initializers

2012 17

  1. Stack Overflow question checklist
  2. Noda Time v1.0 released
  3. How can I enumerate thee? Let me count the ways…
  4. Stack Overflow and personal emails
  5. The future of “C# in Depth”
  6. The perils of conditional mutability
  7. More fun with DateTime
  8. Type initializer circular dependencies
  9. Diagnosing weird problems – a Stack Overflow case study
  10. Eduasync 20: Changes between the VS11 Preview and the Visual Studio 11 Beta
  11. Subtleties in API design – member placement
  12. Currying vs partial function application
  13. Eduasync part 19: ordering by completion, ahead of time…
  14. Coding in the style of Glee
  15. CodeMash 2012 report
  16. Eduasync part 18: Changes between the Async CTP and the Visual Studio 11 Preview
  17. Awaiting CodeMash 2012

2011 57

  1. Book Review: Fluent C# (Rebecca Riordan, Sams)
  2. Eduasync part 17: unit testing
  3. Eduasync part 16: Example of composition: majority voting
  4. Eduasync part 15: implementing COMEFROM with a horrible hack
  5. Laptop review: Kobalt G150
  6. Upcoming speaking engagements
  7. Optimization and generics, part 2: lambda expressions and reference types
  8. Optimization and generics, part 1: the new() constraint (updated: now with CLR v2 results)
  9. Speaking engagement: Progressive .NET, London, September 7th
  10. Eduasync part 14: Data passing in coroutines
  11. Eduasync part 13: first look at coroutines with async
  12. Eduasync part 12: Observing all exceptions
  13. Eduasync part 11: More sophisticated (but lossy) exception handling
  14. LINQ To Objects and the performance of nested “Where” calls
  15. Eduasync part 10: CTP bug – don’t combine multiple awaits in one statement…
  16. Eduasync part 9: generated code for multiple awaits
  17. Eduasync part 8: generated code from a complex async method
  18. Eduasync part 7: generated code from a simple async method
  19. Eduasync part 6: using the infrastructure manually
  20. Eduasync part 5: making Task awaitable
  21. Eduasync part 4: Filling in AsyncTaskMethodBuilder
  22. Eduasync part 3: the shape of the async method / awaitable boundary
  23. Eduasync part 2: the shape of the caller / async method boundary
  24. Eduasync part 1: introduction
  25. Of memory and strings
  26. Edulinq – the e-book
  27. Reimplementing LINQ to Objects: Part 45 – Conclusion and List of Posts
  28. Reimplementing LINQ to Objects: Part 44 – Aspects of Design
  29. Reimplementing LINQ to Objects: Part 43 – Out-of-process queries with IQueryable
  30. C# in Depth 2nd edition: now available in mobi/epub (Kindle) format
  31. Reimplementing LINQ to Objects: Part 42 – More optimization
  32. Reimplementing LINQ to Objects: Part 41 – How query expressions work
  33. Reimplementing LINQ to Objects: Part 40 – Optimization
  34. Reimplementing LINQ to Objects: Part 39 – Comparing implementations
  35. Reimplementing LINQ to Objects: Part 38 – What’s missing?
  36. Reimplementing LINQ to Objects: Part 37 – Guiding principles
  37. Gotcha around iterator blocks
  38. Reimplementing LINQ to Objects: Part 36 – AsEnumerable
  39. Reimplementing LINQ to Objects: Part 35 – Zip
  40. Reimplementing LINQ to Objects: Part 34 – SequenceEqual
  41. Reimplementing LINQ to Objects: Part 33 – Cast and OfType
  42. Reimplementing LINQ to Objects: Part 32 – Contains
  43. Reimplementing LINQ to Objects: Part 31 – ElementAt / ElementAtOrDefault
  44. Reimplementing LINQ to Objects: Part 30 – Average
  45. Reimplementing LINQ to Objects: Part 29 – Min/Max
  46. Reimplementing LINQ to Objects: Part 28 – Sum
  47. Reimplementing LINQ to Objects: Part 27 – Reverse
  48. Reimplementing LINQ to Objects: Part 26d – Fixing the key selectors, and yielding early
  49. Reimplementing LINQ to Objects: Part 26c – Optimizing OrderedEnumerable
  50. Reimplementing LINQ to Objects: Part 26b – OrderBy{,Descending}/ThenBy{,Descending}
  51. Reimplementing LINQ to Objects: Part 26a – IOrderedEnumerable
  52. Reimplementing LINQ to Objects: Part 25 – ToDictionary
  53. Reimplementing LINQ to Objects: Part 24 – ToArray
  54. Reimplementing LINQ to Objects: Part 23 – Take/Skip/TakeWhile/SkipWhile
  55. Reimplementing LINQ to Objects: Part 22 – GroupJoin
  56. Reimplementing LINQ to Objects: Part 21 – GroupBy
  57. Reimplementing LINQ to Objects: Part 20 – ToList

2010 65

  1. Reimplementing LINQ to Objects: Part 19 – Join
  2. Reimplementing LINQ to Objects: Part 18 – ToLookup
  3. Reimplementing LINQ to Objects: Part 17 – Except
  4. Reimplementing LINQ to Objects: Part 16 – Intersect (and build fiddling)
  5. Reimplementing LINQ to Objects: Part 15 – Union
  6. Reimplementing LINQ to Objects: Part 14 – Distinct
  7. Reimplementing LINQ to Objects: Part 13 – Aggregate
  8. Reimplementing LINQ to Objects: Part 12 – DefaultIfEmpty
  9. Reimplementing LINQ to Objects: Part 11 – First/Single/Last and the …OrDefault versions
  10. Reimplementing LINQ to Objects: Part 10 – Any and All
  11. Reimplementing LINQ to Objects: Part 9 – SelectMany
  12. Reimplementing LINQ to Objects: Part 8 – Concat
  13. Reimplementing LINQ to Objects: Part 7 – Count and LongCount
  14. Reimplementing LINQ to Objects: Part 6 – Repeat
  15. Reimplementing LINQ to Objects: Part 5 – Empty
  16. Reimplementing LINQ to Objects: Part 4 – Range
  17. Reimplementing LINQ to Objects: Part 3 – “Select” (and a rename…)
  18. A Model/View to a Kill (Naked came the null delegate, part 5)
  19. Creative freedom, control, and the balance of power
  20. The joys of date/time arithmetic
  21. The importance of context, and a question of explicitness
  22. Multiple exceptions yet again… this time with a resolution
  23. Using extension method resolution rules to decorate awaiters
  24. Propagating multiple async exceptions (or not)
  25. Configuring waiting
  26. Evil code – overload resolution workaround
  27. Dreaming of multiple tasks again… with occasional exceptions
  28. C# in Depth 2nd edition: ebook available, but soon to be updated
  29. Control flow redux: exceptions in asynchronous code
  30. Dreaming of multiple tasks
  31. C# 5 async: experimenting with member resolution (GetAwaiter, BeginAwait, EndAwait)
  32. C# 5 async: investigating control flow
  33. C# 5 async and choosing terminology: why I’m against “yield”
  34. Initial thoughts on C# 5’s async support
  35. Overloading and generic constraints
  36. The curious case of the publicity-seeking interface and the shy abstract class
  37. Book Review: Effective C# (2nd edition) by Bill Wagner
  38. Non-iterable collection initializers
  39. You are all individuals! (I’m not…)
  40. Reply to a reply… tweaking refactoring
  41. Query expression syntax: continuations
  42. Mini-post: abstractions vs repetition; a driving analogy
  43. Very quick interlude: I know that CAPTCHAs aren’t working on this blog if you’re using Chrome
  44. Reimplementing LINQ to Objects: Part 2 – “Where”
  45. Reimplementing LINQ to Objects: Part 1 – Introduction
  46. Presentation preparation
  47. Don’t let this get away
  48. Code and data
  49. Writing the perfect question
  50. Reflecting on presentation skills: The Guathon, August 13th 2010
  51. There’s a hole in my abstraction, dear Liza, dear Liza
  52. Iterate, damn you!
  53. Degrees of reality in sample code
  54. How many Jedi?
  55. Epicenter 2010: quick plug and concessionary tickets
  56. How do we raise our game?
  57. Book review: “Confessions of a public speaker” by Scott Berkun
  58. Documentation with Sandcastle – a notebook
  59. Just how lazy are you?
  60. Speaking of which…
  61. Optimisations in LINQ to Objects
  62. The irritation of bad names
  63. Type initialization changes in .NET 4.0
  64. LINQ to Rx: second impressions
  65. First encounters with Reactive Extensions

2009 51

  1. “Magic” null argument testing
  2. Custom value types are like buses
  3. Where do you benefit from dynamic typing?
  4. Just how spiky is your traffic?
  5. Noda Time gets its own blog
  6. Noda Time is born
  7. What’s in a name (again)?
  8. Revisiting randomness
  9. OMG Ponies!!! (Aka Humanity: Epic Fail)
  10. Contract classes and nested types within interfaces
  11. MVP Again
  12. Migrating from Visual Studio 2010 beta 1 to beta 2 – solution file change required
  13. Iterating atomically
  14. Generic collections – relegate to an appendix?
  15. MVP no more
  16. An object lesson in blogging and accuracy; was: Efficient “vote counting” with LINQ to Objects – and the value of nothing
  17. API design: choosing between non-ideal options
  18. Generic constraints for enums and delegates
  19. Recent activities
  20. The “dream book” for C# and .NET
  21. Tricky decisions… Code Contracts and Parallel Extensions in C# in Depth 2nd edition
  22. Evil Code of the Day: variance and overloading
  23. Non-review: The Data Access Handbook by John Goodson and Robert A. Steward
  24. Faking COM to fool the C# compiler
  25. Books going cheap
  26. Evil code of the day
  27. OS Jam at Google London: C# 4 and the DLR
  28. Dynamic type inference and surprising possibilities
  29. Reasons for voting on questions and answers
  30. A different approach to inappropriate defaults
  31. Language proliferation
  32. RFC: C# in Depth 2nd edition, proposed changes and additions
  33. Go on, ask me anything
  34. Buffering vs streaming benchmark: first results
  35. Benchmarking IO: buffering vs streaming
  36. Breaking Liskov
  37. Book Review: C# 2008 and 2005 Threaded Programming: Beginner’s Guide
  38. Current book project: Real World Functional Programming
  39. What’s in a name?
  40. Answering technical questions helpfully
  41. Benchmarking: designing an API with unusual goals
  42. For vs Foreach on arrays and lists
  43. Programming is hard
  44. Benchmarking made easy
  45. RFID: What I really want it for
  46. Designing LINQ operators
  47. Quick rant: why isn’t there an Exception(string, params object[]) constructor?
  48. Stack Overflow reputation and being a micro-celebrity
  49. Stack Overflow Reputation Tool now online
  50. Horrible grotty hack: returning an anonymous type instance
  51. You don’t have to use query expressions to use LINQ

2008 96

  1. New version of Data Structures and Algorithms book now online
  2. Value types and parameterless constructors
  3. Redesigning System.Object/java.lang.Object
  4. List of talks now up on C# in Depth site
  5. The Snippy Reflector add-in
  6. Copenhagen C# talk videos now up
  7. November 19th: London .NET User Group, Push LINQ!
  8. How much do you care about blog tags?
  9. Jaffa bugs
  10. .NET 4.0’s game-changing feature? Maybe contracts…
  11. Returning from Copenhagen
  12. C# 4.0: dynamic ?
  13. What other Enumerable extension methods would you like to see?
  14. DeveloperDeveloperDeveloper: Registration now open (hurry!)
  15. Mapping from a type to an instance of that type
  16. Why boxing doesn’t keep me awake at nights
  17. DotNetRocks interview
  18. Non-nullable reference types
  19. Formatting strings
  20. Copenhagen talk on C# – what do you want to hear about?
  21. New addiction: Stack Overflow
  22. Book Review: Programming C# 3.0 by Jesse Liberty and Donald Xie
  23. Book review: Pro LINQ – Language Integrated Query in C# 2008, by Joe Rattz
  24. Book reviews – what do you look for?
  25. Logging enumeration flow
  26. Annoying IE8 beta 2 CSS breakage
  27. With apologies to Flanders and Swann
  28. Developer Developer Developer day 7: voting now open
  29. Data Structures and Algorithms: new free eBook available (first draft)
  30. Core .NET refcard now available
  31. Lessons learned from Protocol Buffers, part 4: static interfaces
  32. Lessons learned from Protocol Buffers, part 3: generic type relationships
  33. Holiday blogging
  34. Lessons learned from Protocol Buffers, part 2: self-referential generic types
  35. Lessons learned from Protocol Buffers, part 1: messages, builders and immutability
  36. Pre-Copenhagen interview
  37. Speaking in Copenhagen, October 30th
  38. Visual Studio 2008 SP1 and .NET 3.5 SP1 both out now
  39. C# refcard now available (free) from DZone
  40. Thank you, JetBrains: dotTrace rocks
  41. Making reflection fly and exploring delegates
  42. Making the most of generic type inference
  43. Book review: Accelerated C# 2008 by Trey Nash
  44. Calling Trey Nash…
  45. Judging a book by its cover (or title)
  46. Google release protocol buffers as an open source project
  47. The trouble with book reviews
  48. Manning book draw
  49. Blog update
  50. Automatic lambda expressions
  51. I’m Sorry, I Haven’t a Cluestick
  52. Guest post: Joe Albahari reviews C# in Depth
  53. Parallel Extensions June CTP
  54. More parallelisation fun: Conway’s Game of Life
  55. Mandelbrot revisited – benchmark edition
  56. The Beauty of Closures
  57. C# in Depth – it’s really real
  58. Programming “in” a language vs programming “into” a language
  59. Book review: User Interface Design for Programmers (Joel Spolsky)
  60. Critical dead-weight
  61. Google, here I come!
  62. We’ve shipped! C# in Depth is out now (ebook)
  63. Book review: C# 3.0 in a Nutshell
  64. Range variables – is it just me that thinks they’re different?
  65. PostSharp and iterator blocks – a beautiful combination
  66. Book review: Head First C#
  67. Book review/preview: “C# Query Expressions And Supporting Features in C# 3.0” (Eckel/King)
  68. C# 4: Immutable type initialization
  69. Reviewing other C# books?
  70. Reading Geek Night 2 – March 28th
  71. C# 4, part 5: Other bits and bobs which probably don’t merit inclusion
  72. The value of a language specification
  73. C# 4 idea: Iterator blocks and parameter checking
  74. Trivia: when is a no-op not a no-op?
  75. Odd query expressions
  76. Implementing deferred execution, and a potential trap to avoid
  77. Data pipelines as a conceptual stepping stone to higher order functions
  78. Visualising the Mandelbrot set with LINQ – yet again
  79. LambdaExpression – source code would be nice
  80. Visual LINQ: Watch query expressions as they happen!
  81. My first screencast – automatic properties
  82. Human LINQ
  83. Language design, when is a language “done”, and why does it matter?
  84. C# 4, part 4: My manifesto and wishlist
  85. Macros, and languages within languages
  86. C# 4, part 3: Ideas from Microsoft
  87. C# 4, part 2: Ideas from other community members
  88. A simple extension method, but a beautiful one
  89. C# 4, part 1: Looking back at the past
  90. Immutability and inheritance
  91. Bridging gaps, and finding my role
  92. Types of Parallelism
  93. Extension methods on lamdba expressions don’t work, unfortunately
  94. LINQ to Objects – not just for in-memory collections
  95. “Push” LINQ revisited – next attempt at an explanation
  96. Last post about the book (nearly) and a new source of information…

2007 46

  1. Boxing day
  2. C# in Depth: All chapters available in MEAP!
  3. Covariance and void return types
  4. Refactris
  5. A cautionary parallel tale: ordering isn’t simple
  6. Group pipelining returns: new and improved design
  7. Don’t call us, we’ll call you – push enumerators
  8. VS2005 and VS2008 co-existence
  9. Visual Studio 2008 is out now!
  10. C# in Depth: Chapters 8 and 9 now in MEAP
  11. Getting started with F#
  12. Joe Duffy speaks as well as he writes
  13. I love LINQ: Simplifying a tedious task
  14. Book news
  15. C# in Depth: Chapters 6 and 7 now in MEAP
  16. Fun with captured variables
  17. LINQ to Silliness: Generating a Mandelbrot with parallel potential
  18. Yeehaa! Framework source code, here we come!
  19. C# in Depth: Chapters 4 and 5 now available in MEAP
  20. Announcement: Partnership with Iterative Training
  21. Java isn’t an acronym
  22. Announcing “C# in Depth”
  23. How does everyone else mock web services?
  24. Writing user interfaces
  25. Extension methods and .NET 2.0
  26. Is C# 3 too big to learn from scratch?
  27. Smart enumerations
  28. Visual Studio 2008 (Orcas) Beta 2 Released
  29. Overloading == to return a non-boolean
  30. Who do the “stars” look up to?
  31. Why hasn’t Microsoft bought JetBrains yet?
  32. Implementing Ruby on .NET, and the importance of specifications
  33. Writing is hard work: what I’ve been up to recently…
  34. Non-volatile reads and Interlocked, and how they interact
  35. The CCR (Concurrency and Coordination Runtime) is out – apparently!
  36. Sheer Evil: Rethrowing exceptions in Java
  37. Visual Studio 2005 vs Eclipse – again, but this time with ReSharper…
  38. Wacky Ideas 3: Object life-cycle support
  39. Wacky Ideas 2: Class interfaces
  40. Wacky Ideas 1: Inheritance is dead, long live mix-ins!
  41. Wacky Ideas – Introduction
  42. What would make a good Java book?
  43. Build and config friendliness counts
  44. New blog, new project
  45. Wii and MythTV: The future of my living room?
  46. Groovy 1.0 released

2006 23

  1. Everything old is new again
  2. The CLI memory model, and specific specifications
  3. Unit tests rock, I suck, news at 11
  4. Why development is still hard in 2006
  5. Opening up the .NET framework source code
  6. An alternative CV strategy
  7. Elegant comparisons with the null coalescing operator
  8. Broken windows and unit testing
  9. The 7 Deadly Sins of Software Development
  10. Father of Three
  11. PowerShell in Action
  12. Groovy
  13. Faith blog
  14. MSDN Product Feedback Center – use it!
  15. Vista and External Memory Devices
  16. Inheritance Tax
  17. Worst product names ever?
  18. Bringing Subversion and Fitnesse together
  19. List.ForEach vs foreach(…)
  20. Singletons and inheritance
  21. ICloneable? Not quite…
  22. Nice doc comment idea
  23. Enhanced enums in C#

2005 21

  1. Deadlock detection – finally released
  2. Pedantry – how much is too much?
  3. What kind of deadlock prevention do you want?
  4. Visual Studio vs Eclipse
  5. RSS for my articles
  6. New (to me) threading paradigms
  7. System.Random (and java.util.Random)
  8. Adverts on my C# article pages?
  9. Code formatter online
  10. CLI spec mistake with unboxing and enums
  11. CSS in the blog
  12. Book idea
  13. Yay! I’m not the only one who doesn’t like designers…
  14. Corner cases in Java and C#
  15. A short case study in LINQ efficiency
  16. Problems posting comments?
  17. Nasty generics restrictions
  18. Improvement to extension method syntax
  19. LINQ, DLinq, XLinq and C# 3.0
  20. Overuse of regular expressions
  21. Welcome!