tags:

views:

56

answers:

2

Consider the following:

var o = new { Foo = "foo", Bar = "bar" };

This instance is read-only, since the anonymous type doesn't implement setters like a class does:

public class O
{
    public String Foo { get; set; }
    public String Bar { get; set; }
}

Is it possible to "open up" the anonymous instance and allow it's properties to be altered? Preferably in fewer characters than it would take to create a class.

I'm thinking perhaps this can be done with an extension method on Object; o.SetProperty(o.Foo, "foo!");, if you can't implement setters in-line at the construction of the object.

+7  A: 

No, cause anonymous types in C# are immutable by design.

Brian Rasmussen
Well, C# anonymous types are (and indeed the question is tagged C#). I'm just highlighting that this is a feature of the specific compiler, not "anonymous types" per se.
Marc Gravell
@Marc: Good point, and I guess that the reason for making anonymous types immutable in the first place has to do with how they are typically used in LINQ.
Brian Rasmussen
+1 Thank you. I've accepted Johannes' more elaborate answer. It touches on a few alternatives.
roosteronacid
@roosteronacid: You're welcome.
Brian Rasmussen
+3  A: 

Anonymous types are immutable by design, so there's no way you can change their state. You could use reflection (as Mark Gravell pointed out correctly) but neither is this desirable performance wise nor from a design perspective.

You've got multiple options to work around this:

  • Use Tuples instead of annonymous types. Note that they are immutable too but you can work with them more easily to create methods like tupleA.WithItem2(newValueForItem2). Similar to the string class.
  • write your own "named" type using auto properties, usually straightforward
  • use a refactoring tool like CodeRush that can generate a "named" type from your usage
Johannes Rudolph
The claim about reflection is invalid: the following works fine: ` var obj = new { id = 1, name = "abc" }; obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic).Single(f => f.FieldType == typeof(int)).SetValue(obj, 456); Console.WriteLine(obj.id);`
Marc Gravell