简体   繁体   English

从类库中的公共 api 返回数据列表的最佳做法是什么?

[英]What is the best practice to return List of data from public api inside class library?

I have a class library which contains a method returning List to the clients (mvc,console app etc...).我有一个类库,其中包含一个将 List 返回给客户端(mvc、控制台应用程序等)的方法。

Now while I was reading Guidelines for Collections , I came to know about below point:现在,当我阅读《收藏指南》时,我了解到以下几点:

X DO NOT use ArrayList or List<T> in public APIs. X 不要在公共 API 中使用 ArrayList 或List<T>

Currently the client which is consuming my class library api is MVC which just loops on it and perform some string.format on some properties from List<Statistics> but do not change anything on original list.目前,使用我的类库 api 的客户端是 MVC,它只是循环它并对List<Statistics>某些属性执行一些 string.format,但不更改原始列表中的任何内容。

I have thought of considering IEnumerable<Statistics> but then client can also cast it to List and then manipulate it and same goes with IReadOnlyList also.我曾考虑考虑IEnumerable<Statistics>但客户端也可以将其转换为 List 然后对其进行操作,IReadOnlyList 也是如此。

MSDN design guidelines does not state that if not ArrayList or List<T> then what should be the appropriate COLLECTION for return List of something for public API? MSDN 设计指南没有说明如果不是ArrayListList<T>那么什么应该是适当的 COLLECTION 来返回公共 API 的某些东西的列表?

This is my base class which is exposed to client :这是我暴露给客户端的基类:

public abstract class BaseManager
{
    //Other shared code
    public abstract List<Statistics> GetStatistics();
}

public class Manager1 : BaseManager
{
    public override List<Statistics> GetStatistics()
    {
        var stats = new List<Statistics>();
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });
        return stats;
    }
}

As a rule of thumb, you want to expose to your clients as little as possible.根据经验,您希望尽可能少地向客户展示。
You also don't want to tie them to a specific implementation if you have an interface that guarantees the contract you allow them.如果您有一个接口来保证您允许它们的合同,您也不希望将它们与特定的实现联系起来。

So, in this spirit -所以,本着这种精神——

If you want your client to only be able to read the data returned using a foreach loop, then return an IEnumerable<T> .如果您希望您的客户端只能读取使用foreach循环返回的数据,则返回IEnumerable<T>
If you want your clients to have access to the count property, return an IReadOnlyCollection<T> .如果您希望您的客户能够访问count属性,请返回IReadOnlyCollection<T>
If you want your client to be able to access a specific part of the data based on it's index, than return an IReadOnlyList<T> .如果您希望您的客户端能够根据其索引访问数据的特定部分,则返回IReadOnlyList<T>

Please note that IReadOnlyList<T> inherits the IReadOnlyCollection<T> and this interface inherits the IEnumerable<T> - so all of these options will allow the usage of foreach , the last two will allow the usage of count (as a property), and the last one will allow the usage of an indexer.请注意IReadOnlyList<T>继承了IReadOnlyCollection<T>并且这个接口继承了IEnumerable<T> - 所以所有这些选项都将允许使用foreach ,最后两个将允许使用count (作为属性),最后一个将允许使用索引器。

Also, please note that your underlying type can still be a List as it implements the IReadOnlyList<T> and therefor all other interfaces I've mentioned.另外,请注意,您的基础类型仍然可以是List因为它实现了IReadOnlyList<T>以及我提到的所有其他接口。

Another thing to keep in mind is that the ReadOnly in this case does not mean that all the members held by the collection are immutable - you can still change the properties of them (assuming they are mutable types) - but the collection itself being immutable - you can't add or remove items to / from it.要记住的另一件事是,在这种情况下ReadOnly并不意味着集合所拥有的所有成员都是不可变的 - 您仍然可以更改它们的属性(假设它们是可变类型) - 但集合本身是不可变的 -您不能在其中添加或删除项目。

Update更新
Following your comment:按照您的评论:
If the IEnumerable<T> is a list you can down-cast it:如果IEnumerable<T>是一个列表,您可以向下转换它:

IEnumerable<int> myIEnum = new List<int>(); 
var myList = (List<int>)myIEnum; 

But the ToList() extension method only creates a list that is a copy of the original IEnumerable<T> .但是ToList()扩展方法只创建一个列表,它是原始IEnumerable<T>的副本。

If your base class would be:如果您的基类是:

public abstract class BaseManager
{
    //Other shared code
    public abstract IEnumerable<Statistics> GetStatistics();
}

The derived classes can still use a list inside the method, but will return it as an IEnumerable<Statistics> :派生类仍然可以在方法内部使用列表,但会将其作为IEnumerable<Statistics>

public class Manager1 : BaseManager
{
    public override IEnumerable<Statistics> GetStatistics()
    {
        var stats = new List<Statistics>();
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });
        return stats;
    }
}

If you want to actually create an IEnumerable that can't be down-cast to a list you can always do this:如果您想实际创建一个不能向下转换为列表的IEnumerable ,您可以随时执行以下操作:

    public override IEnumerable<Statistics> GetStatistics()
    {
        var stats = new List<Statistics>();
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });
        stats.Add(new Statistics { .... });

        foreach(var stat in stats)
        {
            yield return stat;
        }
    }

If you are familiar with .Net, you may notice there are a lot class with the name of _______Collection .如果您熟悉 .Net,您可能会注意到有很多名为_______Collection They match the conditions in the article, so I think they are what the guideline recommends.它们符合文章中的条件,所以我认为它们是指南推荐的。

Such as:如:

  • System.Collections.Specialized.NameValueCollection System.Collections.Specialized.NameValueCollection
  • System.Text.RegularExpressions.MatchCollection System.Text.RegularExpressions.MatchCollection
  • System.Collections.Generic.Dictionary.KeyCollection System.Collections.Generic.Dictionary.KeyCollection

So what they suggest are所以他们建议的是

  • Create one like StatisticsCollection创建一个像StatisticsCollection
  • Implement a collection interface like ICollection<Statistics>实现像ICollection<Statistics>这样的集合接口

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从 2 个 arrays 返回一组 static 数据的最佳做法是什么 - What is the best practice to return a set of static data from 2 arrays 在类内部从数据库存储/检索数据时的最佳实践 - Best practice when storing/retrieving data from database inside class 在项目中添加类库dll的最佳实践是什么? - What's the best practice when adding a Class Library dll in a project? 使用公共字段的最佳做法是什么? - What is the best practice for using public fields? C#将参数作为方法参数传递以从泛型类获取和设置数据的最佳实践是什么 - C# What is the best practice to pass a parameter as method argument to both get AND set data from a generic class 从继承的类更改基础对象属性的最佳实践是什么? - what is the best practice of changing base object properties from inherited class 从传入的字符串的基类的列表的列表中返回列表的最佳方法是什么 - what's the best way to return a List from a list of Lists of a base class based on string passed in 实例化类和从数据库加载数据的最佳实践 - Best practice for instantiating a class and loading data from database 将数据从控制器传递到视图布局的最佳实践是什么? - What is the best practice of passing data from a controller to a view layout? 类中枚举更改函数返回的最佳实践 - Best practice for an enum in a class changing a return of a function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM