Why refactor argument of List<Term> to IEnumerable<Term>? - c#

I have a method that looks like this:
public void UpdateTermInfo(List<Term> termInfoList)
{
foreach (Term termInfo in termInfoList)
{
UpdateTermInfo(termInfo);
}
m_xdoc.Save(FileName.FullName);
}
Resharper advises me to change the method signature to IEnumerable<Term> instead of List<Term>. What is the benefit of doing this?

The other answers point out that by choosing a "larger" type you permit a broader set of callers to call you. Which is a good enough reason in itself to make this change. However, there are other reasons. I would recommend that you make this change because when I see a method that takes a list or an array, the first thing I think is "what if that method tries to change an item in my list/array?"
You want the contents of a bucket, but you are requiring not just the bucket but also the ability to change its contents. Why would you require that if you're not going to use that ability? When you say "this method cannot take any old sequence; it has to take a mutable list that is indexed by integers" I think that you're making that requirement on the caller because you're going to take advantage of that power.
If "I'm planning on messing up your data structure" is not what you intend to communicate to the caller of the method then don't communicate that. A method that takes a sequence communicates "The most I'm going to do is read from this sequence in order".

Simply put, accepting an enumerable allows your function to be compatible with a broader scope of input arguments, such as arrays and LINQ queries.
To expound on accepting LINQ queries, one could do:
UpdateTermInfo(myTermList.Where(x => somefilter));
Additionally, specifying an interface rather than a concrete class allows others to provide their own implementation of that interface. In this way, you are being "subscriptive" rather than "proscriptive." (Yes, I did just make up a word.)
In general (with many exceptions relating to what sort of abilities you want to reserve for potential later modifications), it is a best-practice to implement functions using arguments that are the most general that they can be. This gives maximum flexibility to the consumer of your function.
As a result, if you are dead-set on using a list for this function (perhaps because at some later date you expect you might want to use properties such as Count or the index operator), I would strongly urge you to consider using IList<Term> instead of List<Term> for the reasons mentioned above.

List implements IEnumerable, using it would makes things more flexible. If an instance came along where you didn't want to use a List and wanted to use a different collection object it would cast from IEnumerable with ease.
For instance IEnumerable allows you to use Arrays and many others as opposed to always using a List.
Inumerable is simply a collection of items, dissimilar to a List, where you can add, remove, sort, use For Each, Count etc.

The main idea behind that refactor is that you make the method more general. You don't say what data structure you want, only what you need from it: that you can iterate through its elements.
So later, when you decide that O(n) search is not good enough for you, you only have to change one line and move along.

If you use List then you are confining yourself to only use a concrete implementation of List where as with IEnumerable you can pass in Arrays, Lists, Collections as they all implement that interface.

Related

IEnumerable to IReadOnlyCollection

I have IEnumerable<Object> and need to pass to a method as a parameter but this method takes IReadOnlyCollection<Object>
Is it possible to convert IEnumerable<Object> to IReadOnlyCollection<Object> ?
One way would be to construct a list, and call AsReadOnly() on it:
IReadOnlyCollection<Object> rdOnly = orig.ToList().AsReadOnly();
This produces ReadOnlyCollection<object>, which implements IReadOnlyCollection<Object>.
Note: Since List<T> implements IReadOnlyCollection<T> as well, the call to AsReadOnly() is optional. Although it is possible to call your method with the result of ToList(), I prefer using AsReadOnly(), so that the readers of my code would see that the method that I am calling has no intention to modify my list. Of course they could find out the same thing by looking at the signature of the method that I am calling, but it is nice to be explicit about it.
Since the other answers seem to steer in the direction of wrapping the collections in a truly read-only type, let me add this.
I have rarely, if ever, seen a situation where the caller is so scared that an IEnumerable<T>-taking method might maliciously try to cast that IEnumerable<T> back to a List or other mutable type, and start mutating it. Cue organ music and evil laughter!
No. If the code you are working with is even remotely reasonable, then if it asks for a type that only has read functionality (IEnumerable<T>, IReadOnlyCollection<T>...), it will only read.
Use ToList() and be done with it.
As a side note, if you are creating the method in question, it is generally best to ask for no more than an IEnumerable<T>, indicating that you "just want a bunch of items to read". Whether or not you need its Count or need to enumerate it multiple times is an implementation detail, and is certainly prone to change. If you need multiple enumeration, simply do this:
items = items as IReadOnlyCollection<T> ?? items.ToList(); // Avoid multiple enumeration
This keeps the responsibility where it belongs (as locally as possible) and the method signature clean.
When returning a bunch of items, on the other hand, I prefer to return an IReadOnlyCollection<T>. Why? The goal is to give the caller something that fulfills reasonsable expectations - no more, no less. Those expectations are usually that the collection is materialized and that the Count is known - precisely what IReadOnlyCollection<T> provides (and a simple IEnumerable<T> does not). By being no more specific than this, our contract matches expectations, and the method is still free to change the underlying collection. (In contrast, if a method returns a List<T>, it makes me wonder what context there is that I should want to index into the list and mutate it... and the answer is usually "none".)
As an alternative to dasblinkenlight's answer, to prevent the caller casting to List<T>, instead of doing orig.ToList().AsReadOnly(), the following might be better:
ReadOnlyCollection<object> rdOnly = Array.AsReadOnly(orig.ToArray());
It's the same number of method calls, but one takes the other as a parameter instead of being called on the return value.

'Don't expose generic list', why to use collection<T> instead of list<T> in method parameter

I am using FxCop and it shows warning for "Don't expose generic list" which suggests use Collection<T> instead of List<T>. The reason why it is preferred, I know all that stuff, as mentioned in this SO post and MSDN and many more articles I have been through.
But my question is this, I am having few methods which does so much heavy calculation and methods accepts parameters of List<T> which is supposed to be faster and good in terms of performance. But FxCop issues warning for this as well as. So one option is that I should declare the parameter as Collection<T>, then use ToList() inside the method and then use it.
So which one is optimized?
"Suppress the warning for this case" OR "use Collection<T> in parameter and then use ToList() inside the method itself".
The code analysis/FxCop rules have been written to support framework creators (Microsoft creates a lot of frameworks). A framework is consumed by external parties and you should be careful when you design the public interface. Provided that you are not writing a framework to be consumed by external parties you can simply ignore rules that doesn't provide value to you.
However, one of the reasons that this rule exists is that exposing collections on a class is somewhat difficult. Often the elements in the collection are owned by the containing class and in that case you violate encapsulation if you allow clients to modify the collection used to store the aggregated items. By returning List<T> you allow the clients to modify the collection in many different ways. But often you want to keep track of the items in the collection. E.g. adding a new element might require some additional bookkeeping in the containing class etc. You lose this kind of control when you return a List<T> unless of course you make a copy when you return it (but then the client should understand that they only get a copy of collection and modifications will be ignored).
All in all you can probably improve your class design by avoiding exposing classes like List<T> and being more explicit about how aggregated elements can be added, modified and removed. But if you are in a hurry and just want to crank out some code then using List<T> may be exactly what you need to get the job done.
Don't bother using generic lists in public properties as long as you are not coding a framework somebody else want's to extend in the near future.
I suggest to suppress the warning. You can refactor your classes later if requirements change.
IMHO your interpretation of "Don't expose generic list' which suggests use collection instead of list". Is invalid.
The critical difference between collection and list is that the elements in list are ordered. Some methods may require that passed elements have order. Then we must use in parameter a list.
The key to understand delivered warning is that you should use instead of concrete class List<T> a interface IList<T>.
As the method operate on the list it is not so important what kind of list it is. The key factor is that it is a list.
Concluding the method parameters should be abstract as possible.
You should use the type that is most appropriate for your purposes (and suppress the warning if appropriate). If you're passing a bunch of items, and order and uniqueness don't matter, use a collection. If you're passing an ordered collection of items, use a list. If you're passing data such that every item is unique but order doesn't matter, use a set. Use the type that has the semantic meaning appropriate for the exchange. In a few cases where the semantics and the methods that you need don't necessarily align (suppose you need AddRange), make an exception, or use the conversion methods.

c# string[] vs IEnumerable<string>

What should I prefer if I know the number of elements before runtime?
Resharper offers me IEnumerable<string> instead of string[]?
ReSharper suggests IEnumerable<string> if you are only using methods defined for IEnumerable. It does so with the idea that, since you clearly do not need the value to be typed as array, you might want to hide the exact type from the consumers of (i.e., the code that uses) the value because you might want to change the type in the future.
In most cases, going with the suggestion is the right thing to do. The difference will not be something that you can observe while your program is running; rather, it's in how easily you will find it to make changes to your program in the future.
From the above you can also infer that the whole suggestion/question is meaningless unless the value we are talking about is passed across method boundaries (I don't remember if R# also offers it for a local variable).
If ReSharper suggests you use IEnumerable<string> it means you are only using features of that interface and no array specific features. Go with the suggestion of ReSharper and change it.
If you are trying to provide this method as an interface to other methods, I would prefer to have the output of your method more generic, hence would go for IEnumerable<string>.
Inside a method, if you are trying to instantiate and this is not being passed around to other methods, I would go for string[]. unless I need deferred execution. Although, it doesn't matter which one you use in this case.
The actual type should be string[] but depending on the user you may want to expose it as something else. e.g. IEnumerable<string> sequence = new string[5]... In particular if it's something like static readonly, then you should make it a ReadOnlyCollection so the entries can't be modified.
with string[] you can do more you can acces items by index with IEnumerable you have to loop to find specific index
It's probably suggesting this because it's looking for a better Liskov Substitution at this point in your code. Keep in mind the difference between the declared type and the implementing type. IEnumerable<> isn't an implementation, it's an interface. You can declare the variable as an IEnumerable<string> and build it with a string[] since the string array implements IEnumerable<string>.
What this does for you is allow you to pass around that string array as a more generic, more abstracted type. Anything which expects or returns an IEnumerable<string> (regardless of implementation, be it List<string> or string[] or anything else) can then use your string array, without having to worry about the specific implementation you pass it. As long as it satisfies the interface, it's polymorphic of the correct type.
Keep in mind that this isn't always the way to go. Sometimes you, as the developer, are very concerned with the implementation (perhaps for really fine-grained performance tuning, for example) and don't want to move up to an abstraction. The decision is up to you. ReSharper is merely making a suggestion to use an abstraction rather than an implementation in a variable/method declaration.
ReSharper is likely flagging it for you because you are not returning the least constrained type. If you aren't going to be using access on it by index in the future, I'd go with IEnumerable to have less constraint on the method which returns it.
Depends on your usage later on. If you need to enumare through these elements or sort or compare them later on then I would recommend IEnumerable otherwise go with array.
I wrote this response for a similar question regarding array or IEnumerable for return values, which was then closed as duplicate before I could post it. I thought the answer might be interesting to some so I post it here.
The main advantage of IEnumerable over T[] is that IEnumerable (for return values) can be made lazy. Ie it only computes the next element when needed.
Consider the difference between Directory.GetFiles and Directory.EnumerateFiles. GetFiles returns an Array, EnumerateFiles returns IEnumerable. This means that for a directory with two million files the Array will contain two million strings. EnumerateFiles only instansiate the strings as needed saving memory and improving response time.
However, it's not all benefits.
foreach is significantly less efficient on non-arrays (you can see this by disassembling the ILCode).
Array promises more, ie that its length will not change.
Lazy evaluation is not always better, consider the Directory class. The GetFiles implementation will open a find file handle, iterate over all files, close the find file handle and then return results. EnumerateFiles will do nothing until the first find file is requested, then the find file handle is opened and the files iterated, find file handle is closed when the enumerator is disposed. This means that the life-time of the find file handle is controlled by the caller, not the callee. Can be seen as less encapsulation and can give potential runtime errors with locked file handles.
In my humble opinion, I think R# is overzelous in suggestion IEnumerable over arrays especially so for return values (input parameters have less potential drawbacks). What I tend to do when I see a function that returns IEnumerable is a .ToArray in order to avoid potential issues with Lazy evaluation but if the Collection is already an Array this is inefficient.
I like the principle; promise alot, require little. Ie don't require that the input parameters must be arrays (use IEnumerable) but return Array over IEnumerable as Array is a bigger promise.

Why create an IEnumerable?

I don't understand why I'd create an IEnumerable. Or why it's important.
I'm looking at the example for IEnumerable:
http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx
But I can basically do the same thing if I just went:
List<Person> people = new List<Person>();
so what's IEnumerable good for? Can you give me a situation where I'd need to create a class that implements IEnumerable?
IEnumerable is an interface, it exposes certain things to the outside. While you are completely right, you could just use a List<T>, but List<T> is very deep in the inheritance tree. What exactly does a List<T>? It stores items, it offers certain methods to Add and Remove. Now, what if you only need the "item-keeping" feature of a List<T>? That's what an IEnumerable<T> is - an abstract way of saying "I want to get a list of items I can iterate over". A list is "I want to get a collection which I can modify, can access by index and iterate". List<T> offers a lot more functionality than IEnumerable<T> does, but it takes up more memory. So if a method is taking an IEnumerable<T>, it doesn't care what exactly it gets, as long as the object offers the possibilites of IEnumerable<T>.
Also, you don't have to create your own IEnumerable<T>, a List<T> IS an IEnumerable<T>!
Lists are, of course IEnumerable - As a general rule, you want to be specific on what you output but broad on what you accept as input eg:
You have a sub which loops through a list of objects and writes something to the console...
You could declare the parameter is as either IEnumerable<T> or IList<T> (or even List<T>). Since you don't need to add to the input list, all you actually need to do is enumerate - so use IEnumerable - then your method will also accept other types which implement IEnumerable including IQueryable, Linked Lists, etc...
You're making your methods more generic for no cost.
Today, you generally wouldn't use IEnumerable anymore unless you were supporting software on an older version of the framework. Today, you'd normally use IEnumerable<T>. Amongst other benefits, IEnumerable fully implements all of the LINQ operations/extensions so that you can easily query any List type that implements IEnumerable<T> using LINQ.
Additionally, it doesn't tie the consumer of your code to a particular collection implementation.
It's rare that nowdays you need to create your own container classes, as you are right there alreay exists many good implementations.
However if you do create your own container class for some specific reason, you may like to implement IEnumerable or IEnumerable<T> because they are a standard "contract" for itteration and by providing an implementation you can take advantage of methods/apis that want an IEnumerable or IEnumerable<T> Linq for example will give you a bunch of useful extension methods for free.
An IList can be thought of as a particular implementation of IEnumerable. (One that can be added to and removed from easily.) There are others, such as IDictionary, which performs an entirely different function but can still be enumerated over. Generally, I would use IEnumerable as a more generic type reference when I only need an enumeration to satisfy a requirement and don't particularly care what kind it is. I can pass it an IList and more often than not I do just that, but the flexibility exists to pass it other enumerations as well.
Here is one situation that I think I have to implement IEnumerable but not using List<>
I want to get all items from a remote server. Let say I have one million items going to return. If you use List<> approach, you need to cache all one million items in the memory first. In some cases, you don't really want to do that because you don't want to use up too much memory. Using IEnumerable allows you to display the data on the screen and then dispose it right away. Therefore, using IEnumerable approach, the memory footprint of the program is much smaller.
It's my understanding that IEnumerable is provided to you as an interface for creating your own enumerable class types.
I believe a simple example of this would be recreating the List type, if you wanted to have your own set of features (or lack thereof) for it.
What if you want to enumerate over a collection that is potentially of infinite size, such as the Fibonacci numbers? You couldn't do that easily with a list, but if you had a class that implemented IEnumerable or IEnumerable<T>, it becomes easy.
When a built in container fits your needs you should definitely use that, and than IEnumerable comes for free. When for whatever reason you have to implement your own container, for example if it must be backed by a DB, than you should make sure to implement both IEnumerable and IEnumerable<T> for two reasons:
It makes foreach work, which is awesome
It enables almost all LINQ goodness. For example you will be able to filter your container down to objects that match a condition with an elegant one liner.
IEnumerable provides means for your API users (including yourself) to use your collection by the means of a foreach. For example, i implemented IENumerable in my Binary Tree class so i could just foreach over all of the items in the tree without having to Ctrl+C Ctrl+V all the logic required to traverse the tree InOrder.
Hope it helps :)
IEnumerable is useful if you have a collection or method which can return a bunch of things, but isn't a Dictionary, List, array, or other such predefined collection. It is especially useful in cases where the set of things to be returned might not be available when one starts outputting it. For example, an object to access records in a database might implement iEnumerable. While it might be possible for such an object to read all appropriate records into an array and return that, that may be impractical if there are a lot of records. Instead, the object could return an enumerator which could read the records in small groups and return them individually.

Are there drawbacks to creating a class that encapsulates Generic Collection?

A part of my (C# 3.0 .NET 3.5) application requires several lists of strings to be maintained. I declare them, unsurprisingly, as List<string> and everything works, which is nice.
The strings in these Lists are actually (and always) Fund IDs. I'm wondering if it might be more intention-revealing to be more explicit, e.g.:
public class FundIdList : List<string> { }
... and this works as well. Are there any obvious drawbacks to this, either technically or philosophically?
I would start by going in the other direction: wrapping the string up into a class/struct called FundId. The advantage of doing so, I think, is greater than the generic list versus specialised list.
You code becomes type-safe: there is a lot less scope for you to pass a string representing something else into a method that expects a fund identifier.
You can constrain the strings that are valid in the constructor to FundId, i.e. enforce a maximum length, check that the code is in the expected format, &c.
You have a place to add methods/functions relating to that type. For example, if fund codes starting 'I' are internal funds you could add a property called IsInternal that formalises that.
As for FundIdList, the advantage to having such a class is similar to point 3 above for the FundId: you have a place to hook in methods/functions that operate on the list of FundIds (i.e. aggregate functions). Without such a place, you'll find that static helper methods start to crop up throughout the code or, in some static helper class.
List<> has no virtual or protected members - such classes should almost never be subclassed. Also, although it's possible you need the full functionality of List<string>, if you do - is there much point to making such a subclass?
Subclassing has a variety of downsides. If you declare your local type to be FundIdList, then you won't be able to assign to it by e.g. using linq and .ToList since your type is more specific. I've seen people decide they need extra functionality in such lists, and then add it to the subclassed list class. This is problematic, because the List implementation ignores such extra bits and may violate your constraints - e.g. if you demand uniqueness and declare a new Add method, anyone that simply (legally) upcasts to List<string> for instance by passing the list as a parameter typed as such will use the default list Add, not your new Add. You can only add functionality, never remove it - and there are no protected or virtual members that require subclassing to exploit.
So you can't really add any functionality you couldn't with an extension method, and your types aren't fully compatible anymore which limits what you can do with your list.
I prefer declaring a struct FundId containing a string and implementing whatever guarantees concerning that string you need there, and then working with a List<FundId> rather than a List<string>.
Finally, do you really mean List<>? I see many people use List<> for things for which IEnumerable<> or plain arrays are more suitable. Exposing your internal List in an api is particularly tricky since that means any API user can add/remove/change items. Even if you copy your list first, such a return value is still misleading, since people might expect to be able to add/remove/change items. And if you're not exposing the List in an API but merely using it for internal bookkeeping, then it's not nearly as interesting to declare and use a type that adds no functionality, only documentation.
Conclusion
Only use List<> for internals, and don't subclass it if you do. If you want some explicit type-safety, wrap string in a struct (not a class, since a struct is more efficient here and has better semantics: there's no confusion between a null FundId and a null string, and object equality and hashcode work as expected with structs but need to be manually specified for classes). Finally, expose IEnumerable<> if you need to support enumeration, or if you need indexing as well use the simple ReadOnlyCollection<> wrapper around your list rather than let the API client fiddle with internal bits. If you really need a mutatable list API, ObservableCollection<> at least lets you react to changes the client makes.
Personally I would leave it as a List<string>, or possibly create a FundId class that wraps a string and then store a List<FundId>.
The List<FundId> option would enforce type correct-ness and allow you to put some validation on FundIds.
Just leave it as a List<string>, you variable name is enough to tell others that it's storing FundIDs.
var fundIDList = new List<string>();
When do I need to inherit List<T>?
Inherit it if you have really special actions/operations to do to a fund id list.
public class FundIdList : List<string>
{
public void SpecialAction()
{
//can only do with a fund id list
//sorry I can't give an example :(
}
}
Unless I was going to want someone to do everything they could to List<string>, without any intervention on the part of FundIdList I would prefer to implement IList<string> (or an interface higher up the hierarchy if I didn't care about most of that interface's members) and delegate calls to a private List<string> when appropriate.
And if I did want someone to have that degree of control, I'd probably just given them a List<string> in the first place. Presumably you have something to make sure such strings actually are "Fund IDs", which you can't guarantee any more when you publicly use inheritance.
Actually, this sounds (and often does with List<T>) like a natural case for private inheritance. Alas, C# doesn't have private inheritance, so composition is the way to go.

Categories