2

When I am working in ASP.Net MVC or WebApi, I often find myself creating Views or return data structures that include 'List<>'s of objects. Meaning that I have a list of data objects that I want to return as part of a view.

I know that best practice is that the property for the List should be a IEnumerable interface. But, so often I am creating these Lists at the time that I create the View Model.

So where is it okay to initialize the List<>? Is it best to do it in a constructor for the View, or best to do it in the calling method?

Code for review:

    public class AllProfilesViewModel
{
    public AllProfilesViewModel(IEnumerable<FullUserProfile> allProfiles)
    {
        AllProfiles = allProfiles;
    }

    public AllProfilesViewModel()
    {
        AllProfiles = new List<FullUserProfile>();
    }

    public IEnumerable<FullUserProfile> AllProfiles { get; set; }        
}

public struct FullUserProfile
{
    public string Id { get; set; }
    public bool IsActive { get; set; }
    public string Email { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
7

Personally I'd do something like this

public class AllProfilesViewModel
{
    public AllProfilesViewModel(IEnumerable<FullUserProfile> allProfiles)
    {
        _allProfilesList.AddRange(allProfiles);
    }

    private List<FullUserProfile> _allProfilesList = new List<FullUserProfile>();

    public IReadOnlyCollection<FullUserProfile> AllProfiles 
    { get {return _allProfilesList.AsReadOnly(); } }

    public void AddProfile(FullUserProfile profile)
    { _allProfilesList.Add(profile); } 
}

Keep the ViewModel as a black box - the users of this class don't need to know the actual implementation of the list.

Creating the AllProfiles property as a ReadOnlyCollection makes it clear to the caller how the set of data items can be used – it is a finite size, includes a count property, it can be iterated over multiple times without any performance hit, but it can’t be updated.

  • This is similar to the approach I would use, though I usually expose the property as an IReadOnlyList<T>, which includes the ability access values via indexer, and I usually don't include .AsReadOnly() in the getter. – KChaloux Sep 19 '18 at 13:39
  • @KChaloux a valid point, but something that was previously exposed as an IEnumerable<T> won't require indexed access. – Peregrine Sep 19 '18 at 13:44
5

First off:

I know that best practice is that the property for the List should be a IEnumerable interface.

Not necessarily. IEnumerable is a read-only, sequential-access-only collection interface. There are many cases in which that's exactly what you need, but plenty of other cases where it isn't. Depending on your use case, ICollection, IReadOnlyList, or various other interfaces may be appropriate. If you want the consumer to be able to add stuff, it's probably best to just make the property it a List and keep it simple. Extra layers of indirection have costs, not only in performance but also in code readability and maintainability.

Having said that:

So where is it okay to initialize the List<>? Is it best to do it in a constructor for the View, or best to do it in the calling method?

Even if the consumer isn't supposed to change the contents of the collection, it's likely that your class will want to at some point. In this example, we have a list of all user profiles. When a new user registers, we want to add to that list. So probably the best way to do it is to have a private field of type List<FullUserProfile>, which is created in the constructor, (or just initialized in its declaration,) and then a public property of type IEnumerable<FullUserProfile> (or whichever collection interface is appropriate) whose get returns the list.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.