Skip to content

Instantly share code, notes, and snippets.

@daveaglick
Created August 16, 2017 20:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daveaglick/2e5697a7249578365624a41309450b19 to your computer and use it in GitHub Desktop.
Save daveaglick/2e5697a7249578365624a41309450b19 to your computer and use it in GitHub Desktop.
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);
}
}
@daveaglick
Copy link
Author

FWIW I don't particularly care about the syntax. this ref Foo foo might make more sense than ref this Foo foo. And it might be good to make the ref semantics explicit at the call like normal ref params, something like ref foo.UpdateBar(3);.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment