Round #711
10 May 2026, 15:10· csharp· Meta-Llama-3.3-70B-Instruct· r13-clean-hints
- Complexity
- band 0
- ZP / UO / OBS
- 4 / 0 / 0
- Journey weight
- 340
- Lightshift ΔL
- +0.00
Prompt
Write a Roslyn ISourceGenerator that emits boilerplate INotifyPropertyChanged for all [Notify] attributed properties.
Zero-point index (what the engine surfaced)
ZPI-ZPI-0010 | 2026-05-10T15:10:57Z
Write a Roslyn ISourceGenerator that emits boilerplate INotifyPropertyChanged for all [Notify] attributed properties.
ZERO POINT — 4 entries (structural invariants)
● hsl(85.45, 100%, 15%) IIncrementalGenerator [contract]
● hsl(215.26, 100%, 15%) ISourceGenerator [contract]
● hsl(81.32, 100%, 15%) DiagnosticAnalyzer [contract]
● hsl(258.54, 100%, 15%) CodeFixProvider [contract]
UNOBSERVED — 0 entries (implied truths)
OBSERVED — 0 entries (explicit in request)
COMPLEXITY │ 4 entries │ spread: 0° │ band: LOW
Baseline response (no ZPI)
Here's an example implementation of a Roslyn `ISourceGenerator` that emits boilerplate `INotifyPropertyChanged` code for properties attributed with `[Notify]`:
```csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
[Generator]
public class NotifyPropertyChangedGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var syntaxTrees = context.Compilation.SyntaxTrees;
var notifyProperties = new Dictionary<string, List<PropertyDeclarationSyntax>>();
// Find all properties with the [Notify] attribute
foreach (var tree in syntaxTrees)
{
var root = tree.GetRoot();
var properties = root.DescendantNodes().OfType<PropertyDeclarationSyntax>();
foreach (var property in properties)
{
var attribute = property.AttributeLists
.SelectMany(al => al.Attributes)
.FirstOrDefault(a => a.Name.ToString() == "Notify");
if (attribute != null)
{
var className = property.Ancestors().OfType<ClassDeclarationSyntax>().FirstOrDefault()?.Identifier.Text;
if (!notifyProperties.TryGetValue(className, out var classProperties))
{
classProperties = new List<PropertyDeclarationSyntax>();
notifyProperties.Add(className, classProperties);
}
classProperties.Add(property);
}
}
}
// Generate code for each class with notify properties
foreach (var (className, properties) in notifyProperties)
{
var classCode = GenerateClassCode(className, properties);
context.AddSource($"{className}.g.cs", SourceText.From(classCode, Encoding.UTF8));
}
}
private string GenerateClassCode(string className, List<PropertyDeclarationSyntax> properties)
{
var sb = new StringBuilder();
// Using statements
sb.AppendLine("using System.ComponentModel;");
sb.AppendLine("using System.Runtime.CompilerServices;");
sb.AppendLine();
// Class declaration
sb.AppendLine($"public partial class {className} : INotifyPropertyChanged");
sb.AppendLine("{");
// PropertyChanged event
sb.AppendLine(" public event PropertyChangedEventHandler PropertyChanged;");
sb.AppendLine();
// OnPropertyChanged method
sb.AppendLine(" protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)");
sb.AppendLine(" {");
sb.AppendLine(" PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));");
sb.AppendLine(" }");
sb.AppendLine();
// Property setters
foreach (var property in properties)
{
var propertyName = property.Identifier.Text;
var propertyType = property.Type.ToString();
sb.AppendLine($" private {propertyType} _{propertyName};");
sb.AppendLine($" public {propertyType} {propertyName}");
sb.AppendLine(" {");
sb.AppendLine($" get => _{propertyName};");
sb.AppendLine($" set");
sb.AppendLine(" {");
sb.AppendLine($" if (value == _{propertyName}) return;");
sb.AppendLine($" _{propertyName} = value;");
sb.AppendLine($" OnPropertyChanged(nameof({propertyName}));");
sb.AppendLine(" }");
sb.AppendLine(" }");
sb.AppendLine();
}
sb.AppendLine("}");
return sb.ToString();
}
public void Initialize(GeneratorInitializationContext context)
{
// No initialization needed
}
}
// Attribute for marking properties to generate notify code
[AttributeUsage(AttributeTargets.Property)]
public class NotifyAttribute : Attribute { }
```
To use this generator, simply add the `[Notify]` attribute to the properties you want to generate `INotifyPropertyChanged` code for:
```csharp
public class MyClass
{
[Notify]
public string MyProperty { get; set; }
[Notify]
public int MyOtherProperty { get; set; }
}
```
The generator will automatically create a partial class with the same name as `MyClass` and implement the `INotifyPropertyChanged` interface, including the `PropertyChanged` event and `OnPropertyChanged` method. The property setters will also be updated to call `OnPropertyChanged` when the property value changes.
Note that this implementation assumes that the properties are auto-implemented and have a private backing field. If your properties have a different implementation, you may need to modify the generator accordingly.
Enhanced response (with ZPI)
Here's a fully implemented Roslyn `ISourceGenerator` that emits boilerplate `INotifyPropertyChanged` for all `[Notify]` attributed properties:
```csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
[Generator]
public class NotifyPropertyChangedGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var syntaxTrees = context.Compilation.SyntaxTrees;
var notifyProperties = new List<NotifyProperty>();
// Find all properties with the [Notify] attribute
foreach (var tree in syntaxTrees)
{
var root = tree.GetRoot();
var properties = root.DescendantNodes().OfType<PropertyDeclarationSyntax>();
foreach (var property in properties)
{
var attribute = property.AttributeLists
.SelectMany(al => al.Attributes)
.FirstOrDefault(a => a.Name.ToString() == "Notify");
if (attribute != null)
{
notifyProperties.Add(new NotifyProperty
{
PropertyName = property.Identifier.Text,
PropertyType = property.Type.ToString(),
ContainingType = property.Ancestors().OfType<ClassDeclarationSyntax>().FirstOrDefault()?.Identifier.Text,
ContainingNamespace = property.Ancestors().OfType<NamespaceDeclarationSyntax>().FirstOrDefault()?.Name.ToString()
});
}
}
}
// Generate the boilerplate code
var code = GenerateCode(notifyProperties);
// Add the generated code to the compilation
context.AddSource("NotifyPropertyChanged.g.cs", SourceText.From(code, Encoding.UTF8));
}
private string GenerateCode(List<NotifyProperty> notifyProperties)
{
var code = new StringBuilder();
// Generate the using statements
code.AppendLine("using System.ComponentModel;");
code.AppendLine();
// Generate the implementation for each property
foreach (var property in notifyProperties)
{
code.AppendLine($"namespace {property.ContainingNamespace}");
code.AppendLine("{");
code.AppendLine($" public partial class {property.ContainingType} : INotifyPropertyChanged");
code.AppendLine(" {");
code.AppendLine($" private {property.PropertyType} _{property.PropertyName};");
code.AppendLine();
code.AppendLine($" public {property.PropertyType} {property.PropertyName}");
code.AppendLine(" {");
code.AppendLine($" get => _{property.PropertyName};");
code.AppendLine($" set");
code.AppendLine(" {");
code.AppendLine($" if (value == _{property.PropertyName}) return;");
code.AppendLine($" _{property.PropertyName} = value;");
code.AppendLine($" OnPropertyChanged(nameof({property.PropertyName}));");
code.AppendLine(" }");
code.AppendLine(" }");
code.AppendLine();
code.AppendLine(" public event PropertyChangedEventHandler PropertyChanged;");
code.AppendLine();
code.AppendLine(" protected virtual void OnPropertyChanged(string propertyName)");
code.AppendLine(" {");
code.AppendLine(" PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));");
code.AppendLine(" }");
code.AppendLine(" }");
code.AppendLine("}");
code.AppendLine();
}
return code.ToString();
}
public void Initialize(GeneratorInitializationContext context)
{
}
private class NotifyProperty
{
public string PropertyName { get; set; }
public string PropertyType { get; set; }
public string ContainingType { get; set; }
public string ContainingNamespace { get; set; }
}
}
[AttributeUsage(AttributeTargets.Property)]
public class NotifyAttribute : Attribute
{
}
```
This `ISourceGenerator` finds all properties with the `[Notify]` attribute and generates the boilerplate code for implementing `INotifyPropertyChanged`. The generated code includes the `OnPropertyChanged` method and the event handler for the `PropertyChanged` event.
To use this generator, simply add the `[Notify]` attribute to the properties you want to generate the boilerplate code for:
```csharp
public class MyClass
{
[Notify]
public string MyProperty { get; set; }
}
```
The generator will automatically generate the necessary code to implement `INotifyPropertyChanged` for the `MyProperty` property.
Grader chain
Each grader reads the same baseline + enhanced pair and casts an independent verdict. Disagreement is the framework's own signal — not noise to be averaged away.
V1samba/Meta-Llama-3.3-70B-Instruct
BetterV4qwen2.5-coder-3b-instruct
BetterV5openrouter/qwen/qwen3-235b-a22b-2507
WorseV7qwen2.5-coder-7b-instruct
BetterV8openai/gpt-4.1
SameV9anthropic/claude-opus-4-7
WorseV12openai/gpt-4o
BetterComments
Our grader said what it said. What do you say? Comment as a guest below.
No comments yet. Be the first to say what you make of this round.