c# - 返回类型为 IEnumerable 而不仅仅是 List?

标签 c# asp.net-mvc ienumerable

我正在做 .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 method GetMovies(), the IEnumerable<> 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/

相关文章:

C# 部署 : install additional file in the installation directory

asp.net-mvc - 当字段不在表单数据中时,为什么默认模型绑定(bind)器不验证字段?

c# - 在 C# 中动态转换字段

c# - 如何转义包含空格的路径

javascript - 客户端对表单的一部分进行验证

c# - 多少异步/等待是可以的?

asp.net - ObjectDataSource 的意义是什么

.net-4.0 - 为什么我不能在 .NET 4.0 中将 List<int> 分配给 IEnumerable<object>

c# - 先读取 IEnumerable 或等待其完成更改

c# - .WPF 应用程序生成 <appname>.dll.config 而不是 <appname>.exe.config