C#C
C#2y ago
Stroniax

Builder Pattern as Ref Struct

Hey all, I'm trying to make a source-generated builder which I want to be a struct. I'm running into a problem when trying to chain the entire build, but if I capture the builder in a variable first I can chain it as much as I like. Wondering if there's any language feature/etc that would help me out here? What I'd like is to use the same builder struct instance and not have to copy it with each chained method.

C#
public struct MyBuilder {
  public required int Id { get; set; }
  public string? Name { get; set; }
  public My Build() => new(this);
}
public static class MyBuilderExtensions {
  public ref MyBuilder WithId(this ref MyBuilder b, int id) {
    b.Id = id;
    return ref b;
  }
  public ref MyBuilder WithName(this ref MyBuilder b, string? name) {
    b.Name = name;
    return ref b;
  }
}
public static class Usage {
  public static My Works() {
    var builder = new MyBuilder() { Id = 1 };
    return builder.WithName("Test").Build();
  }
  public static My DoesNotWork() {
    // CS1510: A ref or out value must be an assignable variable
    return new MyBuilder() { Id = 1 }.WithName("Test").Build();
  }
}
public partial class My
{
  public required int Id { get => throw null; init => throw null; }
  public string Name { get => throw null; init => throw null; }
  // only if set by builder/init
  public bool TryGetName(out string name) => throw null;;
  [SetsRequiredMembers]
  public My(int id) => throw null;
  [SetsRequiredMembers]
  public My(MyBuilder b) => throw null;
}


EDIT:
The problem occurs because the extension method operates on a ref of the instance, so I must have a field/variable declared beforehand of the type. This means I can't just call new().Extension(), as the result of new() must be assigned to something before it can be used. That is what I am trying to resolve.
Was this page helpful?