我正在做 .NET MVC 教程。话虽如此,我遇到过这样的代码:
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"}
};
}
}
电影的索引 View 如下所示:
@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>
所以我的问题是,为什么在私有(private)方法GetMovies()
中的MoviesController
中,使用了IEnumerable
返回类型?为什么不使用 List
返回类型?
最佳答案
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>
同时使用 IEnumerable<>
更多开放 sOlid Principles ,我很少建议将任何集合类型接口(interface)/类传递给 View 。
而在 C# 中,数组/集合是 First-Class Citizens问题是它们在维护 Single Responsibility Principle 时不可扩展.
例如:
// Controller Returns:
var people = .... as IEnumerable<Person>;
return View(people);
@model IEnumerable<Person>
现在假设要向 View 添加与组无关的任何信息(如页面标题)..你如何做到这一点?您可以扩展并创建自己的派生自 IEnumerable<T>
的类但这破坏了 SRP,因为页面的标题与人群无关。相反,您应该创建一个 First-Class 模型来表示 View 所需的一切:
public class MyViewModel
{
public string Title { get; set;}
public IEnumerable<Person> People { get; set;}
}
return View(myViewModel);
@model MyViewModel
我建议始终这样做。一旦您开始在 MVC 中使用部分或模板,或者想要回发相同的对象,离开 IEnumerable<>
就会变得越来越困难。因为您需要更改部分和/或模板和/或 Javascript...
So my question is, why in the
MoviesController
in the private methodGetMovies()
, theIEnumerable<>
return type is used?
一般来说 Program against an Interface and not an Implementation 是个好习惯, 也称为 Design by contract (DbC), also known as contract programming, programming by contract and design-by-contract programming, .
这是一个soLid Principle特别是 Liskov 替换原则。摘录:
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...
在实践中它意味着当前代码:
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"}
};
}
可以更改为:
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();
}
现在我们不知道如何检索电影...只要契约(Contract)/接口(interface)满足我们的数据需求,我们就不必关心。
关于c# - 返回类型为 IEnumerable 而不仅仅是 List?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53711138/