{
  "id": 6341551,
  "title": ".NET 10 Generic Math Shift Masking: Catch Overshifts That Now Wrap",
  "url": "https://urgent.news/2026/09/08/net-10-generic-math-shift-masking-catch-overshifts-that-now-wrap",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-08T22:13:40.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/ssukhpinder/net-10-generic-math-shift-masking-catch-overshifts-that-now-wrap-1612"
  },
  "original_language": "en",
  "account": ".NET 10 introduces a change in the behavior of generic math shift operators, such as left shift, unsigned right shift, and signed right shift, for small integer types like byte, char, sbyte, short, and ushort. Previously, on .NET 9, these operators returned zero for oversized shifts within the type's width, but on .NET 10, they now mask the shift amount according to the operand's width. This means that for an eight-bit byte, a count of 8 becomes 0 and 9 becomes 1 after masking, leading to a shift by zero or one position. The change is specific to operators dispatched through generic math and only affects these small built-in types. The runtime now behaves consistently, but it is up to the application to decide whether an oversized count is valid. The source code provided demonstrates the boundary between .NET 9 and .NET 10 by running tests under both runtimes and checking the results for byte and byte unsigned right shift operations. The sample shows that .NET 10 produces different results compared to .NET 9 for oversized shifts. To address this change, developers can either reject oversized shift counts or normalize them using modulo for cyclic counts. Implementing explicit policies like rejection or modulo normalization makes the behavior more transparent and easier to audit across different runtimes.",
  "summary": ".NET 10 generic math shift masking changes the result of some oversized shifts on small integer types. If a helper uses IShiftOperators<T, int, T> , code such as a generic byte << 8 can return 1 on .NET 10 where it returned 0 on .NET 9. That is a narrow behavioral change, but it can matter in bit-field parsing, binary protocols, compact identifiers, and any test fixture that treats an…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}