简体   繁体   English

什么是更好,更清洁的方式使用List <T>

[英]What is a better, cleaner way of using List<T>

I'm looking to implement a few nicer ways to use List in a couple of apps I'm working on. 我正在寻找在我正在开发的几个应用程序中实现一些更好的方法来使用List。 My current implementation looks like this. 我目前的实现看起来像这样。

MyPage.aspx.cs MyPage.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    BLL.PostCollection oPost = new BLL.PostCollection();
    oPost.OpenRecent();
    rptPosts.DataSource = oArt;
    rptPosts.DataBind();
}

BLL Class(s) BLL班级

public class Post
{
    public int PostId { get; set; }
    public string PostTitle { get; set; }
    public string PostContent { get; set; }
    public string PostCreatedDate { get; set; }

    public void OpenRecentInitFromRow(DataRow row)
    {
        this.PostId = (int) row["id"];
        this.PostTitle = (string) row["title"];
        this.PostContent = (string) row["content"];
        this.PostCreatedDate = (DateTime) row["createddate"];
    }
}
public class PostCollection : List<Post>
{
    public void OpenRecent()
    {
        DataSet ds = DbProvider.Instance().Post_ListRecent();
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            Post oPost = new Post();
            oPost.OpenRecentInitFromRow(row);
            Add(oPost);
        }
    }
}

Now while this is working all well and good, I'm just wondering if there is any way to improve it, and just make it cleaner that having to use the two different classes do to something I think can happen in just one class or using an interface. 现在虽然这一切都运行得很好,但我只是想知道是否有任何方法可以改进它,并且只是让它更清洁,不得不使用两个不同的类做我认为可能只在一个类或使用一个界面。

For one thing, I wouldn't derive from List<T> - you aren't really specializing the behaviour. 首先,我不会从List<T>派生出来 - 你并不是真正专注于这种行为。

I'd also suggest that you could make Post immutable (at least externally), and write a static method (or constructor) to create one based on a DataRow: 我还建议您可以使Post不可变(至少在外部),并编写一个静态方法(或构造函数)来创建一个基于DataRow的方法:

public static Post FromDataRow(DataRow row)

Likewise you can have a list method: 同样,您可以拥有一个列表方法:

public static List<Post> RecentPosts()

which returns them. 返回它们。 Admittedly that might be better as an instance method in some sort of DAL class, which will allow mocking etc. Alternatively, in Post: 不可否认,作为某种DAL类中的实例方法可能更好,这将允许模拟等。或者,在Post中:

public static List<Post> ListFromDataSet(DataSet ds)

Now, as for the use of List<T> itself - are you using .NET 3.5? 现在,至于List<T>本身的使用 - 您使用的是.NET 3.5吗? If so, you could make this considerably neater using LINQ: 如果是这样,你可以使用LINQ使这个更加整洁:

public static List<Post> ListFromDataSet(DataSet ds)
{
    return ds.Tables[0].AsEnumerable()
                       .Select(row => Post.FromDataRow(row))
                       .ToList();
}

Edit: John Skeet's answer is probably a better option. 编辑:John Skeet的回答可能是更好的选择。 But if you want to make just a few simple changes, read on: 但是,如果您只想进行一些简单的更改,请继续阅读:

Place the database access code, OpenRecentInitFromRow into the PostCollection and treat that as a Post manager class. 将数据库访问代码OpenRecentInitFromRow放入PostCollection并将其视为Post Manager类。 That way the Post class is a plain old Data Transfer Object. 这样Post类就是一个普通的旧数据传输对象。

public class Post
{
    public int PostId { get; set; }
    public string PostTitle { get; set; }
    public string PostContent { get; set; }
    public string PostCreatedDate { get; set; }
}

public class PostCollection : List<Post>
{
    public void OpenRecent()
    {
        DataSet ds = DbProvider.Instance().Post_ListRecent();
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            Add(LoadPostFromRow(row));
        }
    }

    private Post LoadPostFromRow(DataRow row)
    {
        Post post = new Post();
        post.PostId = (int) row["id"];
        post.PostTitle = (string) row["title"];
        post.PostContent = (string) row["content"];
        post.PostCreatedDate = (DateTime) row["createddate"];
        return post;
    }
}

Are you deriving from List<T> because you want to offer other consumers of PostCollection the ability to Add and Remove items? 您是从List <T>派生的,因为您想为PostCollection的其他消费者提供添加和删除项目的能力吗? I'm guessing not, and that you actually just want a way to expose a collection you can bind to. 我猜不是,而你实际上只是想要一种方法来公开你可以绑定的集合。 If so, you could consider an iterator, perhaps: 如果是这样,你可以考虑一个迭代器,也许:

class BLL {
    ...

    public IEnumerable<Post> RecentPosts {
        get {
            DataSet ds = DbProvider.Instance().Post_ListRecent(); 
            foreach (DataRow row in ds.Tables[0].Rows) 
            { 
                Post oPost = new Post(); 
                oPost.OpenRecentInitFromRow(row); 
                yield return oPost;
            } 
        }
    }    

    ...
}

Notwithstanding the fact that this might be considered poor form (in that we have a property getter that might be making a network call), this iterator approach will do away with the overhead of calling OpenRecentInitFromRow for Posts that are never enumerated. 尽管这可能被认为是糟糕的形式(因为我们有一个可能正在进行网络调用的属性获取器),但这种迭代器方法将消除为从未枚举的Posts调用OpenRecentInitFromRow的开销。

You also become agnostic as to how potential consumers of your Posts might want to consume them. 您还可以了解邮件的潜在消费者可能希望如何使用它们。 Code that absolutely, positively has to have every Post can do ToList(), but other code might want to use a LINQ query that short-circuits the enumeration after the right Post is found. 绝对,肯定必须让每个Post都可以执行ToList()的代码,但是其他代码可能想要使用LINQ查询,该查询在找到正确的Post之后使枚举短路。

I'm looking to implement a few nicer ways to use List 我正在寻找一些更好的方法来使用List

That seems like an odd request. 这似乎是一个奇怪的要求。 The "List" type is a means, rarely an end. “列表”类型是一种手段,很少是结束。 With that in mind, one nicer way to accomplish your real end is to use IEnumerable rather than List, because that List forces you to keep your entire collection in memory while IEnumerable only requires one object at a time. 考虑到这一点,实现真正结束的一种更好的方法是使用IEnumerable而不是List,因为该List强制您将整个集合保留在内存中,而IEnumerable一次只需要一个对象。 The trick is just that you have to wire everything in your processing stream, from the data layer all the way up through presentation, to use it. 诀窍在于,您必须连接处理流中的所有内容 ,从数据层一直到演示,然后使用它。

I have a good example in the link below about how to do this in a very clean way: 我在下面的链接中有一个很好的例子,关于如何以非常干净的方式执行此操作:
Fastest method for SQL Server inserts, updates, selects SQL Server最快的插入,更新和选择方法

Depending on your existing data layer code you may be able to skim much of the first half of the (long) post - the main point is that you use an iterator block to turn an SqlDataReader into an IEnumerable<IDataRecord> . 根据您现有的数据层代码,您可以浏览(长)帖子的前半部分 - 主要的一点是您使用迭代器块将SqlDataReader转换为IEnumerable<IDataRecord> Once you have that, it's pretty straightforward the rest of the way through. 一旦你拥有了它,那么在剩下的时间里它非常简单。

You could do this: 你可以这样做:

protected void Page_Load(object sender, EventArgs e)
{
    BLL.PostCollection oPost = new BLL.PostCollection();
    rptPosts.DataSource = Post.OpenRecent();
    rptPosts.DataBind();
}
public class Post
{
    public int PostId { get; set; }
    public string PostTitle { get; set; }
    public string PostContent { get; set; }
    public string PostCreatedDate { get; set; }

    public void OpenRecentInitFromRow(DataRow row)
    {
        this.PostId = (int) row["id"];
        this.PostTitle = (string) row["title"];
        this.PostContent = (string) row["content"];
        this.PostCreatedDate = (DateTime) row["createddate"];
    }

    public static List<Post> OpenRecent()
    {
        DataSet ds = DbProvider.Instance().Post_ListRecent();
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            Post oPost = new Post();
            oPost.OpenRecentInitFromRow(row);
            Add(oPost); //Not sure what this is doing
        }
        //need to return a List<Post>
    }
}

暂无
暂无

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

相关问题 使用 Entity Framework Core 更新记录的更好(更清洁)方法 - Better(Cleaner) way to Update Record using Entity Framework Core 将字符串对添加到列表中的更好方法是什么 <T> ? - What is the better way to add pairs of strings into List<T>? 是 List.Find<T> 被认为是危险的? 有什么更好的方式来做 List<T> .Find(谓词<T> )? - Is List.Find<T> considered dangerous? What's a better way to do List<T>.Find(Predicate<T>)? 转换列表中的字符串<int>使用 LINQ(更简洁的方式) - Convert a string in a List<int> using LINQ (cleaner way) 寻找一种更好的方式来排序我的列表<T> - Looking for a better way to sort my List<T> 更清洁的方式来初始化和填充新的List &lt;&gt;? - Cleaner way to initialize & populate a new List<>? 使用 BlockingCollection<T> :OperationCanceledException,有没有更好的办法? - Using BlockingCollection<T>: OperationCanceledException, is there a better way? 有没有更好的方法可以使用“ Linq样式”将列表插入/扩展到列表中? - Is there a better way to insert / expand a list into a list using “Linq style”? 比使用 Type 更清洁的方式(可能是?) - 寻找更清洁方式的代码气味 - Cleaner way than using Type (possibly as?) - code smell looking for cleaner way 什么是迭代或嵌套嵌套对象集合的更有效或更有效的方法 - What is a cleaner or more efficient way of iterating over nested collections of objects
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM