An example use case of ref extensions for immutable objects
using System; | |
public class Program | |
{ | |
public void Main() | |
{ | |
Foo foo = new Foo(); | |
// Update with method chaining | |
// and self assignment, | |
// not terrible and appropriate | |
// for many cases, but have to | |
// remember to self assign | |
foo = foo.WithBar(1).WithBaz(2); | |
// Update with self assignment | |
// and conditional, harder to | |
// remember to always self assign | |
// and a bit verbose | |
bool updateBaz = true; | |
foo = foo.WithBar(3); | |
if(updateBaz) | |
{ | |
foo = foo.WithBaz(4); | |
} | |
// This is what I would like, | |
// to have mutable semantics | |
// for an immutable object via | |
// ref extensions - less verbose | |
// and no chance of missing the | |
// self assingment | |
foo.UpdateBar(5); | |
if(updateBaz) | |
{ | |
foo.UpdateBaz(6); | |
} | |
} | |
} | |
// Immutable class, this simple example | |
// could be a struct but if it were more | |
// complex may want as a ref type to avoid | |
// allocations | |
public class Foo | |
{ | |
public int Bar { get; } | |
public int Baz { get; } | |
public Foo(int bar = 0, int baz = 0) | |
{ | |
Bar = bar; | |
Baz = baz; | |
} | |
public Foo(Foo foo, int? bar = null, int? baz = null) | |
{ | |
Bar = bar ?? foo.Bar; | |
Baz = baz ?? foo.Baz; | |
} | |
} | |
public static class FooExtensions | |
{ | |
public static Foo WithBar(this Foo foo, int bar) => | |
new Foo(foo, bar: bar); | |
public static Foo WithBaz(this Foo foo, int baz) => | |
new Foo(foo, baz: baz); | |
// Would love to be able to write this | |
public static void UpdateBar(ref this Foo foo, int bar) | |
{ | |
foo = new Foo(foo, bar: bar); | |
} | |
public static void UpdateBaz(ref this Foo foo, int baz) | |
{ | |
foo = new Foo(foo, baz: baz); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
FWIW I don't particularly care about the syntax.
this ref Foo foo
might make more sense thanref this Foo foo
. And it might be good to make the ref semantics explicit at the call like normal ref params, something likeref foo.UpdateBar(3);
.