I'm building a service for accessing my database with Entity Framework in ASP.NET MVC 5.
So I'm writing first a base service with his interface. But I'm worry about a little thing.
Usually I return an IEnumerable<T> in my interface, but that often leads to ToList() calls in the code.
So I was wondering what is the best to return in such an interface.
I could just return IList but I'm afraid that it may be too much and that I won't need all of the methods provided with IList.
Here's my code :
public interface IBaseService<T>
{
T Add(T obj);
T Update(T obj);
T Remove(string id);
T Get(string id);
ICollection<T> Find(Expression<Func<bool, T>> func);
ICollection<T> GetAll();
}
You said that
Usually I return an IEnumerable in my interface, but that often
leads to ToList() calls in the code.
You have to find out why you are calling ToList() on the results. It's possible, but unlikely, that you want to modify the result (add\remove items). It's generally not a good practice to return modifiable collection from methods like Find or GetAll, but you can return ICollection<T> or IList<T> (if you also need fast access via indexer or to insert\remove at specific positions).
However much more likely that you call to ToList to figure out how many elements are there and\or to access specific elements. If you need just Count - return IReadOnlyCollection<T> which extends IEnumerable<T> with just Count property. If you also need fast access via indexer - return IReadOnlyList<T> which extends IReadOnlyCollection<T> with indexer.
Both Array and List<T> implement all those interfaces so you can just return those classes as is:
static IReadOnlyList<string> Test() {
return new string[0]; // fine
}
However, when returning List this way - caller might cast it back to IList<T> and still modify it. That's not a problem usually, but if you want to prevent that, use AsReadOnly on list (it will not copy anything to the new list so don't worry about perfomance):
static IReadOnlyList<string> Test() {
return new List<string>().AsReadOnly(); // not required but good practice
}
It depends on your intention. In most cases your return type should probably be IReadOnlyCollection<T>. In rare cases where you want the caller to be able to modify the collection, you can return ICollection<T>. Use IEnumerable<T> only if you are certain that the caller will only require forward iteration.
I guess the purest solution would be to go with IEnumerable<T>, but it comes down to setting a convention in your solution. If you're responsible for architecture, you might as well decide to return List<T> just to have the comfort of broader set of methods at hand.
Related
So in my class I have this private readonly member ICollection<IMusicItem> playlist. I would prefer to use the interface ICollection<T>.
I would like to use the List<T>.AddRange(IEnumerable<T> items). In my method would it be dangerous to cast the ICollection to a List<T> even if I instantiate the ICollection<T> as a new List<T>() in the constructor.
Is this bad practice, is there a better way of doing this?
Or is it just better to have a List<T>
It's bad practice, because it breaks encapsulation. Using an interface is good, but it's pointless if you have to cast the object back to a concrete type. Act as if you didn't know the concrete type, or it's a future bug waiting to happen if you decide to switch to another type later on.
Use an extension method instead:
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
collection.Add(item);
}
Note: It's better to expose interfaces in a public API so you're free to change the implementing object later, but it's a matter of style whether to do it on private fields. You may as well use the concrete class.
It's not dangerous (when done right), just pointless.
if (playlist is IList<IMusicItem>)
{
(playList as IList<IMusicItem>).AddRange(items);
}
else
{
// still need a foreach here
}
The real issue is "I would prefer to use the interface ICollection<T>".
Why exactly? Your question suggests it always is a List, so why not expose it as such?
Exposing it as a more general ICollection<> only makes sense when other implementations than List might exist, and then the casting is useless.
I have spent quite a few hours pondering the subject of exposing list members. In a similar question to mine, Jon Skeet gave an excellent answer. Please feel free to have a look.
ReadOnlyCollection or IEnumerable for exposing member collections?
I am usually quite paranoid to exposing lists, especially if you are developing an API.
I have always used IEnumerable for exposing lists, as it is quite safe, and it gives that much flexibility. Let me use an example here:
public class Activity
{
private readonly IList<WorkItem> workItems = new List<WorkItem>();
public string Name { get; set; }
public IEnumerable<WorkItem> WorkItems
{
get
{
return this.workItems;
}
}
public void AddWorkItem(WorkItem workItem)
{
this.workItems.Add(workItem);
}
}
Anyone who codes against an IEnumerable is quite safe here. If I later decide to use an ordered list or something, none of their code breaks and it is still nice. The downside of this is IEnumerable can be cast back to a list outside of this class.
For this reason, a lot of developers use ReadOnlyCollection for exposing a member. This is quite safe since it can never be cast back to a list. For me I prefer IEnumerable since it provides more flexibility, should I ever want to implement something different than a list.
I have come up with a new idea I like better. Using IReadOnlyCollection:
public class Activity
{
private readonly IList<WorkItem> workItems = new List<WorkItem>();
public string Name { get; set; }
public IReadOnlyCollection<WorkItem> WorkItems
{
get
{
return new ReadOnlyCollection<WorkItem>(this.workItems);
}
}
public void AddWorkItem(WorkItem workItem)
{
this.workItems.Add(workItem);
}
}
I feel this retains some of the flexibility of IEnumerable and is encapsulated quite nicely.
I posted this question to get some input on my idea. Do you prefer this solution to IEnumerable? Do you think it is better to use a concrete return value of ReadOnlyCollection? This is quite a debate and I want to try and see what are the advantages/disadvantages that we all can come up with.
EDIT
First of all thank you all for contributing so much to the discussion here. I have certainly learned a ton from each and every one and would like to thank you sincerely.
I am adding some extra scenarios and info.
There are some common pitfalls with IReadOnlyCollection and IEnumerable.
Consider the example below:
public IReadOnlyCollection<WorkItem> WorkItems
{
get
{
return this.workItems;
}
}
The above example can be casted back to a list and mutated, even though the interface is readonly. The interface, despite it's namesake does not guarantee immutability. It is up to you to provide an immutable solution, therefore you should return a new ReadOnlyCollection. By creating a new list (a copy essentially), the state of your object is safe and sound.
Richiban says it best in his comment: a interface only guarantees what something can do, not what it cannot do.
See below for an example:
public IEnumerable<WorkItem> WorkItems
{
get
{
return new List<WorkItem>(this.workItems);
}
}
The above can be casted and mutated, but your object is still immutable.
Another outside the box statement would be collection classes. Consider the following:
public class Bar : IEnumerable<string>
{
private List<string> foo;
public Bar()
{
this.foo = new List<string> { "123", "456" };
}
public IEnumerator<string> GetEnumerator()
{
return this.foo.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
The class above can have methods for mutating foo the way you want it to be, but your object can never be casted to a list of any sort and mutated.
Carsten Führmann makes a fantastic point about yield return statements in IEnumerables.
One important aspect seems to be missing from the answers so far:
When an IEnumerable<T> is returned to the caller, they must consider the possibility that the returned object is a "lazy stream", e.g. a collection built with "yield return". That is, the performance penalty for producing the elements of the IEnumerable<T> may have to be paid by the caller, for each use of the IEnumerable. (The productivity tool "Resharper" actually points this out as a code smell.)
By contrast, an IReadOnlyCollection<T> signals to the caller that there will be no lazy evaluation. (The Count property, as opposed to the Count extension method of IEnumerable<T> (which is inherited by IReadOnlyCollection<T> so it has the method as well), signals non-lazyness. And so does the fact that there seem to be no lazy implementations of IReadOnlyCollection.)
This is also valid for input parameters, as requesting an IReadOnlyCollection<T> instead of IEnumerable<T> signals that the method needs to iterate several times over the collection. Sure the method could create its own list from the IEnumerable<T> and iterate over that, but as the caller may already have a loaded collection at hand it would make sense to take advantage of it whenever possible. If the caller only has an IEnumerable<T> at hand, he only needs to add .ToArray() or .ToList() to the parameter.
What IReadOnlyCollection does not do is prevent the caller to cast to some other collection type. For such protection, one would have to use the class ReadOnlyCollection<T>.
In summary, the only thing IReadOnlyCollection<T> does relative to IEnumerable<T> is add a Count property and thus signal that no lazyness is involved.
Talking about class libraries, I think IReadOnly* is really useful, and I think you're doing it right :)
It's all about immutable collection... Before there were just immutables and to enlarge arrays was a huge task, so .net decided to include in the framework something different, mutable collection, that implement the ugly stuff for you, but IMHO they didn't give you a proper direction for immutable that are extremely useful, especially in a high concurrency scenario where sharing mutable stuff is always a PITA.
If you check other today languages, such as objective-c, you will see that in fact the rules are completely inverted! They quite always exchange immutable collection between different classes, in other words the interface expose just immutable, and internally they use mutable collection (yes, they have it of course), instead they expose proper methods if they want let the outsiders change the collection (if the class is a stateful class).
So this little experience that I've got with other languages pushes me to think that .net list are so powerful, but the immutable collection were there for some reason :)
In this case is not a matter of helping the caller of an interface, to avoid him to change all the code if you're changing internal implementation, like it is with IList vs List, but with IReadOnly* you're protecting yourself, your class, to being used in not a proper way, to avoid useless protection code, code that sometimes you couldn't also write (in the past in some piece of code I had to return a clone of the complete list to avoid this problem).
My take on concerns of casting and IReadOnly* contracts, and 'proper' usages of such.
If some code is being “clever” enough to perform an explicit cast and break the interface contract, then it is also “clever” enough to use reflection or otherwise do nefarious things such as access the underlying List of a ReadOnlyCollection wrapper object. I don’t program against such “clever” programmers.
The only thing that I guarantee is that after said IReadOnly*-interface objects are exposed, then my code will not violate that contract and will not modified the returned collection object.
This means that I write code that returns List-as-IReadOnly*, eg., and rarely opt for an actual read-only concrete type or wrapper. Using IEnumerable.ToList is sufficient to return an IReadOnly[List|Collection] - calling List.AsReadOnly adds little value against “clever” programmers who can still access the underlying list that the ReadOnlyCollection wraps.
In all cases, I guarantee that the concrete types of IReadOnly* return values are eager. If I ever write a method that returns an IEnumerable, it is specifically because the contract of the method is that which “supports streaming” fsvo.
As far as IReadOnlyList and IReadOnlyCollection, I use the former when there is 'an' implied stable ordering established that is meaningful to index, regardless of purposeful sorting. For example, arrays and Lists can be returned as an IReadOnlyList while a HashSet would better be returned as an IReadOnlyCollection. The caller can always assign the I[ReadOnly]List to an I[ReadOnly]Collection as desired: this choice is about the contract exposed and not what a programmer, “clever” or otherwise, will do.
It seems that you can just return an appropriate interface:
...
private readonly List<WorkItem> workItems = new List<WorkItem>();
// Usually, there's no need the property to be virtual
public virtual IReadOnlyList<WorkItem> WorkItems {
get {
return workItems;
}
}
...
Since workItems field is in fact List<T> so the natural idea IMHO is to expose the most wide interface which is IReadOnlyList<T> in the case
!! IEnumerable vs IReadOnlyList !!
IEnumerable has been with us from the beginning of time. For many years, it was a de facto standard way to represent a read-only collection. Since .NET 4.5, however, there is another way to do that: IReadOnlyList.
Both collection interfaces are useful.
<>
The extension method ToList() returns a List<TSource>. Following the same pattern, ToDictionary() returns a Dictionary<TKey, TSource>.
I am curious why those methods do not type their return values as IList<TSource> and IDictionary<TKey, TSource> respectively. This seems even odder because ToLookup<TSource, TKey> types its return value as an interface instead of an actual implementation.
Looking at the source of those extension methods using dotPeek or other decompiler, we see the following implementation (showing ToList() because it is shorter):
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return new List<TSource>(source);
}
So why does this method type its return value as a specific implementation of the interface and not the interface itself? The only change would be the return type.
I am curious because the IEnumerable<> extensions are very consistent in their signatures, except for those two cases. I always thought it to be a bit strange.
Additionally, to make things even more confusing, the documentation for ToLookup() states:
Creates a Lookup from an IEnumerable according to a
specified key selector function.
but the return type is ILookup<TKey, TElement>.
In Edulinq, Jon Skeet mentions that the return type is List<T> instead of IList<T>, but does not touch the subject further.
Extensive searching has yielded no answer, so here I ask you:
Is there any design decision behind not typing the return values as interfaces, or is it just happenstance?
Returning List<T> has the advantage that those methods of List<T> that are not part of IList<T> are easily used. There are a lot of things you can do with a List<T> that you cannot do with a IList<T>.
In contrast, Lookup<TKey, TElement> has only one available method that ILookup<TKey, TElement> does not have (ApplyResultSelector), and you probably would not end up using that anyway.
These kind of decisions may feel arbitrary but I guess that ToList() returns List<T> rather than an interface because List<T> both implements IList<T> but it adds other members not present in a regular IList<T>-typed object.
For example, AddRange().
See what IList<T> should implement (http://msdn.microsoft.com/en-us/library/5y536ey6.aspx):
public interface IList<T> : ICollection<T>,
IEnumerable<T>, IEnumerable
And List<T> (http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx):
public class List<T> : IList<T>, ICollection<T>,
IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>,
IEnumerable
Maybe your own code doesn't require IReadOnlyList<T>, IReadOnlyCollection<T> or ICollection, but other components on .NET Framework and other products may rely on a more specialized list object and that's why .NET dev team decided to do not return an interface.
Don't feel always return an interface is the best practice. It's if your code or third-party ones require such encapsulation.
There are a number of advantages to just having a List over an IList. To begin with, List has methods that IList does not. You also know what the implementation is which allows you to reason about how it will behave. You know it can efficiently add to the end, but not the start, you know that it's indexer is very fast, etc.
You don't need to worry about your structure being changed to a LinkedList and wrecking the performance of your application. When it comes to data structures like this it really is important in quite a lot of contexts to know how your data structure is implemented, not just the contract that it follows. It's behavior that shouldn't ever change.
You also can't pass an IList to a method accepting a List, which is something that you see quite a lot of. ToList is frequently used because the person really needs an instance of List, to match a signature they can't control, and IList doesn't help with that.
Then we ask ourselves what advantages there are to returning IList. Well, we could possibly return some other implementation of a list, but as mentioned before this is likely to have very detrimental consequences, almost certainly much more than could possibly be gained from using any other type. It might give you warm fuzzies to be using an interface instead of an implementation, but even that is something I don't feel is a good mentality (in general or) in this context. As a rule returning an interface is generally not preferable to returning a concrete implementation. "Be liberal in what you accept and specific in what you provide." The parameters to your methods should, where possible, be interfaces defining the least amount of functionality you need to that your caller can pass in any implementation that does what you need of it, and you should provide as concrete of an implementation as the caller is "allowed" to see so that they can do as much with the result as that object is capable of. Passing an interface is restricting that value, which is only occasionally something that you want to do.
So now we move onto, "Why return ILookup and not Lookup?" Well, first off Lookup isn't a public class. There is no Lookup in System.Collections.*. The Lookup class that is exposed through LINQ exposes no constructors publicly. You're not able to use the class except through ToLookup. It also exposes no functionality that isn't already exposed through ILookup. In this particular case they designed the interface specifically around this exact method (ToLookup) and the Lookup class is a class specifically designed to implement that interface. Because of all of this virtually all of the points discussed about List just don't apply here. Would it have been a problem to return Lookup instead, no, not really. In this case it really just doesn't matter much at all either way.
In my opinion returning a List<T> is justified by the fact that the method name says ToList. Otherwise it would have to be named ToIList. It is the very purpose of this method to convert an unspecific IEnumerable<T> to the specific type List<T>.
If you had a method with an unspecific name like GetResults, then a return type like IList<T> or IEnumerable<T> would seem appropriate to me.
If you look at the implementation of the Lookup<TKey, TElement> class with reflector, you'll see a lot of internal members, that are only accessible to LINQ itself. There is no public constructor and Lookup objects are immutable. Therefore there would be no advantage in exposing Lookup directly.
Lookup<TKey, TElement> class seems to be kind of LINQ-internal and is not meant for public use.
I believe that the decision to return a List<> instead of an IList<> is that one of the more common use cases for calling ToList is to force immediate evaluation of the entire list. By returning a List<> this is guaranteed. With an IList<> the implementation can still be lazy, which would defeat the "primary" purpose of the call.
This is one of the common things that programmers have difficulty understanding around the use of interfaces and concrete types.
Returning a concrete List<T> that implements IList<T> only gives the method consumer more information. Here is what the List object implements (via MSDN):
[SerializableAttribute]
public class List<T> : IList<T>, ICollection<T>, IList, ICollection,
IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
Returning as a List<T> gives us the ability to call members on all of these interfaces in addition to List<T> itself. For example we could only use List.BinarySearch(T) on a List<T>, as it exists in List<T> but not in IList<T>.
In general to maximize flexibility of our methods, we should take the most abstract types as parameters (ie. only the things we're going to use) and return the least abstract type possible (to allow a more functional return object).
In general when you call ToList() on a method you're looking for a concrete type otherwise the item could stay as type IEnumerable. You don't need to convert to a List unless you're doing something that requires a concrete list.
The short answer is that in general returning the most specific type available is recommended by the authoritative Framework Design Guidelines. (sorry I don't have a citation on hand, but I remember this clearly since it stuck out in contrast to the Java community guidelines which prefer the opposite).
This makes sense to me. You can always do e.g. IList<int> list = x.ToList(), only the library author needs to be concerned with being able to support the concrete return type.
ToLookup<T> is the unique one in the crowd. But perfectly within the guidelines: it is the most specific type available that the library authors are willing to support (as others have pointed out, the concrete Lookup<T> type appears to be more of an internal type not meant for public use).
Because List<T> actually implements a range of interfaces, not just IList:
public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable{
}
Each of those interfaces define a range of features which the List must conform. Picking one particular one, would render bulk of the implementation unusable.
If you do want to return IList, nothing stops you from having your own simple wrapper:
public static IList<TSource> ToIList<TSource>(this IEnumerable<TSource> source)
{
if (source == null) throw new ArgumentNullException(source);
return source.ToList();
}
If a function returns a newly-constructed immutable object, the caller should generally not care about the precise type returned provided it is capable of holding the actual data that it contains. For example, a function that is supposed to return an IImmutableMatrix might normally return an ImmutableArrayMatrix backed by a privately-held array, but if all the cells hold zeroes it might instead return an ZeroMatrix, backed only by Width and Height fields (with a getter that simply returns zero all the time). The caller wouldn't care whether it was given an ImmutableArrayMatrix matrix or a ZeroMatrix; both types would would allow all of their cells to be read, and guarantee their values would never change, and that's what the caller would care about.
On the other hand, functions that return newly-constructed objects that allow open-ended mutation should generally return the precise type the caller is going to expect. Unless there will be a means by which the caller can request different return types (e.g. by calling ToyotaFactory.Build("Corolla") versus ToyotaFactory.Build("Prius")) there's no reason for the declared return type to be anything else. While factories that return immutable data-holding objects can select a type based on the data to be contained, factories that return freely-mutable types will have no way of knowing what data may be put into them. If different callers will have different needs (e.g. returning to the extant example, some callers' needs would be met with an array, while others' would not) they should be given a choice of factory methods.
BTW, something like IEnumerator<T>.GetEnumerator() is a bit of a special case. The returned object will almost always be mutable, but only in a very highly-constrained fashion; indeed, it is expected that the returned object regardless of its type will have exactly one piece of mutable state: its position in the enumeration sequence. Although an IEnumerator<T> is expected to be mutable, the portions of its state which would vary in derived-class implementations are not.
It is said that IEnumerable is used in a custom collection. One of the uses is the foreach loop used to traverse through the custom collection.
However my question is that instead of making a custom collection that first implements IEnumerable and then constructing another class to implement IEnumerator to store a group of custom objects, why can't we just use list<your_customer_object>.
Thanks in advance for help.
Because you might want to implement a different data structure. IEnumerable abstracts the concept of sequence, while a List has the concept of index, adding/removing items and its own, data structure.
As an example of different structure, here's a class which allows you to enter an infinite foreach loop.
public class InfiniteSequence : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
return new InfiniteEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
class InfiniteEnumerator : IEnumerator<int>
{
public void Dispose()
{
throw new NotImplementedException();
}
public bool MoveNext()
{
Current++;
return true;
}
public void Reset()
{
Current = 0;
}
public int Current { get; private set; }
object IEnumerator.Current
{
get { return Current; }
}
}
}
Of course you can use List<T>.
If List<T> fits your needs, then use it and don't create a new class that inherits from IEnumerable<T>.
You would provide your own implementation of IEnumerable<T> when List<T> isn't right for your needs. The canonical example of this is when you want to support lazy evaluation of your collection, perhaps with a method that uses yield return.
As #ken2k said, you can just List<T> and you will got a generic version of List with your T type. But if you want to hide this implementation and customize some operations that List<T> or include new features, you can inherits from the List and implement your own methods. For sample:
public class CustomerCollection : List<Customer> // at this time, you have all methods from List such as Add, Remove, [index] etc...
{
public double AverageAge()
{
return this.Average(customer => customer.Age)
}
// other methods...
}
IEnumeralbe is the most abstraction of collections in .Net Framework, you can just interate in this abstraction.
You can just use List<T> or any other of the generic collection types. After all List<T> implements IEnumerable<T>.
Do you have a particular edge case that you need to cover with a bespoke collection?
Of course you can define your members as List<T>, that however binds the customer of your class to a specific implementation. If you define the member as IEnumerable<T> (assuming that the consumers will only want to enumerate your collection) than you can change the implementation to a different collection type that implements the interface without breaking the contract. You if you change it from List<T> to SortedSet<T> to implement order your consumers are not affected.
It's basically the advantage of coding against interfaces rather than concrete types.
You can use a different interface, ie. ICollection<T> if your consumers want more than just enumerate.
If it doesn't do anything else, go ahead. Specialized collections are for collections that need to do... special... things.
(For example, a ListViewItemCollection would have to notify its parent ListView when updated, so it needs to implement IList(T), and therefore IEnumerable(T). If you had a custom collection, it might inherit from that. Inheriting only from IEnumerable(T) makes sense only when your collection can be enumerated, but not indexed.)
You Can.
public class List<T> : IList<T>, ICollection<T>,
IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>,
IEnumerable
I think the source of confusion here is the difference between a "custom collection" and a "collection of custom class instances". Of these two, your List<CustomObject> is the latter case - you are only reusing a collection created by someone else and taking advantage of generics to keep the item type info, that's all. Truly custom collection would probably implement IEnumerable<T>, but you will rarely (if ever) need it.
So in this case you not only can, but probably also should use List<CustomObject>
I'm implementing a persistent collection - for the sake of argument, let's say it's a singly-linked list, of the style common in functional languages.
class MyList<T>
{
public T Head { get; }
public MyList<T> Tail { get; }
// other various stuff
// . . .
}
It seems natural to have this class implement ICollection<T>, since it can implement all the normal behavior one would expect of an ICollection<T>, at least in broad strokes. But there is a lot of mismatch between this class's behavior and ICollection<T>. For example, the signature of the Add() method
void Add(T item); // ICollection<T> version
assumes that the addition will be performed as a side-effect that mutates the collection. But this is a persistent data structure, so Add() should instead create a new list and return it.
MyList<T> Add(T item); // what we really want
It seems the best way to resolve this is to just create the version we want, and also generate a non-functional explicit implementation of the version defined in the interface.
void ICollection<T>.Add(T item) { throw new NotSupportedException(); }
public MyList<T> Add(T item) { return new MyList<T>(item, this); }
But I have a few concerns about that option:
Will this be confusing to users? I envision scenarios where someone is working with this class, and finds that calling Add() on it sometimes raises an exception, and sometimes runs but doesn't modify the list as would normally be expected for an ICollection, depending on the type information associated with the reference being used?
Following on (1), the implementation of ICollection<T>'s IsReadOnly should presumably return true. But that would seem to conflict with what is implied in other spots where Add() is being used with instances of the class.
Is (2) resolved in a non-confusing way by following the explicit implementation pattern again, with the new version returning false and the explicit implementation returning true? Or does this just make it even worse by falsely implying that MyList<T>'s Add() method is a mutator?
Or would it be better to forget trying to use the existing interface and just create a separate IPersistentCollection<T> interface that derives from IEnumerable<T> instead?
edit I changed the name of the class, and switched over to using ICollection. I wanted to focus on the object's behavior and how it relates to the interface. I just went with the cons list as a simple example. I appreciate the advice that if I were to implement a cons list I should try and come up with a less-confusing name and, should avoid implementing IList because that interface is intended for fast random access, but they are somewhat tangential issues.
What I intended to ask about is what others think about the tension between the semantics of read-only (or immutable) collections that are baked into the Framework, and persistent collections which implement equivalent behavior to what is described by the interface, only functionally rather than through mutating side effects.
Will implementing IList<T> be confusing?
Yes. Though there are situations in which an implementation of IList<T> throws -- say, when you are attempting to resize the list but its implementation is an array -- I would find it quite confusing to have an IList<T> that could be mutated in no way and did not have fast random access.
Should I implement a new IPersistentList<T>?
That depends on whether anyone will use it. Are consumers of your class likely to have a half-dozen different implementations of IPL<T> to choose from? I see no point in making an interface that is implemented by only one class; just use the class.
WPF's ItemsControl can get better performance if its ItemsSource is an IList<T> instead of an IEnumerable<T>.
But your persistent linked list will not have fast random access anyway.
It would make more sense to me to make a new IPersistentList<T> (or IImmutableList<T> since "persistent" sounds to me like the data is saved off somewhere.) interface since, really, it's different behavior than what is expected of an IList<T>. Classes that implement IList<T> should be mutable IMHO.
Oh, and of course, I'd avoid using the class name List<T> since it's already part of the framework.