实现IEnumerable,列表

时间:2015-05-26 02:24:31

标签: c# list ienumerable

我找到了this MSDN tutorial

它描述了实现uspUser_GetUserDetails 'LastName','FirstName','UserId',null,'DistrictId' 以便在IEnumerable循环中使用该对象。我的问题是,在示例的主要方法中,它使用foreach数组初始化Person People。我可以使用class而不是List< ClientEntry>数组吗?为某个类实现List需要什么?

3 个答案:

答案 0 :(得分:2)

肯定可以使用List<Person>代替Person[]。您只需要替换所有支持变量,将其类型从数组更改为List并更改相关代码。然而,重点是List已经是可枚举的,因此使用List作为内部存储来实现另一个IEnumerable没有多大意义,除非你正在做一些特别的事情,比如根据动态条件等跳过某些元素。 / p>

答案 1 :(得分:2)

正如可以在关于List<T>的文档中看到的那样,这个类有签名:

[SerializableAttribute]
[DebuggerDisplayAttribute("Count = {Count}")]
public class List<T> : IList<T>, ICollection<T>, 
    IEnumerable<T>, IEnumerable, IList, ICollection, IReadOnlyList<T>, 
    IReadOnlyCollection<T>

如您所见,它已经实施了IEnumerable<T>IEnumerable。这意味着每个List<T>实例都可以在foreach循环中使用:

List<Person> people = new List<Person>();
//add people
foreach(Person p in people) {
}

此外,对T没有限制(您可以使用您喜欢的任何类型)。否则签名应包含

public class OtherList<T> : IEnumerable<T> where T : class

where T : ...表示T应满足某个约束。完全没有必要自己开始实施List<T>

List<T>class。由于C#不允许多重继承,因此只能通过添加继承来从Peolpe创建List<People>元素:

// Collection of Person objects. This class 
// implements IEnumerable so that it can be used 
// with ForEach syntax. 
public class People : List<Person> {

    public People(Person[] pArray) {
        this.AddRange(pArray);
    }

}

在这种情况下,您不必实施IEnumerable<T>和其他接口。但是,只有当您想要添加其他行为(或修改某些行为)时,才有理由使用People而不是List<Person>

答案 2 :(得分:1)

您无需创建自定义集合即可在列表中使用类。已经有一个开箱即用的通用集合可用于任何类(通过泛型)。

你现在可以这样做,

[Flags()]
public enum AddressTypeValue : ushort
{
    Personal = 0,
    Business = 1,
    POBox = 2,
    Inertnational = 4
}
public class Address
{
    public AddressTypeValue AddressType { get; set; }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Address Address { get; set; }

    public Person() 
    {
        Address = new Address() { AddressType == AddressTypeValue.Personal };
    }
}

//在列表中使用它的一些代码

List<Person> people = new List<Person>();

public List<Person> GetPeopleMatchingFirstName(string firstNameToMatch)
{
    var people = DBContext.People.Where(p => p.FirstName.BegintsWith(firstNameToMatch) || p.FirstName.EndsWith(firstNameToMatch) || p.FirstName.Equals(firstNameToMatch, StringComparison.InvariantCultureIgnoreCase);
    return people.ToList();
}

现在,如果您想要一个强类型集合,您希望在其中添加/删除/插入/索引等自定义逻辑,那么您只需要实现IList或IEnumerable。

有更简单的方法可以做到这一点,因为你只是通过继承实现List并覆盖你想要改变的东西。如果您要更改的行为不是虚拟的(无法覆盖),那么您可能需要List的自定义实现。

public class MyCustomListOfPeople : List<Person>
{
    public override Add(Person person)
    {
        //send email that a person was added or w/e you want to do here
        base.Add(person);
    }
}

如果您想要一个只读列表,那么无法添加内容,那么您可以在传入基本列表的地方使用ReadOnlyCollection。构建完成后,无法在ReadOnlyCollection中添加或删除任何内容。这对于状态列表,邮政编码,报告数据等等非常有用。

包装List并将其公开为IEnumerable也很容易,而不允许访问它的添加/删除等方法。

public class AnotherListOfPeople : IEnumerable<Person>
{
    private List<Person> internalList = new List<Person>();

    //internal logic to manipulate people

    public IEnumerator<Person> GetEnumerator()
    {
        return internalList.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return internalList.GetEnumerator();
    }
}

执行后者允许您将私有列表的内置枚举器表示为其他内容。因此,枚举器接口由包装类公开,允许使用Linq和foreach枚举您的类,同时阻止调用者直接访问列表。

您可以通过更多方式利用List或IEnumerable的强大功能,但通常您可以只使用List来满足您的需求,而且很少需要为自定义集合包装或实现接口。