static void Main(string[] args) { var dictionary = new Dictionary <string, Foo>(); Func <string, Foo> createValue = (key) => { var foo = new Foo { ID = key }; dictionary.Add(key, foo); return(foo); }; // this wrapper object is not useable, since no key has been specified for it yet var wrapper = new KeyedValueWrapper <string, Foo>(dictionary.TryGetValue, createValue); // create wrapper1 based on the wrapper object but changing the key to "ABC" var wrapper1 = wrapper.Change("ABC"); var wrapper2 = wrapper1; Foo foo1 = wrapper1.Value; Foo foo2 = wrapper2.Value; Console.WriteLine("foo1 and foo2 are equal? {0}", object.ReferenceEquals(foo1, foo2)); // Output: foo1 and foo2 are equal? True // create wrapper1 based on the wrapper object but changing the key to "BCD" var wrapper3 = wrapper.Change("BCD"); var wrapper4 = wrapper3; Foo foo3 = wrapper3.Value; dictionary = new Dictionary <string, Foo>(); // throw a curve ball by reassigning the dictionary variable Foo foo4 = wrapper4.Value; Console.WriteLine("foo3 and foo4 are equal? {0}", object.ReferenceEquals(foo3, foo4)); // Output: foo3 and foo4 are equal? True Console.WriteLine("foo1 and foo3 are equal? {0}", object.ReferenceEquals(foo1, foo3)); // Output: foo1 and foo3 are equal? False }
static void Main(string[] args) { // this wrapper object is not useable, since no key has been specified for it yet var wrapper = new KeyedValueWrapper <string, Foo>(new Dictionary <string, Foo>(), (key) => new Foo { ID = key }); // create wrapper1 based on the wrapper object but changing the key to "ABC" var wrapper1 = wrapper.Change("ABC"); var wrapper2 = wrapper1; Foo foo1 = wrapper1.Value; Foo foo2 = wrapper2.Value; Console.WriteLine("foo1 and foo2 are equal? {0}", object.ReferenceEquals(foo1, foo2)); // Output: foo1 and foo2 are equal? True // create wrapper1 based on the wrapper object but changing the key to "BCD" var wrapper3 = wrapper.Change("BCD"); var wrapper4 = wrapper3; Foo foo3 = wrapper3.Value; Foo foo4 = wrapper4.Value; Console.WriteLine("foo3 and foo4 are equal? {0}", object.ReferenceEquals(foo3, foo4)); // Output: foo3 and foo4 are equal? True Console.WriteLine("foo1 and foo3 are equal? {0}", object.ReferenceEquals(foo1, foo3)); // Output: foo1 and foo3 are equal? False // Counter-example: manipulating the dictionary instance that was provided to the wrapper can disrupt expected behavior var dictionary = new Dictionary <string, Foo>(); var wrapper5 = wrapper.Change("CDE", dictionary); var wrapper6 = wrapper5; Foo foo5 = wrapper5.Value; dictionary.Clear(); Foo foo6 = wrapper6.Value; // one might expect this to be true: Console.WriteLine("foo5 and foo6 are equal? {0}", object.ReferenceEquals(foo5, foo6)); // Output: foo5 and foo6 are equal? False }