I am working on a project and I have an object, upon instantiation of which, will have a large number of values (20+) passed into it. I know I could make a constructor that would take in all of the values, but I am looking for a cleaner / more efficient way to do this.
Just to put this in perspective, the object is a character in a game, new instances of which are frequently created. The values assigned are attributes which are randomly generated.
Is a constructor with a large number of arguments the best way to go? Or is there a better way to do this that I don't know about? Any advice would be greatly appreciated.
EDIT: When a new game starts, a List<Character> is created and a for loop creates 10 instances of character and adds them to the list.
You can create a call that defines your game character. have users populate that class and pass it as the argument to your class.
something like this,
public class CharecterInfo
{
public string Name {get;set;}
public int Power {get;set;}
public int Health{get;set;}
}
public class Charecter
{
public Charecter(CharecterInfo charecterInfo)
{
//import values
}
}
I would avoid using public properties, since your class could be used while it's not properly initialized (in a bad state) which is the job of the constructor. you should use a constructor and validate the input before allowing the user to continue.
If the properties have public setters, you can use the object initialization syntax, e.g.:
Character c = new FooCharacter() {
Name = "Ugly Monster",
HP = 10000,
....,
};
Edit: as pointed out in the comments, this assumes that your constructor (empty or with minimal parameters) will initialize all required properties with valid data. The initialization syntax is just syntactic sugar that sets any specified properties after the constructor has initialized the object.
This completely depends on what those arguments are... But generally, it's not a great idea to have huge parameter lists. This is because of the confusion it creates over which parameter is what. An exception to this would be where you have a variable-length argument list that takes key/value pairs, allowing you to pass your data in an undefined order.
One alternative is to make another class that represents all your arguments. You could just create an instance of this, set the relevant fields and pass that in. To extend the idea, you might break that class up into a few classes and then provide a handful of constructors that take different combinations of those.
The useful thing with this approach is that you can have a default value for any of the arguments. Normally, if you want to specify a value for something further down the argument list but use defaults for the rest, you have to fill in all the default values in between. With this approach you can use all defaults except for the values you want to specify.
You have several options:
If all of the values are required:
Stick with the large list of parameters
Create a new class which has all of these items as properties
If not all of the values are required and you can use the Builder-pattern:
This link describes the pattern in detail: http://cdmckay.org/blog/2009/07/03/joshua-blochs-builder-pattern-in-csharp/
You can make a method that returns a class instance. Perhaps even in that class itself.
Something like:
public class Character
{
public string Name;
public int Level;
static Random random = new Random();
public static Character CreateNew()
{
Character newOne = new Character();
newOne.Level = random.Next(1, 5);
newOne.Name = (random.Next(1, 2) == 1) ? "Me" : "You";
return newOne;
}
}
One possibility lies in OOAD itself. Character attributes sound like a big enough concern to be the responsibility of a distinct class with which your character class collaborates.
A quick CRC analysis of your domain may help identify one or more newly distinguished responsibilities & corresponding types that are missing presently.
Related
Intent:
The intent of this pattern is to use sharing to support a large number
of objects that have part of their internal state in common where the
other part of state can vary.
Objects can share state via static fields.
What is the difference between sharing internal state of a large number of objects using the flyweight pattern and using static fields?
Is the pool of objects that the flyweight provides via its Factory what the flyweight is really all about?
Using static fields, there can only ever be one instance of the object in use at any one point in time. Using the flyweight pattern, you can have any number of different instances in use simultaneously, (each one of which is used multiple times). The canonical example of the flyweight pattern is for a text editor, where you need an object instantiated for each and every character in the document. Instead of having one object in memory for each character in a 10,000 word document, you then only need 26 objects, (assuming document only uses lower case letters), one for the letter 'a', one for the letter 'b', etc., and they are reused, transiently, over and over again throughout the document, each time you need to perform some function or action requiring an 'a' object.
EDIT: to answer question from first comment below:
So, since you need 26 different objects, making a Letter class that was a static, or a singleton, wouldn't work. If it was a static, you can't make any instances, and so whatever the static values would have to be appropriate for every place in the code where you made use of it.
If it was a singleton, then of course you only have one object. Every property would have to be adjustable (and adjusted) every time you used it.
To use this pattern for the letters in the alphabet, you have to have 26 different classes, one for each letter...
Also, the "part of the class that can vary" really means that some fields represent state that is different for every instance of the class. Whereas the part that is in common means that the values of those common fields are in common for all uses of the object matching those state values (all the 'a's for example), not for every instance of the class.
Again, using the text editor as an example.
Every place in your code that you need to deal with a character that is an 'a', you would first, go to the data structure that stores your 26 instances of character objects, and fetch the 'a' instance,
You would first modify/change the varying properties (the properties not tied to it's nature as an 'a', but perhaps to it's font size, position, color, etc.) to match the needs for this specific character 'a' in the document.
Then you would utilize the object to do whatever it is you need to do with it, and then return it to the storage structure for reuse the next time your code needs an 'a'.
The Flyweight pattern is used to avoid the overhead of large numbers of very similar classes. There are cases in programming where it seems that you need to generate a very large number of small class instances to represent data. Sometimes you can greatly reduce the number of different classes that you need to instantiate if you can recognize that the instances are fundamentally the same except for a few parameters. If you can move those variables outside the class instance and pass them in as part of a method call, the number of separate instances can be greatly reduced by sharing them.
In this context, it's important to bear in mind that the Flyweight was invented in an era where C# was nothing more than a rough sketch on some power point charts. And the maturation of the language was informed by some of these patterns implicitly. C# includes class members...
It is more typical to declare a non-static class with some static
members, than to declare an entire class as static. Two common uses of
static fields are to keep a count of the number of objects that have
been instantiated, or to store a value that must be shared among all
instances.
Source C# statics on MSDN
Taking things further, WPF technology popularized shared resources, and the result is often declarative code only.
So if your language of choice is C#, you may be advised to consider the Flyweight pattern against inherent properties that already exist in the language.
While patterns and their implementations are a bit subjective, using statics is a valid - albeit simplest possible - way to achieve Flyweight.
If you can use statics, that's great. Otherwise you can do something like you've touched on ... your factory that constructs flyweight objects can assign/reference the proper shared object.
Here is some example, it print all of the soldiers and their medals.
Because not all of the soldiers are decorated we are using the flyweight design pattern.
public class Soldiers
{
private string[] _soldiers;
private Dictionary<int, Medal> _medals = new Dictionary<int, Medal>();
public Soldiers(string[] soldier)
{
this._soldiers = soldier;
}
public Medal this[int index]
{
get
{
Medal medal = new Medal();
this._medals.Add(index, medal);
return this._medals[index];
}
}
public override string ToString()
{
var soldierList = new List<string>();
for (var i = 0; i < this._soldiers.Length; i++)
{
string soldier = this._soldiers[i];
if (this._medals.ContainsKey(i))
soldier = soldier + ", Medal: " + this._medals.ElementAt(i).ToString();
soldierList.Add(soldier);
}
return string.Join("; ", soldierList);
}
public class Medal
{
public bool Bronze;
public bool Silver;
public bool Gold;
public override string ToString()
{
return (this.Bronze ? "Bronze," : "") + (this.Silver ? "Silver," : "") + (this.Gold ? "Gold" : "")
}
}
}
Usage:
Soldiers soldiers = new Soldiers(new string[] { "SoldierA" , "SoldierB" , "SoldierC" });
soldiers[0].Gold = true;
soldiers[0].Silver = true;
soldiers[2].Bronze = true;
Console.Write(soldiers.ToString()) // "SoldierA, Medal: Silver,Gold; SoldierB; SoldierC, Medal: Bronze";
Is there an app or website where I can input parameter info (types and variable names), their defaults, and have it generate all the combinations of method overloads?
I have a class where the constructor can take in five parameters of different types. The parameters get mapped to properties, none of which have public setters. Each parameter has a default value.
I want my class to have overloaded constructors for all the various combinations of the parameters (ranging from no parameters to any and all combinations of the five parameters). To make it more confusing, one of the parameters can be passed in as a specific type or as a string, and I want the various combinations of overloads to take that into consideration.
Update:
I agree this design may not be the best. The class in question is one I'm using in a similar fashion to the PropertyMetadata class of WPF's DependencyProperty. A value is assigned for the property backing, and a new instance of the metadata class is passed in at that time. It's forcing my hand to create this cascading series of constructor overloads. Example:
private ModelProperty<UserModel, string> firstNameProperty =
RegisterProperty(p => p.FirstName, new ModelPropertyMetadata(**** lots of overloads here ****));
public string FirstName
{
get { return GetValue(firstNameProperty); }
set { SetValue(firstNameProperty, value); }
}
Maybe that's not the best design. I could possibly extend ModelPropertyMetadata to new classes which describe specific overloads, but that just seems like its pushing the problem somewhere else. Any thoughts on how to make this design better?
Take a look at optional parameters - these should help you avoid multiple overloads and still provide multiple ways to call a constructor. This is a .NET 4.0 feature.
Why not using optional parameters?
public MyClass(String myVar = null, Int32 v0 = 5, ...) { .. }
You can call the ctor this way:
new MyClass(v0: 10);
I don't know of one, but might I suggest you create a simple type that holds the parameters and has the defaulting logic and you pass that type into your class as what your suggesting will be difficult to maintain.
For a class instance to work properly, some fields should be properly initialized, what's your strategy to initialize these field, what should be given through constructor, what should be given through property?
My confusion is that, if the constructor requires a long parameter list, it's hard to use, if through properties, i tend to forget to set some properties.
What's the best practice?
You must ask yourself, if your class needs that many things to be created, perhaps it is doing too much. It's a sign that you should reconsider your design, or just how much "work" the constructor is doing.
It is true that you should not be able to create an instance with invalid state; thus the constructor should take all properties you need to be in a valid state.
To a degree, it depends on your model. For example, the ORM I use has the constructor take one parameter; an ID by which it can load all the other properties. It would be annoying if I had to pass them all in (that's the job of the ORM really; to set this object up). So in that sense, you can argue you have an "invalid" object (no properties set). But you'd be wrong; what you actually have is a "blank" or "empty" object. That's not the same as invalid.
So think carefully about what it means for your object to be "invalid". I would consider it invalid if other methods took this object, and threw an exception because something wasn't set. Use this logic to determine what needs to be in the constructor, and what can be set later (by some other process).
This is always a balancing act - you don't want to have constructors that require many parameters but you also don't want to require that a user set many properties before an object is in a valid state. Unfortunately there is no real guidance here as you must use your best judgment for the situation at hand.
Many times you may need to create a composite type which has many properties and many possible configurations (e.g. System.Web.Page). Composite types tend to have simple constructors that take little or no parameters and all values must be set through properties. Composite types are high-level types that are composed of lower-level factored (or primitive) types.
Factored types tend to be simpler, contain less state, and can be completely initialized via their constructors. Examples of factored types are System.String and System.Int32. These types are very simple and tend to be the building blocks of composite types.
If your type is a factored type then try your best to allow consumers to initialize the type completely via the constructor. If your type is a composite type then it is better to offer simple constructors with little or no parameters and require that the consumer configure the instance via property setters.
Now that .NET 3.5 allows you set any property on creation, I generally restrict any constructor with parameters to situations where the instance absolutely must have a value on creation. There really isn't any other reason to add constructor overloads with parameters IMO.
I think the best thing would be to perform validation and generally try to keep constructors with no parameters as it is often a requirement for different .NET libraries.
With validation you will have to check the object's validity, but it is pretty common thing to do. Something among the lines:
public interface IValidateable {
IEnumerable<string> Validate();
}
public class Person : IValidateable {
public string Title { get; set; }
public string First { get; set; }
public string Last { get; set; }
public Address HomeAddress { get; set; }
public Person() {
HomeAddress = new Address();
}
public IEnumerable<string> Validate() {
var errors = new List<string>();
if (string.IsNullOrEmpty(First))
errors.Add("First name is required.");
// And so on...
return errors;
}
}
// Usage
var p1 = new Person();
var p2 = new Person {
First = "Dmitriy"
};
if (p1.Validate().Any()) {
// Do something with invalid object
}
For instance, if I have a class like this:
namespace Sample
{
public Class TestObject
{
private Object MyAwesomeObject = new MyAwesomeObject();
}
}
Is there any benefit to set it up so that the property is set in the constructor like this?
namespace Sample
{
public Class TestObject
{
private Object MyAwesomeObject;
public TestObject()
{
MyAwesomeObject = new MyAwesomeObject()
}
}
}
The two are (nearly) identical.
When you define the initializer inline:
private Object MyAwesomeObject = new MyAwesomeObject();
This will happen prior to the class constructor code. This is often nicer, but does have a couple of limitations.
Setting it up in the constructor lets you use constructor parameters to initialize your members. Often, this is required in order to get more information into your class members.
Also, when you setup values in your constructors, you can use your class data in a static context, which is not possible to do with inlined methods. For example, if you want to initialize something using an expression tree, this often needs to be in a constructor, since the expression tree is in a static context, which will not be allowed to access your class members in an inlined member initializer.
It makes it easier to do step by step debugging
It makes it easier to control the order in which you call constructors
It makes it possible to send parameters to the constructors based on some logic or passed in argument to the object you are working on.
Another nice property of initializing stuff at the declaration site is that doing so on readonly fields guarantees that the field is not observable in its default (initiaized to zero) state.
Here's my article on the subject:
http://blogs.msdn.com/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx
The only benefit is that you can be a bit more dynamic in the constructor, where inline initialization requires that you only use static values for constructor arguments and such. For example, if MyAwesomeObject needs the value from a config file, you would have to set that in the constructor
Fields are initialized immediately
before the constructor for the object
instance is called. If the constructor
assigns the value of a field, it will
overwrite any value given during field
declaration.
See Fields (C# Programming Guide).
In your particular example, there's no advantage.
There is, however, lazy instantiation, which reduces your memory footprint in many cases:
namespace Sample
{
public Class TestObject
{
private Object m_MyAwesomeObject;
public TestObject()
{
}
public Object MyAwesomeObject
{
get
{
if (m_MyAwesomeObject == null)
m_MyAwesomeObject = new Object();
return m_MyAwesomeObject;
}
}
}
}
I like to keep all initialization for any class property whether primitive or object in the class constructor(s). Keeps the code easier to read. Easier to debug. Plus the intention of a constructor is to initialize your classes properties.
Also for clients developing against your classes it's nice to make sure that all your properties get a default value and all objects get created. Avoids the NullReferenceExceptions, when a client is using your class. For me putting this all in constructors makes it easier to manage.
I do not like to duplicate code, even if it is among a (hopefully) small number of constructors. To that end I tend to favor inline initialization wherever it makes sense.
Generally, requiring a non-default constructor ensures that the instance is in something other than the default state. This also allows immutable classes, which have their own advantages.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have over the course of a few projects developed a pattern for creating immutable (readonly) objects and immutable object graphs. Immutable objects carry the benefit of being 100% thread safe and can therefore be reused across threads. In my work I very often use this pattern in Web applications for configuration settings and other objects that I load and cache in memory. Cached objects should always be immutable as you want to guarantee they are not unexpectedly changed.
Now, you can of course easily design immutable objects as in the following example:
public class SampleElement
{
private Guid id;
private string name;
public SampleElement(Guid id, string name)
{
this.id = id;
this.name = name;
}
public Guid Id
{
get { return id; }
}
public string Name
{
get { return name; }
}
}
This is fine for simple classes - but for more complex classes I do not fancy the concept of passing all values through a constructor. Having setters on the properties is more desirable and your code constructing a new object gets easier to read.
So how do you create immutable objects with setters?
Well, in my pattern objects start out as being fully mutable until you freeze them with a single method call. Once an object is frozen it will stay immutable forever - it cannot be turned into a mutable object again. If you need a mutable version of the object, you simply clone it.
Ok, now on to some code. I have in the following code snippets tried to boil the pattern down to its simplest form. The IElement is the base interface that all immutable objects must ultimately implement.
public interface IElement : ICloneable
{
bool IsReadOnly { get; }
void MakeReadOnly();
}
The Element class is the default implementation of the IElement interface:
public abstract class Element : IElement
{
private bool immutable;
public bool IsReadOnly
{
get { return immutable; }
}
public virtual void MakeReadOnly()
{
immutable = true;
}
protected virtual void FailIfImmutable()
{
if (immutable) throw new ImmutableElementException(this);
}
...
}
Let's refactor the SampleElement class above to implement the immutable object pattern:
public class SampleElement : Element
{
private Guid id;
private string name;
public SampleElement() {}
public Guid Id
{
get
{
return id;
}
set
{
FailIfImmutable();
id = value;
}
}
public string Name
{
get
{
return name;
}
set
{
FailIfImmutable();
name = value;
}
}
}
You can now change the Id property and the Name property as long as the object has not been marked as immutable by calling the MakeReadOnly() method. Once it is immutable, calling a setter will yield an ImmutableElementException.
Final note:
The full pattern is more complex than the code snippets shown here. It also contains support for collections of immutable objects and complete object graphs of immutable object graphs. The full pattern enables you to turn an entire object graph immutable by calling the MakeReadOnly() method on the outermost object. Once you start creating larger object models using this pattern the risk of leaky objects increases. A leaky object is an object that fails to call the FailIfImmutable() method before making a change to the object. To test for leaks I have also developed a generic leak detector class for use in unit tests. It uses reflection to test if all properties and methods throw the ImmutableElementException in the immutable state.
In other words TDD is used here.
I have grown to like this pattern a lot and find great benefits in it. So what I would like to know is if any of you are using similar patterns? If yes, do you know of any good resources that document it? I am essentially looking for potential improvements and for any standards that might already exist on this topic.
For info, the second approach is called "popsicle immutability".
Eric Lippert has a series of blog entries on immutability starting here. I'm still getting to grips with the CTP (C# 4.0), but it looks interesting what optional / named parameters (to the .ctor) might do here (when mapped to readonly fields)...
[update: I've blogged on this here]
For info, I probably wouldn't make those methods virtual - we probably don't want subclasses being able to make it non-freezable. If you want them to be able to add extra code, I'd suggest something like:
[public|protected] void Freeze()
{
if(!frozen)
{
frozen = true;
OnFrozen();
}
}
protected virtual void OnFrozen() {} // subclass can add code here.
Also - AOP (such as PostSharp) might be a viable option for adding all those ThrowIfFrozen() checks.
(apologies if I have changed terminology / method names - SO doesn't keep the original post visible when composing replies)
Another option would be to create some kind of Builder class.
For an example, in Java (and C# and many other languages) String is immutable. If you want to do multiple operations to create a String you use a StringBuilder. This is mutable, and then once you're done you have it return to you the final String object. From then on it's immutable.
You could do something similar for your other classes. You have your immutable Element, and then an ElementBuilder. All the builder would do is store the options you set, then when you finalize it it constructs and returns the immutable Element.
It's a little more code, but I think it's cleaner than having setters on a class that's supposed to be immutable.
After my initial discomfort about the fact that I had to create a new System.Drawing.Point on each modification, I've wholly embraced the concept some years ago. In fact, I now create every field as readonly by default and only change it to be mutable if there's a compelling reason – which there is surprisingly rarely.
I don't care very much about cross-threading issues, though (I rarely use code where this is relevant). I just find it much, much better because of the semantic expressiveness. Immutability is the very epitome of an interface which is hard to use incorrectly.
You are still dealing with state, and thus can still be bitten if your objects are parallelized before being made immutable.
A more functional way might be to return a new instance of the object with each setter. Or create a mutable object and pass that in to the constructor.
The (relatively) new Software Design paradigm called Domain Driven design, makes the distinction between entity objects and value objects.
Entity Objects are defined as anything that has to map to a key-driven object in a persistent data store, like an employee, or a client, or an invoice, etc... where changing the properties of the object implies that you need to save the change to a data store somewhere, and the existence of multiple instances of a class with the same "key" imnplies a need to synchronize them, or coordinate their persistence to the data store so that one instance' changes do not overwrite the others. Changing the properties of an entity object implies you are changing something about the object - not changing WHICH object you are referencing...
Value objects otoh, are objects that can be considered immutable, whose utility is defined strictly by their property values, and for which multiple instances, do not need to be coordinated in any way... like addresses, or telephone numbers, or the wheels on a car, or the letters in a document... these things are totally defined by their properties... an uppercase 'A' object in an text editor can be interchanged transparently with any other uppercase 'A' object throughout the document, you don't need a key to distinguish it from all the other 'A's In this sense it is immutable, because if you change it to a 'B' (just like changing the phone number string in a phone number object, you are not changing the data associated with some mutable entity, you are switching from one value to another... just as when you change the value of a string...
Expanding on the point by #Cory Foy and #Charles Bretana where there is a difference between entities and values. Whereas value-objects should always be immutable, I really don't think that an object should be able to freeze themselves, or allow themselves to be frozen arbitrarily in the codebase. It has a really bad smell to it, and I worry that it could get hard to track down where exactly an object was frozen, and why it was frozen, and the fact that between calls to an object it could change state from thawed to frozen.
That isn't to say that sometimes you want to give a (mutable) entity to something and ensure it isn't going to be changed.
So, instead of freezing the object itself, another possibility is to copy the semantics of ReadOnlyCollection< T >
List<int> list = new List<int> { 1, 2, 3};
ReadOnlyCollection<int> readOnlyList = list.AsReadOnly();
Your object can take a part as mutable when it needs it, and then be immutable when you desire it to be.
Note that ReadOnlyCollection< T > also implements ICollection< T > which has an Add( T item) method in the interface. However there is also bool IsReadOnly { get; } defined in the interface so that consumers can check before calling a method that will throw an exception.
The difference is that you can't just set IsReadOnly to false. A collection either is or isn't read only, and that never changes for the lifetime of the collection.
It would be nice at time to have the const-correctness that C++ gives you at compile time, but that starts to have it's own set of problems and I'm glad C# doesn't go there.
ICloneable - I thought I'd just refer back to the following:
Do not implement ICloneable
Do not use ICloneable in public APIs
Brad Abrams - Design Guidelines, Managed code and the .NET Framework
System.String is a good example of a immutable class with setters and mutating methods, only that each mutating method returns a new instance.
This is an important problem, and I've love to see more direct framework/language support to solve it. The solution you have requires a lot of boilerplate. It might be simple to automate some of the boilerplate by using code generation.
You'd generate a partial class that contains all the freezable properties. It would be fairly simple to make a reusable T4 template for this.
The template would take this for input:
namespace
class name
list of property name/type tuples
And would output a C# file, containing:
namespace declaration
partial class
each of the properties, with the corresponding types, a backing field, a getter, and a setter which invokes the FailIfFrozen method
AOP tags on freezable properties could also work, but it would require more dependencies, whereas T4 is built into newer versions of Visual Studio.
Another scenario which is very much like this is the INotifyPropertyChanged interface. Solutions for that problem are likely to be applicable to this problem.
My problem with this pattern is that you're not imposing any compile-time restraints upon immutability. The coder is responsible for making sure an object is set to immutable before for example adding it to a cache or another non-thread-safe structure.
That's why I would extend this coding pattern with a compile-time restraint in the form of a generic class, like this:
public class Immutable<T> where T : IElement
{
private T value;
public Immutable(T mutable)
{
this.value = (T) mutable.Clone();
this.value.MakeReadOnly();
}
public T Value
{
get
{
return this.value;
}
}
public static implicit operator Immutable<T>(T mutable)
{
return new Immutable<T>(mutable);
}
public static implicit operator T(Immutable<T> immutable)
{
return immutable.value;
}
}
Here's a sample how you would use this:
// All elements of this list are guaranteed to be immutable
List<Immutable<SampleElement>> elements =
new List<Immutable<SampleElement>>();
for (int i = 1; i < 10; i++)
{
SampleElement newElement = new SampleElement();
newElement.Id = Guid.NewGuid();
newElement.Name = "Sample" + i.ToString();
// The compiler will automatically convert to Immutable<SampleElement> for you
// because of the implicit conversion operator
elements.Add(newElement);
}
foreach (SampleElement element in elements)
Console.Out.WriteLine(element.Name);
elements[3].Value.Id = Guid.NewGuid(); // This will throw an ImmutableElementException
Just a tip to simplify the element properties: Use automatic properties with private set and avoid explicitly declaring the data field. e.g.
public class SampleElement {
public SampleElement(Guid id, string name) {
Id = id;
Name = name;
}
public Guid Id {
get; private set;
}
public string Name {
get; private set;
}
}
Here is a new video on Channel 9 where Anders Hejlsberg from 36:30 in the interview starts talking about immutability in C#. He gives a very good use case for popsicle immutability and explains how this is something you are currently required to implement yourself. It was music to my ears hearing him say it is worth thinking about better support for creating immutable object graphs in future versions of C#
Expert to Expert: Anders Hejlsberg - The Future of C#
Two other options for your particular problem that haven't been discussed:
Build your own deserializer, one that can call a private property setter. While the effort in building the deserializer at the beginning will be much more, it makes things cleaner. The compiler will keep you from even attempting to call the setters and the code in your classes will be easier to read.
Put a constructor in each class that takes an XElement (or some other flavor of XML object model) and populates itself from it. Obviously as the number of classes increases, this quickly becomes less desirable as a solution.
How about having an abstract class ThingBase, with subclasses MutableThing and ImmutableThing? ThingBase would contain all the data in a protected structure, providing public read-only properties for the fields and protected read-only property for its structure. It would also provide an overridable AsImmutable method which would return an ImmutableThing.
MutableThing would shadow the properties with read/write properties, and provide both a default constructor and a constructor that accepts a ThingBase.
Immutable thing would be a sealed class that overrides AsImmutable to simply return itself. It would also provide a constructor that accepts a ThingBase.
I dont like the idea of being able to change an object from a mutable to an immutable state, that kind of seems to defeat the point of design to me. When are you needing to do that? Only objects which represent VALUES should be immutable
You can use optional named arguments together with nullables to make an immutable setter with very little boilerplate. If you really do want to set a property to null then you may have some more troubles.
class Foo{
...
public Foo
Set
( double? majorBar=null
, double? minorBar=null
, int? cats=null
, double? dogs=null)
{
return new Foo
( majorBar ?? MajorBar
, minorBar ?? MinorBar
, cats ?? Cats
, dogs ?? Dogs);
}
public Foo
( double R
, double r
, int l
, double e
)
{
....
}
}
You would use it like so
var f = new Foo(10,20,30,40);
var g = f.Set(cat:99);