Return type as IEnumerable instead of just List?

  • A+
Category:Languages

I am doing a .NET MVC tutorial. With that being said, I've came across code like this:

public class MoviesController : Controller {     public ActionResult Index()     {         var movies = GetMovies();          return View(movies);     }      private IEnumerable<Movie> GetMovies()     {         return new List<Movie>         {             new Movie {Id = 1, Name = "Shrek"},             new Movie {Id = 2, Name = "LotR"}         };     } } 

Index view for Movies looks like:

@model IEnumerable<VideoStore.Models.Movie>  @{     ViewBag.Title = "Index";     Layout = "~/Views/Shared/_Layout.cshtml"; }  <h2>Movies</h2> <table class="table table-bordered table-hover">     <thead>         <tr>             <th>Movie</th>         </tr>     </thead>     <tbody>         @foreach (var movie in Model)         {             <tr>                 <td>@movie.Name</td>             </tr>         }     </tbody> </table> 

So my question is, why in the MoviesController in the private method GetMovies(), the IEnumerable return type is used? Why not to use the List return type?

 


Return type as IEnumerable instead of just List?

//controller  var a = new Dictionary<string, string>(); return View(a);  var b = new List<string>(); return View(b);  var c = new LinkedList<string>(); return View(c);  // All work with:  @model IEnumerable<string> 

While using an IEnumerable<> is more Open sOlid Principles, I rarely recommend passing any collection type interface/class to a view.

While in C# arrays/collections are First-Class Citizens the issue is that they are not extensible while maintaining the Single Responsibility Principle.

For example:

// Controller Returns: var people = .... as IEnumerable<Person>; return View(people);  @model IEnumerable<Person> 

Now suppose to want to add any information to the view that has nothing to do with the group (like a title to the page).. how do you do that? You could extend and make your own class that derives from IEnumerable<T> but that breaks the SRP because the Title of the page has nothing to do with the group of people. Instead you should create a First-Class Model that represents everything the view needs:

public class MyViewModel {   public string Title { get; set;}   public IEnumerable<Person> People { get; set;} }  return View(myViewModel);  @model MyViewModel 

I suggest always doing this. As soon as you start using partials or templates in MVC, or want to post back the same object, it becomes increasingly difficult to move away from IEnumerable<> because you need to changes Partials and/or Templates and/or Javascript...

So my question is, why in the MoviesController in the private method GetMovies(), the IEnumerable<> return type is used?

Generally it's good practice to Program against an Interface and not an Implementation, also referred to as Design by contract (DbC), also known as contract programming, programming by contract and design-by-contract programming,.

It's a soLid Principle specifically Liskov substitution principle. Excerpt:

Substitutability is a principle in object-oriented programming stating that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e. an object of type T may be substituted with any object of a subtype S) without altering any of the desirable properties of the program (correctness, task performed, etc.). More formally, the Liskov substitution principle (LSP) is a particular definition of a subtyping relation, called (strong) behavioral subtyping, that was initially introduced by Barbara Liskov in a 1987 conference keynote address titled Data abstraction and hierarchy. It is a semantic rather than merely syntactic relation, because it intends to guarantee semantic interoperability of types in a hierarchy, object types in particular. Barbara Liskov and Jeannette Wing described the principle succinctly in a 1994 paper as follows...

In practice it means the current code:

    public ActionResult Index()     {         var movies = GetMovies();          return View(movies);     }      private IEnumerable<Movie> GetMovies()     {         return new List<Movie>         {             new Movie {Id = 1, Name = "Shrek"},             new Movie {Id = 2, Name = "LotR"}         };     } 

Could change to:

public class MoviesController : Controller {     private readonly IMovieDb _movieDb;     // Dependency Injecting access to movies     public MoviesController(IMovieDb movieDb)     {         _movieDb = movieDb;     }      public ActionResult Index()     {         var movies = _movieDb .GetMovies();          return View(movies);     }     // ....   public interface IMovieDb {     IEnumerable<Movie> GetMovies(); } 

Now we have no idea how the Movies are retrieved... and we shouldn't care as long as the contract/interface fulfills our data needs.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: