Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
160273 stories
·
33 followers

Boxed In: Working With Azure's Region Constraints Instead of Getting Surprised By Them

1 Share
If you've tried to spin up a VM in East US and gotten slapped with an AllocationFailed error, or watched a GPU quota request sit in "In Review" for three weeks, you already know where this post is going. Azure capacity constraints aren't a rumor anymore...they're a planning input. And most of the guidance out there stops at "just use multiple regions," which is true and also almost useless without the mechanics behind recommendation. This is the post I wish I could hand every client who asks...

Read the whole story
alvinashcraft
55 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Grand Central Station: Why BLoC, Riverpod, and BlocSignal Are Now True Peers

1 Share

By Randal L. Schwartz, and a few million TPU cycles

Motto: "With the rigor of Bloc and the flex and speed of Signal"

The State Management Balkanization Is Officially Over

If you have spent any time in the Flutter community over the past eight years, you have witnessed the great "State Management Wars."

On one track sat Classic BLoC: strict, battle-tested, enterprise-grade, but heavily reliant on asynchronous Dart Stream microtasks. On an adjacent track sat Riverpod: offering compile-time safety and declarative dependency graph plumbing, but steering increasingly toward mandatory code generation and build_runner iteration tax. On the newest high-speed track arrived Signals: offering raw sub-microsecond synchronous reactivity and fine-grained UI rebuilding.

For years, choosing a state management library felt like choosing an isolated railroad network. If an engineering team built their core application with flutter_bloc or flutter_riverpod and wanted to take advantage of synchronous Signals for a new high-frequency feature, conventional wisdom dictated a painful choice: either undertake a risky, multi-month rewrite or suffer through clunky, second-class adapter boilerplate.

Traditional "interop" packages in our ecosystem have almost always been an afterthought—awkward, leaky wrappers designed to tolerate legacy code until someone finds the budget to delete it.

Today, with the release of bloc_signals_bloc and a major update to bloc_signals_riverpod, we are fundamentally changing that paradigm.

BLoC, Riverpod, and BlocSignal are no longer competing silos. They are first-class, bidirectional peers.

🏛️ The Metaphor: Grand Central State Terminal

Imagine walking into a majestic railway terminal—vaulted glass arches overhead, golden sunbeams cutting through the air, and railway block signal gantries glowing bright green.

Pulling up to the platforms side by side on three parallel steel tracks are three distinct locomotives:

  🚂 Track 1: Classic BLoC (The Steam Locomotive) ─────┐
                                                        │
  🚚 Track 2: Riverpod (The Heavy Freight Hauler) ──────┼──► [ Grand Central State Terminal ] ◄──► Synchronous Signals
                                                        │
  🚄 Track 3: BlocSignal (The High-Speed Maglev) ───────┘
  1. The Steam Locomotive (Classic BLoC): The venerable, heavy-duty iron horse. Explicit event-to-state contracts, distinct mechanical pistons, and a proven safety record powering thousands of enterprise apps.
  2. The Heavy Freight Locomotive (Riverpod): The industrial logistics powerhouse. Unmatched at hauling complex dependency graph freight, managing scoped provider routes, and coordinating global-to-local supply chains.
  3. The High-Speed Maglev (BlocSignal): The aerodynamic bullet train. Zero microtask drag, instant sub-microsecond acceleration, streamless execution, and fine-grained reactivity.

In Grand Central Terminal, the tracks do not collide, and no train is treated as second-class rolling stock. Platforms sit adjacent to each other. Passengers (state, events, actions) walk across the concourse between trains with zero baggage check fees, zero customs delays, and zero microtask penalties.

⚡ What Makes Them "True Peers"?

In most architectures, adapting one state container to another requires wrapping everything in custom StreamController instances, registering manual listener callbacks, and remembering to clean up disposers to prevent memory leaks.

Under BlocSignal, peer integration is completely bidirectional, lifecycle-managed, and type-safe:

From Target ➔ To Target How It Works Developer Ergonomics
Classic BLoC ➔ BlocSignal classicBloc.toBlocSignal() Exposes synchronous .state signal + forwards .add(event)
Classic Cubit ➔ CubitSignal classicCubit.toBlocSignal() Exposes synchronous .state signal + typed .cubit methods
Riverpod Provider ➔ BlocSignal provider.toBlocSignal(ref) Exposes synchronous .state signal + typed .notifier methods + auto-disposal
BlocSignal ➔ Classic BLoC blocSignal.toClassicBloc() Direct drop-in for legacy flutter_bloc BlocBuilder / BlocListener
CubitSignal ➔ Classic Cubit cubitSignal.toClassicCubit() Direct drop-in for legacy flutter_bloc widgets
BlocSignal / CubitSignal ➔ Riverpod blocSignal.toProvider() Direct drop-in for Riverpod ref.watch and ref.read
Riverpod AsyncValue ↔ Signals AsyncState .toAsyncState() / .toAsyncValue() Seamless mapping across sealed loading/error/data states

Let's put this into practice with a concrete example.

☕ The "Grand Central Triple Counter" (Least Boilerplate Possible)

What does it look like when all three state engines work together in a single Flutter screen?

Here is a complete, runnable Flutter app where a Classic BLoC, a Riverpod Notifier, and a Modern CubitSignal live side by side. Each manages its own domain state, yet they compose synchronously into a unified Grand Total using a single computed signal in under 65 lines of code:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:bloc/bloc.dart' as bloc_lib;
import 'package:bloc_signals/bloc_signals.dart';
import 'package:bloc_signals_bloc/bloc_signals_bloc.dart';
import 'package:bloc_signals_riverpod/bloc_signals_riverpod.dart';
import 'package:signals_flutter/signals_flutter.dart';

// 🚂 1. CLASSIC BLOC: The Steam Engine (Explicit Event -> State)
class ClassicCounterBloc extends bloc_lib.Bloc<int, int> {
  ClassicCounterBloc() : super(0) {
    on<int>((event, emit) => emit(state + event));
  }
}

// 🚚 2. RIVERPOD: The Freight Hauler (Declarative Notifier)
class RiverpodCounter extends Notifier<int> {
  @override
  int build() => 0;
  void increment() => state++;
}
final riverpodCountProvider =
    NotifierProvider<RiverpodCounter, int>(RiverpodCounter.new);

// 🚄 3. BLOCSIGNAL: The High-Speed Maglev (Synchronous Signals)
class ModernSignalCubit extends CubitSignal<int> {
  ModernSignalCubit() : super(initialState: 0);
  void increment() => emit(stateValue + 1);
}

// 🏛️ GRAND CENTRAL TERMINAL: The Peer Counter Screen
class GrandCentralCounterScreen extends ConsumerWidget {
  const GrandCentralCounterScreen({
    super.key,
    required this.classicBloc,
    required this.signalCubit,
  });

  final ClassicCounterBloc classicBloc;
  final ModernSignalCubit signalCubit;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 🔀 Adapt BLoC and Riverpod into first-class signal peers:
    final blocPeer = classicBloc.toBlocSignal();
    final riverpodPeer = riverpodCountProvider.toBlocSignal(ref);

    // ⚡ Synchronously compute the Grand Total across all three rail lines:
    final grandTotal = computed(
      () => blocPeer.state() + riverpodPeer.state() + signalCubit.state(),
    );

    return Scaffold(
      appBar: AppBar(title: const Text('Grand Central State Terminal')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('🚂 Classic BLoC Count: ${blocPeer.stateValue}'),
            Text('🚚 Riverpod Count: ${riverpodPeer.stateValue}'),
            Text('🚄 BlocSignal Count: ${signalCubit.stateValue}'),
            const Divider(height: 32, indent: 64, endIndent: 64),
            // Reactively updates the instant ANY train leaves its station!
            Watch((context) => Text(
              '🏁 Grand Total: ${grandTotal()}',
              style: Theme.of(context).textTheme.headlineMedium,
            )),
          ],
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton.extended(
            heroTag: 'bloc',
            label: const Text('+1 BLoC'),
            onPressed: () => blocPeer.add(1),
          ),
          const SizedBox(width: 8),
          FloatingActionButton.extended(
            heroTag: 'riverpod',
            label: const Text('+1 Riverpod'),
            onPressed: () => riverpodPeer.notifier.increment(),
          ),
          const SizedBox(width: 8),
          FloatingActionButton.extended(
            heroTag: 'signal',
            label: const Text('+1 Signal'),
            onPressed: () => signalCubit.increment(),
          ),
        ],
      ),
    );
  }
}

void main() {
  // Initialize classic BLoC and modern CubitSignal instances:
  final classicBloc = ClassicCounterBloc();
  final signalCubit = ModernSignalCubit();

  runApp(
    // Wrap with Riverpod's ProviderScope at the application root:
    ProviderScope(
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        home: GrandCentralCounterScreen(
          classicBloc: classicBloc,
          signalCubit: signalCubit,
        ),
      ),
    ),
  );
}

Why This Integration Is Revolutionary:

  1. Bidirectional Control via Typed Getters:
    • blocPeer.add(1) dispatches directly into the underlying classic Bloc event queue.
    • riverpodPeer.notifier.increment() calls the underlying RiverpodCounter methods with full type safety.
    • signalCubit.increment() triggers immediate synchronous signal emission.
  2. Lifecycle Auto-Wiring:
    • counterProvider.toBlocSignal(ref) automatically registers ref.onDispose to close the underlying bridge when the widget or provider scope unmounts. No memory leaks.
  3. Synchronous Cross-Framework Composition:
    • Look at grandTotal: computed(() => blocPeer.state() + riverpodPeer.state() + signalCubit.state()).
    • A single computed signal observes state originating in package:bloc, package:riverpod, and package:bloc_signals simultaneously. When any of the three states update, grandTotal recalculates in the exact same frame with zero microtask queue hops.

🔄 The Return Trip: Exporting BlocSignal to Legacy Trees

Peer status is not a one-way street. What if you build a cutting-edge feature using modern BlocSignal containers, but you need to embed it inside an existing application that relies entirely on flutter_bloc's BlocBuilder or Riverpod's ConsumerWidget?

You don't need to rewrite your containers!

1. Modern BlocSignal ➔ Classic flutter_bloc Trees

final modernCubit = ModernSignalCubit();

// Adapt to a classic flutter_bloc Cubit:
final classicCubit = modernCubit.toClassicCubit();

// Consume directly inside existing flutter_bloc widgets with standard types:
BlocBuilder<bloc_lib.Cubit<int>, int>(
  bloc: classicCubit,
  builder: (context, state) => Text('Legacy BLoC UI: $state'),
);

2. Modern BlocSignal ➔ Riverpod ProviderScope Trees

final modernCubit = ModernSignalCubit();

// Expose modern CubitSignal as a standard Riverpod NotifierProvider:
final myRiverpodProvider = modernCubit.toProvider();

// In any Riverpod ConsumerWidget:
Widget build(BuildContext context, WidgetRef ref) {
  final count = ref.watch(myRiverpodProvider);
  return ElevatedButton(
    onPressed: () => ref.read(myRiverpodProvider.notifier).cubit.increment(),
    child: Text('Riverpod UI: $count'),
  );
}

🎯 What This Means for Engineering Teams

This architectural milestone eliminates the single largest point of friction in Flutter development:

  • No More All-or-Nothing Rewrites: You can introduce BlocSignal into a massive legacy Riverpod or BLoC production codebase one screen, one dialog, or one widget at a time.
  • Respect for Established Code: Your battle-tested classic BLoC authentication flows or Riverpod dependency injection graphs do not need to be touched. They plug directly into synchronous signal pipelines as first-class citizens.
  • Freedom of Choice for Greenfield Features: For new, high-performance features (for example complex forms, real-time dashboards, charts, animations, or web components), your team can leverage zero-codegen, streamless BlocSignal containers with sub-microsecond rendering speed.
  • Clean AI Coding Skills for Interop and Migration: We provide official, pre-packaged AI coding skill bundles that guide AI assistants (such as Antigravity, Claude Code, Gemini, and Cursor) with exact bidirectional rules, decision trees, and step-by-step migration recipes without hallucinations.

🏁 All Aboard at Grand Central

State management in Flutter does not have to be an ideological battleground.

Whether your architecture runs on the Classic BLoC Iron Horse, the Riverpod Freight Hauler, or the BlocSignal Bullet Train, Grand Central Terminal ensures green lights across all lines.

To get started today, add the peer packages to your pubspec.yaml:

dependencies:
  bloc_signals: ^1.0.0
  bloc_signals_bloc: ^1.0.0      # For Classic BLoC peer bridges
  bloc_signals_riverpod: ^1.2.0  # For Riverpod peer bridges
  bloc_signals_flutter: ^1.0.0   # For Flutter widget bindings

Check out the complete documentation, interactive API catalogs, and live showcase apps at blocsignal.dev.

See you on the tracks!

Read the whole story
alvinashcraft
55 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

What's new in Visual Studio 2026 - GitHub Copilot Multi-File Edits, Native Memory Profiling, and .NET 10 Tooling

1 Share

The developer tooling ecosystem has entered an era of deep agentic assistance and extreme hardware efficiency. In enterprise production environments today, software engineering is anchored on the robust LTS foundation of C♯ 14 running on .NET 10, while preview builds of C♯ 15 and .NET 11 continue to test the next frontiers of runtime execution.

 

The release of Visual Studio 2026 represents one of the most substantial architectural evolutions of Microsoft's flagship Integrated Development Environment. In this comprehensive technical walkthrough, we unpack the major capabilities of Visual Studio 2026, from autonomous multi-file GitHub Copilot refactoring and native zero-overhead memory profiling to accelerated parallel build pipelines.

 

What is New in Visual Studio 2026 - Features & Tooling
Visual Studio 2026 Guide: GitHub Copilot Multi-File Edits, Native Memory Profiling, and .NET 10 Tooling Architecture

 

Table of Contents

 

  • Explore how Visual Studio 2026 transforms AI from an inline code completion assistant into an autonomous multi-file refactoring agent.
  • Discover the redesigned Diagnostics Hub featuring real-time, zero-overhead memory heap allocation graphs and GC Gen 0/1/2 telemetry.
  • Master first-class IDE intelligence for C♯ 14 language features, including the `field` keyword, enhanced pattern matching, and interceptors.
  • Experience up to 65% faster solution compilation through out-of-process parallel MSBuild workers and native distributed build caching.
  • Streamline microservice orchestration with integrated .NET Aspire visual topology dashboards and instant Hot Reload 2.0.

 

Next-Gen GitHub Copilot Agent Integration and Multi-File Refactoring

In previous IDE versions, AI coding assistants operated primarily within the confines of single-file cursor context or standalone chat sidebars. Developers still bore the cognitive burden of manually copying code snippets across dependent interfaces, implementation classes, unit test suites, and database configuration files.

 

Visual Studio 2026 fundamentally re-engineers this experience by integrating GitHub Copilot Agent Mode directly into the solution workspace. Operating across the entire Roslyn syntax tree, Copilot can now plan, coordinate, and execute atomic multi-file code refactorings in a single cohesive transaction.

 

When you prompt Copilot to add an enterprise domain entity (e.g., "Add an AuditLogging pipeline to all controller actions"), the agent analyzes your solution architecture, updates repository contracts, writes Entity Framework Core migration snapshots, registers dependency injection services in `Program.cs`, and drafts corresponding xUnit test fixtures simultaneously.

 

As we previously explored in our guide on how to run local AI models in 2026, Visual Studio 2026 also allows developers to connect local ONNX and Ollama inference endpoints directly into the IDE, ensuring complete source privacy for regulated enterprise codebases.

 

Visual Studio 2026 presents these changes in a unified multi-diff review window, allowing you to accept, reject, or fine-tune modifications across individual files before committing them to Git.

 

 

Native .NET 10 Memory Profiling and Zero-Overhead Diagnostics

Diagnosing memory leaks, high Garbage Collection (GC) pressure, and unintended object retention in production enterprise APIs has traditionally required attaching heavyweight external diagnostic profilers that degrade application performance.

 

Visual Studio 2026 introduces a completely rewritten Diagnostics Hub that leverages native EventPipe tracing and .NET 10 hardware-assisted telemetry to provide continuous, zero-overhead memory and CPU profiling directly in the debugging window.

 

Live GC Generation and Heap Allocation Visualization

The memory profiler now displays real-time allocation rates per second categorized by generation (Gen 0, Gen 1, Gen 2, and Large Object Heap). It automatically flags hot paths where boxing, string allocations, or temporary LINQ iterators are thrashing the Garbage Collector.

 

Before & After: Tracking Heap Allocation Hotspots in .NET 10

Consider the following before-and-after refactoring scenario identified instantly by the Visual Studio 2026 Allocation Tracker:

 

// ❌ BEFORE: Diagnostic Hub flags 1.4 MB/sec heap allocations during HTTP request bursts
public class InvoiceSummaryService
{
    public string GenerateSummary(List<InvoiceItem> items)
    {
        // Unnecessary LINQ and string concatenation creates millions of Gen 0 objects
        return string.Join(", ", items.Select(i => i.Sku + ":" + i.Amount.ToString("C")));
    }
}

// ✅ AFTER: Zero-allocation span-based formatting with ValueStringBuilder (0 B Heap Allocations)
public class HighPerformanceInvoiceService
{
    public void FormatSummary(ReadOnlySpan<InvoiceItem> items, Span<char> destination, out int charsWritten)
    {
        var formatter = new ValueStringFormatter(destination);
        foreach (ref readonly var item in items)
        {
            formatter.Append(item.Sku);
            formatter.Append(':');
            formatter.AppendSpanFormattable(item.Amount, "C");
            formatter.Append(", ");
        }
        charsWritten = formatter.Length;
    }
}

 

Reflecting on the evolution of C♯ language features over the years, having native profiling tools that seamlessly illuminate modern low-level optimizations makes writing high-throughput code vastly more intuitive.

 

 

C♯ 14 First-Class Tooling: Field-Backed Properties & Source Generators

With the stable release of C♯ 14 in .NET 10, Visual Studio 2026 delivers comprehensive IntelliSense, quick-fix refactorings, and visual diagnostic squiggles for all new language constructs.

 

1. Field-Backed Auto-Properties (`field` Keyword)

For decades, developers were forced to declare explicit private backing fields whenever custom validation or notification logic was needed in a property accessor. C♯ 14 introduces the contextual `field` keyword, and Visual Studio 2026 provides automated one-click refactorings (`Ctrl + .`) to convert boilerplate code into concise syntax:

 

// Clean C# 14 Field-Backed Property in Visual Studio 2026
public class UserAccount
{
    // Auto-property with accessor-level logic using the 'field' keyword
    public string EmailAddress
    {
        get => field;
        set => field = string.IsNullOrWhiteSpace(value) 
            ? throw new ArgumentException("Email cannot be empty.") 
            : value.Trim().ToLowerInvariant();
    } = "guest@example.com";

    // Value clamping without explicit private backing field
    public int RetryCount
    {
        get => field;
        set => field = Math.Clamp(value, 0, 10);
    } = 3;
}

 

2. Visual Roslyn Source Generator Explorer

Debugging compile-time C♯ Source Generators (such as JSON serializers, regular expression generators, and telemetry loggers) used to be notoriously opaque. Visual Studio 2026 introduces a dedicated Source Generator Explorer tree directly within Solution Explorer. You can set breakpoints inside generated files, inspect generated C♯ source code in real time, and step through generated serialization pipelines during active debug sessions.

 

 

Blazing-Fast Build Acceleration: Parallel MSBuild & Build Caching

Developer productivity is directly tied to inner-loop compilation speed. In massive enterprise solutions spanning dozens of microservices and hundreds of class libraries, waiting for full builds drains developer momentum.

 

Visual Studio 2026 introduces a multi-tier build optimization engine that reduces incremental build times by up to 65% on modern multi-core processors:

  • Out-of-Process Parallel MSBuild Nodes: Compilation workloads are distributed dynamically across isolated out-of-process worker nodes, eliminating 64-bit main thread contention and maximizing CPU utilization across performance and efficiency cores.
  • Solution-Wide Artifact Caching: Unchanged assemblies, source-generated outputs, and NuGet metadata are cached in a local, content-addressable storage cache, skipping redundant compiler passes entirely.
  • Predictive Dependency Graphing: The project system predicts which downstream projects require recompilation based on method signatures rather than raw timestamp updates, avoiding cascading project builds when only private method implementations change.

 

For developers who maintain complex web development pipelines alongside backend APIs, pairing these swift compilation cycles with our 30 essential Chrome extensions for developers helps streamline end-to-end full-stack testing.

 

 

Modern Cloud & Container Debugging: .NET Aspire & Hot Reload 2.0

Cloud-native microservice architectures demand tools that can orchestrate, trace, and debug distributed containers without requiring developers to manage complex YAML files or terminal scripts manually.

 

1. Integrated .NET Aspire Visual Dashboard

Visual Studio 2026 embeds the .NET Aspire orchestration dashboard directly into the IDE interface. With a single click (`F5`), Visual Studio spins up distributed application stacks—including Redis caches, PostgreSQL containers, RabbitMQ queues, and OpenTelemetry endpoints—and visualizes real-time request traces, logs, and structured health metrics inside a unified docking pane.

 

2. Hot Reload 2.0 for Web and Desktop

Hot Reload has been significantly upgraded in Visual Studio 2026 to support edits that previously required a full restart. Developers can now modify generic methods, alter asynchronous state machine logic, add lambda expressions with captured variables, and edit Blazor WebAssembly components with near-instant hot swapping.

 

 

Frequently Asked Questions (FAQ)

1. What are the key highlight features of Visual Studio 2026?

The major highlights include GitHub Copilot Agent Mode for multi-file refactoring, native zero-overhead .NET 10 memory profiling, first-class C♯ 14 language tooling, up to 65% faster builds via parallel MSBuild, and integrated .NET Aspire cloud dashboard tooling.

 

2. How does GitHub Copilot Multi-File Editing work in Visual Studio 2026?

Copilot Agent analyzes the entire solution dependency tree to plan and apply edits across multiple files simultaneously, such as updating models, interfaces, controllers, and test files in a single reviewable transaction.

 

3. Does Visual Studio 2026 support C♯ 14 and .NET 10 out of the box?

Yes. Visual Studio 2026 provides complete day-one support for C♯ 14 language syntax (such as the `field` keyword for auto-properties) and .NET 10 runtime SDKs and project templates.

 

4. Can I debug C♯ Source Generators in Visual Studio 2026?

Yes. Visual Studio 2026 features a built-in Source Generator Explorer that displays all generated source files in Solution Explorer, allowing developers to set breakpoints and inspect generated code during execution.

 

5. What is the performance impact of the new Memory Profiler in Visual Studio 2026?

The new Diagnostics Hub memory profiler uses hardware-accelerated EventPipe technology in .NET 10, delivering zero noticeable performance degradation during active debugging sessions.

 

6. How does Visual Studio 2026 improve build times for large solutions?

It leverages out-of-process parallel MSBuild compilation, local artifact caching, and signature-based dependency evaluation to skip redundant builds and accelerate incremental compilation by up to 65%.

 

7. What improvements are included in Hot Reload 2.0?

Hot Reload 2.0 supports edits to generic types, asynchronous state machines, captured lambda variables, and Blazor WebAssembly components without requiring an application restart.

 

8. Can I use local AI models with Visual Studio 2026 Copilot?

Yes. Visual Studio 2026 provides an extensible AI provider interface allowing enterprise teams to connect local LLMs via Ollama, ONNX Runtime, or private Azure OpenAI instances.

 

9. Is .NET Aspire built into Visual Studio 2026?

Yes. .NET Aspire orchestration, container management, and distributed OpenTelemetry telemetry dashboards are fully embedded within the IDE's debugging windows.

 

10. Is Visual Studio 2026 backward compatible with older .NET frameworks?

Yes. Visual Studio 2026 provides full backward compatibility for building, testing, and debugging solutions targeting .NET 8, .NET 9, and legacy .NET Framework 4.8.x projects.

 

 

End Note

Visual Studio 2026 delivers an unmatched developer experience by blending autonomous AI agent workflows with relentless inner-loop speed and deep runtime mechanical sympathy. By eliminating routine boilerplate through C♯ 14 tooling, streamlining multi-file refactoring with Copilot Agent Mode, and providing real-time memory diagnostics without performance degradation, the IDE sets a new benchmark for software engineering productivity.

 

Whether you are building high-throughput microservices in .NET 10, architecting cloud-native distributed topologies with .NET Aspire, or modernizing enterprise legacy applications, upgrading to Visual Studio 2026 equips your team with the most potent development environment ever built.

 

Have you installed Visual Studio 2026 in your development workflow yet? Which feature has made the biggest impact on your daily productivity—Copilot multi-file edits, parallel MSBuild acceleration, or native memory diagnostics? Share your experiences and thoughts in the comments below!

 

Read the whole story
alvinashcraft
56 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Collection Performance: Use Caution when using Range Expressions in Hot Paths when Collection Slicing

1 Share
Range expressions make collection slicing concise, but they can introduce unexpected overhead in hot paths. This subscriber-only article compares several ways to create slices with `Memory`, `Span`, `ReadOnlyMemory`, and `ReadOnlySpan`—and explains when using start-and-length overloads may be the smarter performance choice.
Read the whole story
alvinashcraft
56 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

You have to beat the models at something

1 Share

In 2025, I wrote that software engineers ought to be assessed by “value over replacement”: not how much money they made for their company, but how much they would have made compared to the average engineer in their position. I’ve always found it vaguely silly when engineers put “built a product that made $X” on their resumes, when they just did the JIRA tickets that came across their desk.

Today, value over replacement is even more important. A replacement-level engineer in the 2010s was fine: maybe not worth promoting, but still worth paying, because writing code had a high fixed cost. Now writing code costs a hundred bucks a month. What are you doing that GPT-5.6-Sol or Claude Opus 5 wouldn’t do in your position? Why is it worth paying an extra two or three orders of magnitude for?

This is a scary thought. But you’re not doing yourself any favors by pretending that LLMs can’t actually write code and it’s all just a scam, or that LLM-written code is inherently so bad as to cause companies using it to collapse next year. We are not going to wake up in 2027 to find that the AI craze is over and everyone is writing code by hand again. You ought to put some serious thought into what you can do better than the models in the medium and long term.

Staying ahead of the models is a moving target. At the start of 2026, “make working changes to large codebases” was in this category, but now it’s not. For this reason, I doubt that you can retreat to some “hard engineering” area that requires deeper expertise. That might work in the short term, but not forever. If LLMs can find a better lower bound on the Riemann hypothesis, they will soon1 be able to write solid high-performance kernel drivers or GPU shaders or whatever.

I think it’s more useful to look at the tasks models haven’t gotten better at over time, and the tasks that are hard for them get better at in principle. The two best examples of these are:

  1. Deep familiarity with the codebase
  2. Technical communication

Deep familiarity

What do frontier LLMs get wrong? What kind of coding mistakes do they make? It’s been a long time since I’ve seen a straight-up hallucination from a coding agent, or a simple logic error like an off-by-one. The mistakes they make tend to be errors of ignorance:

  • Not knowing that there’s a module in the codebase they could use instead of reimplementing some logic
  • Making the change in the wrong system because they didn’t know System X was the standard place for this functionality
  • Adopting a coding style that’s inconsistent with the company’s standard practice

Other times they’re errors of paranoia:

  • Implementing triply-redundant checks for a value that technically could be wrong but practically is set once from config and never updated
  • Assuming that ten milliseconds of stale data is unacceptable and designing a complex, unnecessary system to keep it always up to date
  • Building in fallbacks and “graceful” degradation into some code that ought to simply crash on error (e.g. a CLI tool, or a restartable k8s service)

What do these errors have in common? They’re the kind of errors a smart engineer might make if they had no context on the system: they’re competent enough to be able to solve the problem, but they haven’t been around long enough to confidently say “yes, we can take this risk to avoid an extra three thousand lines of code”. Until someone cracks continuous learning or truly massive context windows, this is just an inherent feature of how AI agents operate. If you can catch these errors, you’ll be providing real value.

The only way to catch these errors is to be familiar with the codebase and familiar with the system in general. For much more on this, see my post You can’t design software you don’t work on. But there’s also a psychological component to it. You have to be willing to confidently disagree with the agent.

AI agents can be very convincing. Often they can get “stuck” on some error above where they’re not willing to take a particular risk, so they keep going back and sneaking in code to cover that case (or writing persuasive arguments about why that case is important). To add value, you need to be willing to say “this sucks, I don’t think we need X and Y at all, why can’t we do Z in a much simpler way?” It takes courage.

You can’t rely on other AI agents to review each other’s work. If you use the same model, it’ll reliably make the exact same assumptions and mistakes. But even if you use different models, they’ll also tend towards the same kinds of mistakes — ignorance and paranoia — for the same structural reasons. AI-driven review loops are in fact more likely to get these things wrong, because modern AIs have been RL-ed to try to find a few nitpicks no matter what. Having a critic AI and a worker AI bounce off each other is a really good way to end up with ten thousand lines of paranoid slop.

Technical communication

Another area where you can add value on top of AI is communication. Newer models are better at coding, but are paradoxically getting worse at writing. GPT-3.5 and GPT-4 had a human-like writing style at times. GPT-4o introduced the modern slop idiolect, and the newer Anthropic models speak “Claudish”: a bizarre semi-baroque semi-truncated way of communicating that nobody enjoys. There have been a few bright spots — GPT-4.5 was okay, and I quite liked o32 — but in general LLMs are not good at this. Here’s two reasons why.

First, good writing is not a verifiable domain. If you want a model to get good at mathematics or coding, you can generate problems for it and automatically grade them. You can’t grade good writing. If you try to get humans to grade it — for instance, via the early OpenAI RLHF attempts — you get the kind of writing that sounds impressive to the average person when consumed in single-paragraph form. This is the origin of the “stick three hundred writing devices into every sentence” style. I think it’d be possible in principle to hand-pick some people with good taste and have them do it, but there are some obvious problems3 that prevent this from happening.

Second, the labs have been monomaniacally focused on capability instead of communication. When you’re trying to train a model that can break new scientific ground or replace a software engineer, you might trade off some communication ability. In fact, I think we can identify exactly how this has been happening. If you look at internal model reasoning tokens, they tend to have strange word choices and oddly truncated grammar:

RESOLUTION: charge the current-leg’s OWN saved-prefix occupancy EAGERLY: when leg i saves e1..et: ALSO commit their occupancy AT LEG i

If you were to translate this into proper English, you would probably end up with something that reads like Claudish:

Charge the current-leg’s saved-prefix occupancy on a clean, eager path: when leg i saves e1..et, commit the occupancy at leg i.

I suspect that the weirdly alien writing style of some LLMs is because you’re reading a semi-literal translation of that model’s internal chain-of-thought, which has become nearly incomprehensible in pursuit of better problem-solving abilities. It is surprisingly hard to translate Claudish to good English: not only do you need to follow the convoluted, compressed language of the original, but you need the technical ability to understand the problem the model is solving.

Because of all this, technical communication may be a surprisingly durable skill. In Peter Watts’ novel Blindsight, the world is full of cognitively augmented humans. The main character is a “synthesist”: someone whose job is to be a translation layer between these geniuses (who speak in abbreviations and gestures) and everyone else. Watts’ idea is that communication ability may be largely independent from — or even negatively correlated with — intelligence. A “country of geniuses” may still need a bunch of ordinary smart people to translate their insights for everyone else.

If you’re trying to communicate to humans, there are also huge advantages to having a human write the content. Many of us are becoming AI-blind: developing an instinctive reflex that stops us reading when we encounter AI-generated content. It’s like the reflex that allows people to ignore flashing billboards or sidebar advertisements on websites. If you circulate some planned technical strategy as an AI-written document, most of your colleagues will have to physically force themselves to read it word-by-word.

Conclusion

Whatever you do, don’t be a meat proxy: someone who simply copies requests into an AI agent and submits their output as your own work product. Doing that is just begging to be fired, since you’re definitionally not adding any value yourself. Even if you have a cunning system of multiple agents — the so-called “software factory” — you’re still on dangerous ground. When the features of your system work their way into enterprise AI tooling (and they will), you’ll be disposable.

You need to find some way to leverage your expertise to do what the models can’t. Simply not using AI at all is better than being a meat proxy, since you’ll probably do some things better than the model would have, but it’s far better to figure out what AI can do and position yourself to fill those gaps. Right now, there are two main gaps: familiarity with the technical details of the system, and the ability to clearly and persuasively write about those details.


  1. If you’re thinking “but LLMs can do these things now!”, substitute your preferred example of high-difficulty software engineering.

  2. Although this was probably a “thank God it doesn’t speak like 4o” reaction.

  3. Defining good taste is hard, there’s no guarantee that AI lab researchers have good taste to start with, nobody will agree on examples, the bulk of users might not even like it, you won’t be able to get enough people to produce the volume of data you need, and so on.

Read the whole story
alvinashcraft
56 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

The MacGuffin And Chekhov’s Gun: 2 Literary Devices Writers Should Know

1 Share

Learn how writers use these literary devices – The MacGuffin and Chekhov’s Gun – to create suspense, drive plots, and keep readers hooked.

Here are two literary devices you could use when plotting your next suspense novel, detective story, crime caper, or mystery. From two masters of the craft, these two strategies can help strengthen your storyline.

The MacGuffin And Chekhov’s Gun: 2 Literary Devices Writers Should Know

1. The MacGuffin

Alfred Hitchcock gives us The MacGuffin. The MacGuffin is an object, event, or character that seems to be the central focus of the plot at the start of the story but, ultimately, proves to be unimportant. An heiress’s jewels are stolen, but the real plot is the detective’s desire for her despite her dark past. A driver must deliver a package cross country, but what is in the package is not important. Mysterious lights are seen over a rural sky the night a boy goes missing, but the story is not about evidence of UFOs but about a community coming together after a tragedy.

Example: The Maltese Falcon by Dashiell Hammett: The valuable Maltese Falcon statuette drives the characters to pursue, deceive, and betray one another. But the object is less important than what the characters are willing to do to obtain it.

2. Chekhov’s Gun

Anton Chekhov gives us Chekhov’s Gun. Chekhov’s Gun is the opposite of the MacGuffin. In this storytelling device, the writer unobtrusively introduces an object early on in the story—but its significance does not become clear until much later, usually in the climax. The treasured penknife the widow finds in her husband’s desk is used to help free her from a kidnapper’s ropes. The plastic toy the hero’s child gets with his take-away meal is tested to prove a plastic company is poisoning the environment. [Suggested reading:  How Chekhov’s Gun Can Help You With Description]

Example: And Then There Were None by Agatha Christie: Early in the novel, 10 people in a house discover a nursery rhyme describing 10 deaths. It seems like an eerie decoration, but then it becomes a blueprint for the murders.

The two devices work at opposite ends of the plot scale. In the first, you deliberately mislead the reader by using something showy and intriguing to get the story started. In the second, you carefully plant a clue that will become important at the end of the story. You can, of course, use these devices in any genre.

The Last Word

The MacGuffin and Chekhov’s Gun may seem like small storytelling devices, but they can have a big impact on your plot. One gives your characters something to chase, while the other plants something that will matter later. Use them carefully, and you can create curiosity and build suspense.


by Anthony Ehlers

The post The MacGuffin And Chekhov’s Gun: 2 Literary Devices Writers Should Know appeared first on Writers Write.

Read the whole story
alvinashcraft
57 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories