0

I have a function that returns a list of strings.

I can loop through that list just like it was an array.

Is there a reason I should convert it into an array before doing so?

EDIT: The reason I'm asking is because I see code online (and on SO) that manipulate/create a collection of string using List (or other types) but then call the ToArray when returning it, why?

user3542112
  • 253
  • 1
  • 4
  • 13
  • Nope, just iterate through the list. – eddie_cat Oct 28 '14 at 15:28
  • I'm not wondering when to use a list or array, I'm already using a list, because I need to (.add function) but why would I convert it to array after? – user3542112 Oct 28 '14 at 15:30
  • If you were passing the list to a method that was expecting an array, you would need to convert it to an array. – eddie_cat Oct 28 '14 at 15:31
  • 1
    I don't think this is a duplicate; this question asks specifically about the situation where a `List` is already existing, and it is converted into an array right before iteration. Voting to reopen. – O. R. Mapper Oct 28 '14 at 15:31
  • 2
    Can you show an example of that code that creates such a collection and then calls `ToArray` before returning the collection? I can think of various reasons to do that, but I would prefer to answer the question for a particular type of situations rather than just utter wild guesses based on what may or may not be the case. – O. R. Mapper Oct 28 '14 at 15:32
  • @O.R.Mapper And now the answers are similar to [the question](http://stackoverflow.com/questions/434761/array-versus-listt-when-to-use-which) that I believe this is a duplicate of. A question asking whether you should convert to an array/List can be answered by examining the reasons for which you would use an array vs List. – mason Oct 28 '14 at 15:47
  • @mason: Yes, some of the answers on this question actually answer [the other question](http://stackoverflow.com/questions/434761/array-versus-listt-when-to-use-which), and get accordingly downvoted here. – O. R. Mapper Oct 28 '14 at 15:48
  • @O.R.Mapper The questions are essentially the same, because the answers apply to both. – mason Oct 28 '14 at 15:49
  • @mason: I disagree with both of your claims. – O. R. Mapper Oct 28 '14 at 15:50

5 Answers5

1

One reason is to make sure that you're not exposing the original list to the client code. If you did exposed, then they may add/remove elements to the returned List<T> which will modify the source list as List<T> is a reference type. This may not be the intended behavior.

If you use ToArray and return the array instead, you don't need to worry about modification in the array, as it is just a copy of the data.

If you have some specific question with some sample code, you may get a specific answer.

Sriram Sakthivel
  • 67,773
  • 7
  • 96
  • 172
  • 1
    They can still replace items in the returned array - arrays are reference types, as well -, so that's not really safer in this regard. Creating a *copy* of the list does guard the original, internal list against such changes, but then, that copy could just as well be a list as an array. Hence, the decision whether or not to return a *copy* of the internal list is independent from that of returning an *array* or a *list*. – O. R. Mapper Oct 28 '14 at 15:37
  • @O.R.Mapper Agree with you, it doesn't matter `Array` or `List` you return, what matters is whether it is a copy or original. But `ToArray` is most common way of returning the copy of the data. – Sriram Sakthivel Oct 28 '14 at 15:41
  • In some situations, [`ReadOnlyCollection`](http://msdn.microsoft.com/en-us/library/ms132474%28v=vs.110%29.aspx) is quite a cleaner way to protect against uncontrolled changes of the internal list. We need to see some code by the OP to make any statement about what is or is not appropriate. – O. R. Mapper Oct 28 '14 at 15:44
0

Not unless you have a specific use case where it's required. There are more options for manipulating/searching Lists than there are with Arrays out-of-the-box with .NET.

If you ever are working on a memory-sensitive application, then Arrays probably have an ever-so-slightly smaller memory footprint, but I wouldn't worry about that unless memory's a very sensitive issue for your app.

Ryan Nigro
  • 3,751
  • 2
  • 15
  • 23
0

One reason is you have class acting as cache for e.g. One class has field listOfAllClients and you want to return subset as below

List<Clients> _listOfClientCache ; 

private client[] GetSClientsByCity(string city)
{
   _listOfClient.Where(x => x.Client.City = city).ToArray();
}

One reason I see is memory foot print, If caller is not going to add or remove elements then it saves memory.

List is implemented using arrays, but when need to add element more than size of underline array then it just doubles the size of underlying array and copy elements. So there is good chance that underlying array size more than actual elements within the List.

Converting to Array will free up memory allocated for the unused elements.

Below is the test

[TestMethod]
    public void ListAndArrayTest()
    {
        int[] array = GetArray();
        Debug.WriteLine("IsFixedSize {0}, Elements {1}", array.IsFixedSize, array.Length);
// This will print IsFixedSize True, Elements 35
    }

    private int[] GetArray()
    {
        List<int> localList = new List<int>();
        for (int i = 0; i < 35; i++)
        {
            localList.Add(i);
        }
        Debug.WriteLine("Capacity {0}, Element Count {1}", localList.Capacity, localList.Count);
        // This will print Capacity **64**, Element Count **35**
        return localList.ToArray();
    }

Output : Capacity 64, Element Count 35 IsFixedSize True, Elements 35

From the output it is clear that caller has pure array, not any reference of original list which was using array under the hood with capacity of 64 element as after 32 elements when it required more elements it doubled size of array to 64 and copied the elements to it.

Once it is converted back to array caller has array of 35 element.

Rajnikant
  • 1,501
  • 13
  • 19
  • I've never seen anyone returning new array for this purpose. Also it doesn't saves any memory. You still have the original list in memory, then how does that saves memory ? – Sriram Sakthivel Oct 28 '14 at 15:45
  • @SriramSakthivel: How do you know the original list is still in memory? The method could compile a list of items (and therefore internally use a `List`), and then return the result as an array because it's not going to change any more. – O. R. Mapper Oct 28 '14 at 15:46
  • 1
    @O.R.Mapper That's arguable, We don't know what context OP is talking about, whether `List` lives still or not. I assumed the former, you have a fair point there. If any concrete example provided we can provide a specific answer. – Sriram Sakthivel Oct 28 '14 at 15:52
  • @SriramSakthivel - This is not arguable, You need to understand basic things. Try below tests in Updated answer on your machine to understand fundamentals. – Rajnikant Oct 28 '14 at 16:04
  • 1
    @RAJ What tests? What I need to understand basic? Did you first understand my comment? If your original list still lives in memory you're not saving any memory! – Sriram Sakthivel Oct 28 '14 at 16:06
  • @SriramSakthivel - Check my updated answer and verify the result. – Rajnikant Oct 28 '14 at 16:07
  • 1
    Read my comment again. If your `localList` was a field in the instance, then you have the `List` in memory which already have the `Capacity` 64 sitting in memory. Then how do you save memory? Do you got my point? Op didn't said that `List` is a local variable. So that is arguable. Does that makes sense? – Sriram Sakthivel Oct 28 '14 at 16:10
  • @SriramSakthivel In my answer I didn't meant for field of class. Neither its been mentioned in the original answer. It was very obvious that One say repository is returning data to service layer. – Rajnikant Oct 28 '14 at 16:15
  • @SriramSakthivel Does it make any sense having field List and having a function within same class returning ToArray on that field to caller function in same class ? Can't it just return void and use same field defined in the class? – Rajnikant Oct 28 '14 at 16:24
  • @RAJ: No, but to a caller function in another class, as outlined in [Sririam's answer](http://stackoverflow.com/a/26612344/1430156). – O. R. Mapper Oct 28 '14 at 16:48
  • @RAJ Repository, `List` as local variable are all your assumptions which is not mentioned in question. That's not the end of the world. Who said we're using it in same class? You assume so many things. I never said we're returning `ToArray` for using in the same class. Simply you're not even trying to understand my point and sticking to your point. Be aware that we can also use instance and static fields. Only local variables are not life. – Sriram Sakthivel Oct 28 '14 at 17:21
  • @SriramSakthivel If we have instance field List then why one function will use .ToArray() on it? Possibility is to return it to caller from some other class and caller within same class right? Now returning to another function within same class doesn't make any sense to me, I would use instance field, hence no question of ToArray(). Now when returing collection to caller in other class there are two posibility 1. You doing some data filtering e.g. instanceListCollection.Where(x=> someCondition).ToArray() ( here I agree with your point). – Rajnikant Oct 28 '14 at 17:28
  • I never said we're returning `ToArray` to same class member. Where did you got that idea? If you read my anwswer, I used the term "client code", what does that mean? Obviously it means some other class. There is no point in discussing about current class here. I guess that makes sense atleast now :| – Sriram Sakthivel Oct 28 '14 at 17:45
0

It could be that the sample code you've seen does some sort of lazy evaluation (like for example most Linq statements do). In that case it would make sense to convert the result to an array to execute the query immediately instead of evaluate it during the first iteration.

Example:

// persons will only be lazy evaluated, which means
// the query will only execute when the "persons" are iterated.
var persons = Persons.Select(x => x.Name == "John Doe");

// here the "ToArray" forces an immediate execution of the query
var personsArray = Persons.Select(x => x.Name == "John Doe").ToArray();
pgenfer
  • 597
  • 2
  • 13
-1

Arrays are more light-weight structures than lists and provide no actual methods for manipulation
(by manipulation I mean: adding and removing items)

To add an item to an array or to delete an item from an array you need to re-define the array.

Lists allows you to use methods such as .Add and .Remove - making them more suitable for collection manipulation structures.

If your requirement focus on just finding an item in a collection - stick to arrays but if you need to manipulate the collection go for the list.

Think of lists as if they were special interface to manipulate arrays.

G.Y
  • 5,341
  • 2
  • 30
  • 51
  • A writeable indexer is quite a "method for manipulation", wouldn't you say? Also, this doesn't answer the question, why it would or wouldn't be useful to convert an existing list to an array before returning it. – O. R. Mapper Oct 28 '14 at 15:44
  • I mean to manipulation as adding and removing items from the collection. – G.Y Oct 28 '14 at 15:46