Created
August 16, 2017 20:50
-
-
Save daveaglick/2e5697a7249578365624a41309450b19 to your computer and use it in GitHub Desktop.
An example use case of ref extensions for immutable objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
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);
.