IEnumerable<T> vs. Array - c#

I'm trying to get the idea, what would be the best way to publish a Readonly List of objects as a public method?
From Eric Lippert's Blog, Arrays are kinda bad, because someone could easily add a new Entry. So one would have to pass a new Array every time the method is called.
He suggests, to pass IEnumerable<T>, since this is per definition read only (no add, remove methods), which I practiced for quite sometime.
But in our new project, people even started to create Arrays of these IEnumerables, because they don't know the DataSource behind, so they get a : Handling warning for possible multiple enumeration of IEnumerable
I'm interested in a technical approach, how one would solve this puzzle. The only solution I came up so far would be to use a IReadOnlyCollection, but this would be way more explicit than an IEnumerable.
What is best practice to publish such lists, which shouldn't be changed, but should be declared as In-Memory Lists?

Usually - and since a while - this solved using immutable collections.
Your public properties should be, for example, of type IImmutableList<T>, IImmutableHashSet<T> and so on.
Any IEnumerable<T> can be converted to an immutable collection:
someEnumerable.ToImmutableList();
someEnumerable.ToImmutableHashSet();
... and so on.
This way you can work with private properties using mutable collections and provide a public surface of immutable collections only.
For example:
public class A
{
private List<string> StringListInternal { get; set; } = new List<string>();
public IImmutableList<string> StringList => StringListInternal.ToImmutableList();
}
There's also an alternate approach using interfaces:
public interface IReadOnlyA
{
IImmutableList<string> StringList { get; }
}
public class A : IReadOnlyA
{
public List<string> StringList { get; set; } = new List<string>();
IImmutableList<string> IReadOnlyA.StringList => StringList.ToImmutableList();
}
Check that IReadOnlyA has been explicitly-implemented, thus both mutable and immutable StringList properties can co-exist as part of the same class.
When you want to expose an immutable A, then you return your A objects upcasted to IReadOnlyA and upper layers won't be able to mutate the whole StringList in the sample above:
public IReadOnlyA DoStuff()
{
return new A();
}
IReadOnlyA a = DoStuff();
// OK! IReadOnly.StringList is IImmutableList<string>
IImmutableList<string> stringList = a.StringList;
Avoiding converting the mutable list to immutable list every time
It should be a possible solution to avoid converting the source list into immutable list each time immutable one is accessed.
Equatable members
If type of items overrides Object.Equals and GetHashCode, and optionally implements IEquatable<T>, then both public immutable list property access may look as follows:
public class A : IReadOnlyA
{
private IImmutableList<string> _immutableStringList;
public List<string> StringList { get; set; } = new List<string>();
IImmutableList<string> IReadOnlyA.StringList
{
get
{
// An intersection will verify that the entire immutable list
// contains the exact same elements and count of mutable list
if(_immutableStringList.Intersect(StringList).Count == StringList.Count)
return _immutableStringList;
else
{
// the intersection demonstrated that mutable and
// immutable list have different counts, thus, a new
// immutable list must be created again
_immutableStringList = StringList.ToImmutableList();
return _immutableStringList;
}
}
}
}

I do not think immutable is the way to go
int[] source = new int[10000000];//uses 40MB of memory
var imm1 = source.ToImmutableArray();//uses another 40MB
var imm2 = source.ToImmutableArray();//uses another 40MB
List behaves the same way. If I want to make full copy every time, I do not have to care about what user does with that array. Making it immutable does not protect content of objects in the collection either, they can be changed freely. #HansPassant suggestion seems to be best
public class A
{
protected List<int> list = new List<int>(Enumerable.Range(1, 10000000));
public IReadOnlyList<int> GetList
{
get { return list; }
}
}

For a collection that you don't intend to modify, IEnumerable<T> is still probably the safest option, plus it allows any collection type to be pased in, not just arrays. The reason for that warning is because of the possibility that the IEnumerable represents a query that uses deferred execution, meaning that a potentially expensive operation could be executed multiple times.
Note that there's not an interface that distinguish in-memory collections versus potentially deferred-execution wrappers. That question has been asked before.
The fix for that is do not enumerate the source multiple times. If the code needs perform multiple iteartions (which may be legitimate) then hydrate the collection to a List<T> before iterating.

IEnumerable is a read-only interface which hides implementation from user. Some can argue, that user may cast IEnumerable to list and add new items, but that means two things:
User violates provided API
You can't stop user from reflection usage
IEnumerable describes behavior, while List is an implementation of that behavior. When you use IEnumerable, you give the compiler a chance to defer work until later, possibly optimizing along the way. If you use ToList() you force the compiler to prepare the results right away.
I use IEnumerable Whenever working with LINQ expressions, because by only specifying the behavior, I give LINQ a chance to defer evaluation and possibly optimize the program.
To prevent any modifications to the List<T> object, expose it only through the ReadOnlyCollection<T> wrapper which does not expose methods that modify the collection. However, if changes are made to the underlying List<T> object, the read-only collection reflects those changes as described in MSDN.
Take a look at The New Read-Only Collections in .NET 4.5 please.

I've been programming for longer than I care to remember, and never had such a requirement to protect a list from getting modified. I'm not saying it's not a possible requirement, I'm just saying it is very rare to need such a requirement. If you have a list circulating around in your app, then most likely you have to fix your design. If you need help with that, let us how you're using the list.
The examples you're giving in your question and comments are not good examples for when to require an immutable or read-only list. Let's discuss them one by one.
You mentioned publishing it as an API. By definition, anything you return from an API is no yours anymore and you shouldn't care how it is used. In fact, once it leaves your API, it is now in the API client's domain, and they can do whatever they want with it. Aside from the fact that you cannot protect it once it is in their domain, you should not dictate how they will use it. More importantly, you should never accept anything as input in your API, even if it is the same list that you returned earlier and you think that you protected. All input MUST be validated appropriately.
Perhaps, you did not really mean API, but more like a DLL library that you share in your projects. Whether it is a DLL or just a class in your project, the same principle applies. When you return something, it is up to the user how to use it. And you should never accept the same thing (list or whatever) back without validation. Similarly, you should never expose an internal member of your class, whether it's a list or a single value. After all, that's the whole idea behind using properties instead of marking the members as public. When you create a property for a single-value member, a copy of the value is returned. Similarly, you should create a property for your list and return a copy, not the list itself.
If you really need a list that is globally accessible, and you want to load it only once, expose it to other classes, protect it against modification, and it is too big to make a copy of it. You can look into some designs like wrapping it in a Singleton and/or make it read-only as per Antonín Lejsek's answer. In fact, his answer can be easily converted to a Singleton by marking the constructor as private, thanks to the simplified Singleton implementation in C#.

Related

C#, making public members their methods private

I the following class:
public class Humptydump
{
public Humptydump()
{ }
public Rectangle Rectangle { public get; private set; }
}
in this class the Rectangle class comes from system.drawing,
how do i make it so people cannot access the methods of the rectangle, but can get the rectangle itself?
In your case, it will "just work".
Since Rectangle is a struct, your property will return a copy of the Rectangle. As such, it will be impossible for anybody to modify your Rectangle directly unless you expose methods to allow this.
That being said, it's impossible, in general, to provide access to a type without also providing access to methods defined on the type. The methods go along with the type. The only alternative in those cases would be to create a new type that exposed the data you choose without the data or methods you wish to be exposed, and provide access to that.
If rectangle was not a struct, one possible thing would be deriving it and hiding those methods:
public class DerivedClass : BaseClass
{
new private SomeReturnType SomeMethodFromBaseClasse(SameParametersAsInBaseClassAndSameSignature
{
//this simply hides the method from the user
//but user will still have the chance to cast to the BaseClass and
//access the methods from there
}
}
Are you talking about the Rectangle object specifically, or on a more general term and just using that as an example?
If you're talking on a more general term, this is something that comes up very often in refactoring patterns. This most commonly happens with collections on objects. If you expose, for example, a List<T> then even if the setter is private then people can still modify the collection through the getter, since they're not actually setting the collection when they do so.
To address this, consider the Law of Demeter. That is, when someone is interacting with a collection exposed by an object, should they really be interacting with the object itself? If so, then the collection shouldn't be exposed and instead the object should expose the functionality it needs to.
So, again in the case of a collection, you might end up with something like this:
class SomeObject
{
private List<AnotherObject> Things;
public void AddAnotherObject(AnotherObject obj)
{
// Add it to the list
}
public void RemoveAnotherObject(AnotherObject obj)
{
// Remove it from the list
}
}
Of course, you may also want to expose some copy of the object itself for people to read, but not modify. For a collection I might do something like this:
public IEnumerable<AnotherObject> TheObjects
{
get { return Things; }
}
That way anybody can see the current state of the objects and enumerate over them, but they can't actually modify it. Not because it doesn't have a setter, but because the IEnumerable<T> interface doesn't have options to modify the enumeration. Only to enumerate over it.
For your case with Rectangle (or something similar which isn't already a struct that's passed by value anyway), you would do something very similar. Store a private object and provide public functionality to modify it through the class itself (since what we're talking about is that the class needs to know when its members are modified) as well as functionality to inspect it without being able to modify what's being inspected. Something like this, perhaps:
class SomeObject
{
private AnotherObject Thing;
public AnotherObject TheThing
{
get { return Thing.Copy(); }
}
public void RenameThing(string name)
{
Thing.Name = name;
}
// etc.
}
In this case, without going into too much detail about what AnotherObject is (so consider this in some ways pseudo-code), the property to inspect the inner object returns a copy of it, not the actual reference to the actual object. For value types, this is the default behavior of the language. For reference types, you may need to strike a balance between this and performance (if creating a copy is a heavy operation).
In this case you'll also want to be careful of making the interface of your object unintuitive. Consuming code might expect to be able to modify the inner object being inspected, since it exposes functionality to modify itself. And, indeed, they can modify the copy that they have. How you address this depends heavily on the conceptual nature of the objects and how they relate to one another, which a contrived example doesn't really convey. You might create a custom DTO (even a struct) which returns only the observable properties of the inner object, making it more obvious that it's a copy and not the original. You might just say that it's a copy in the intellisense comments. You might make separate properties to return individual data elements of the inner object instead of a single property to return the object itself. There are plenty of options, it's up to you to determine what makes the most sense for your objects.

Refactoring into sub classes

public class ScheduleRatesController
{
protected CoreDataManager dataManager;
public ScheduleRatesController()
{
dataManager = new CoreDataManager();
}
// testing
public ScheduleRatesController(CoreDataManager manager)
{
dataManager = manager;
}
public virtual void GetTranQuotesToFillRatesAndPayments(ref List<int> ids)
{
ids.AddRange(new List<int>());
}
}
So to give you guys some background, we're splitting one DB query into a bunch of different ones, and we want subclasses to basically each take on a DB call for their GetTranQuotesToFillRatesAndPayments() method that represents it's specific query.
What you see above is the base class I have. I made those two methods virtual as I plan on having subclasses override them to perform their own stuff. So one could be like:
public override void GetTranQuotesToFillRatesAndPayments(ref List<int> ids)
{
ids.AddRange(dataManager.GetLoanTranQuotes());
}
and etc. My question is, is this the best/cleanest way to perform a pattern like this?
The code that calls this is going to contain a huge list of filtered id's, that it's going to need to fill by calling each classes call to GetTranQuotesToFillRatesAndPayments(). Let me know if this doesn't make sense. I'm kind of getting turned off by the fact that I'm going to need to call the same method like 6 times, each on a different class. I think that might be messy in itself even though the goal of it was to make it clean. I don't want to have something like this on the calling side:
List<int> ids = new List<int>();
ScheduleRatesController controller = new LoanController();
controller.GetTranQuotesToFillRatesAndPayments(ref ids);
controller = new TradeController();
controller.GetTranQuotesToFillRatesAndPayments(ref ids);
etc.
Let me know if you need any more background or info.
Thanks.
Several design remarks:
Using the ref keyword usually indicates design problems and should be avoided. There is no need to pass a reference value using the ref keyword (any List<T> is always passed by reference). Your program would work equally without it.
A better idea than passing your list to the method would be to return your data from the method, and allow callers to decide what to do with it. Maybe you will only want to find a single value at some other place in your program, and creating a new list is an overkill. Also, you should try to add as little functionality as possible to each class (Single Responsibility Principle), and your class is right now responsible for fetching the data and deciding how it should be stored.
Naming: your method name is really complex. Also, the name "controller" doesn't usually represent an object responsible for fetching data.
On the other hand, you have a CoreDataManager class (btw, Manager is a bad suffix for any class), which appears to contain a bunch of methods which return various data. What is the need for ScheduleRatesController then? Does it only copy this to a list?
Business logic should be separated from your Data access layer. You should consider using Repository pattern, or similar (check this answer, for example), to ensure that your data class only fetches the data from the DB.
If you have several classes which need to fulfill a certain contract, start by creating the interface which they need to implement. Don't think about reusing code at this time. Your code, for example, forces all subclasses to use the CoreDataManager, while one day it may turn out that a certain "controller" might need to be composed of different objects.
Use a List<Func<List<int>,List<int>>>. Which is basically a list of functions with the following type signature:
List<int> MyFunc(List<int> foo);
You can then pass the list of functions to a method that works like the following:
public List<int> GetAllIds(List<Func<List<int>,List<int>>> functionList) {
var listOfIds = new List<int>();
foreach(var f in functionList) {
listOfIds = f(listOfIds);
}
return listOfIds;
}
You can use lambdas to compose functionList like so:
functionList.Add(list => {
list.AddRange(dataManager.GetLoanTranQuotes());
return list;
});
Now you do not have to depend on any specific inheritance hierarchy. You can use function composition to produce the whole list.

In API code, is it a good idea to use a private setter for list type C# properties?

I'm looking for an opinion on something. Consider the following code from a class called SomeApiObject:
// Property with private setter
public IList<string> SomeList
{
get;
private set;
}
// Constructor
public SomeApiObject()
{
SomeList = new List<string>();
}
With this setup, users of the class SomeApiObject cannot reassign the SomeList property, but what they can do is to manipulate the existing list by using methods such as Add(), Remove(), and Clear().
The upside of this pattern is that the property is guaranteed to never be null, which can be a very convenient assumption to make as a user is working with the API, since it means the user can always iterate over the list, get the list's size, or add to it without ever having to check for null.
I see a few downsides. For one, it's not necessarily obvious to a user that the list is intended to be writable by manipulating its contents. For another, I could envision situations where manipulating the list is less convenient syntactically or possibly worse in performance than assigning a new list.
I'm on the fence with this one, and I'm seeking opinions.
Are the potential downsides just too obnoxious for a user of the API?
Is the guarantee of never being null as nice a feature as I think it is?
EDIT:
I'm already convinced of the benefits of using some sort of "never null" pattern. What I'm more interested in is for someone to play devil's advocate and show me why having a private setter on a list that's meant to be manipulated might be annoying and/or prohibitive from the perspective of a user of the API.
I released a .NET API wrapper some time ago, and so far a few users have expressed confusion over how to assign values to properties like this one.
Never null is a good design feature. In regards to only exposing lists as read only properties this is put forward as a recommendation in the my favorite guidelines book: http://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321545613
Though a better approach is not to allow external callers to manipulate the state of your object directly and to make the class immutable:
public class MyClass
{
private List<string> _inner = new List<string>();
public IEnumerable<string> Items
{
get { return _inner.GetEnumerator(); }
}
public void AddItem(string item);
{
_inner.Add(item);
}
}
If you want to remove the possibility of users getting a reference to the list then simply manipulating it externally in an unintended manner, then you should change your property to only return an IEnumerable instead.
public IEnumerable<string> SomeList
{
get { return list.GetEnumerator(); }
private set {}
}
This will allow the user to still make use of the collection (also will support linq) and will protect the collection from external manipulation.
One other point to consider is that the question depends on whether the object "owns" the list (composition) or "has" the list (aggregation). If the object owns the list, the setter should be private; if it simply has the list from another object, the setter could possibly be public.
A complication in the composition case (other than the possibility of the list being assigned a null value) is that a public setter causes the class to cede all control over the implementation of the list. Suppose, for instance, you have the implementation:
public IList<string> SomeList
{
get;
private set;
}
public SomeApiObject()
{
SomeList = new List<string>();
}
Now suppose in a subsequent version, you want to use SomeSpecializedList, which implements IList<string>, instead of List<String>. You could easily refactor:
private SomeSpecializedList specializedList;
public IList<string> SomeList
{
get {return specializedList;}
private set {specializedList = value as SomeSpecializedList;}
}
public SomeApiObject()
{
SomeList = new SomeSpecializedList<string>();
}
Only the private implementation has changed; users of the class are unaffected. But if the setter were public, the client could have potentially passed any IList instance into SomeList, and this would be a breaking change.
it depends on the situation. in some cases, it might make sense to be able to have a null list, in other not so much. you have to ask yourself if it makes sense. .net itself does it both ways.
As much as I hate saying this, it really depends on what you're trying to do with your API. If you want to provide the user with a collection that they can work with, then #Matthew's answer is appropriate. If you want to hide the collection or only allow certain actions to be permitted (like Add, Remove, etc.), then you could hide the collection and expose a facade to the collection:
private IList<string> _someList = new List<string>();
public void Add(string item){ _someList.Add(item); }
public string Remove(string item) { return _someList.Remove(item); }
...
Hope this helps.

Convenience or "lazy programming" IList management - protecting IList.Add method

How do you manage this simple scenario when you have an object with a list of items. EG:
public class ContainerObject
{
IList<ChildObject> Children { get; }
public void AddCustom(ChildObject toAdd)
{
// Some validation ...
Children.Add(toAdd);
}
}
Assuming the collection is initialised to an implementation of IList, is there any way in which to control the way in which items are added to the list?
For example, I have another method on the ContainerObject class that takes a ChildObject and adds it to the list. This method is required to perform some basic validation on the ChildObject before adding it.
I am being lazy in that I don't want to mess around and write a custom list interface (without an add method) that consuming developers need to implement. I am also using the ToList() method on the IQueryable interface so this is another reason for sticking with IList - it just works.
So, is there an approach in which you can police how items are added to the IList instance i.e. prevent use of the Add method and only allow adding to the collection via my custom method, or am I just asking for the impossible? ... and being lazy :(
I can think of a few hacky ways in which to check when items are added via my custom method or directly on the list but these seem hacky!
Anyone experience anything similar to this? If so, what did you do?
You can make your property return a wrapper around the original list using ReadOnlyCollection<T>. This will ensure that callers don't add any items themselves. You can keep a reference to the original mutable list. Note that because the read-only collection is only a wrapper, callers which cache the read-only collection will still see additions that you make to the original list. That may or may not be a good thing depending on your expected use.
EDIT: To explain my caching comment...
Suppose a client did:
IList<ChildObject> originalChildren = container.Children;
container.AddChild(new ChildObject());
IList<ChildObject> updatedChildren = container.Children;
with the Children property implemented like this:
private IList<ChildObject> children = new List<ChildObject>();
public IList<ChildObject> Children
{
get { return new ReadOnlyCollection<ChildObject>(children); }
}
Then originalChildren and updateChildren would both have the same contents - the returned ReadOnlyCollection wouldn't be a snapshot of the collection of children at the first line. It would just be a wrapper around the collection. Clients wouldn't be able to rely on it not changing - they just wouldn't be able to change it themselves.
Return a ReadOnlyCollection to the world wrapping your list which you manage the Adds to.

Immutable object pattern in C# - what do you think? [closed]

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);

Categories