实现 IEnumerable,列表
Implementing IEnumerable, Lists
它描述了实现 IEnumerable
以便在 foreach
循环中使用该对象。我的问题是,在示例的主要方法中,它使用 Person
数组来初始化 People
class
。我可以使用 List< ClientEntry>
而不是 ClientEntry
数组吗?为某个 class 实现列表需要什么?
当然可以使用 List<Person>
而不是 Person[]
。您只需要替换所有支持变量,将它们的类型从数组更改为列表,并更改相关代码。然而,重点是 List 已经是可枚举的,因此使用 List 作为内部存储来实现另一个 IEnumerable
没有多大意义,除非你正在做一些特殊的事情,比如根据动态条件等跳过某些元素。
正如在有关 List<T>
的文档中所见,此 class 具有签名:
[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>
.
您无需创建自定义集合即可在列表中使用 class。已经有一个开箱即用的通用集合,可用于任何 class(通过泛型)。
你现在可以这样做了,
[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();
}
现在,如果您想要一个强类型集合,您希望在其中具有 Add/Delete/Insert/Indexing 等的自定义逻辑,那么并且只有在那时您才需要实现 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 且不允许访问它的 add/delete 等方法也很容易。
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();
}
}
做后者允许你将私有列表的内置枚举器暴露给其他东西。所以枚举器接口被包装 class 暴露,那些允许你的 class 被枚举Linq 和 foreach 同时阻止调用者直接访问列表。
您可以通过更多方式利用 List 或 IEnumerable 的强大功能,但通常您可以只使用 List 来满足您的任何需要,很少需要包装一个列表或实现自定义集合的接口。
它描述了实现 IEnumerable
以便在 foreach
循环中使用该对象。我的问题是,在示例的主要方法中,它使用 Person
数组来初始化 People
class
。我可以使用 List< ClientEntry>
而不是 ClientEntry
数组吗?为某个 class 实现列表需要什么?
当然可以使用 List<Person>
而不是 Person[]
。您只需要替换所有支持变量,将它们的类型从数组更改为列表,并更改相关代码。然而,重点是 List 已经是可枚举的,因此使用 List 作为内部存储来实现另一个 IEnumerable
没有多大意义,除非你正在做一些特殊的事情,比如根据动态条件等跳过某些元素。
正如在有关 List<T>
的文档中所见,此 class 具有签名:
[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>
.
您无需创建自定义集合即可在列表中使用 class。已经有一个开箱即用的通用集合,可用于任何 class(通过泛型)。
你现在可以这样做了,
[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();
}
现在,如果您想要一个强类型集合,您希望在其中具有 Add/Delete/Insert/Indexing 等的自定义逻辑,那么并且只有在那时您才需要实现 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 且不允许访问它的 add/delete 等方法也很容易。
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();
}
}
做后者允许你将私有列表的内置枚举器暴露给其他东西。所以枚举器接口被包装 class 暴露,那些允许你的 class 被枚举Linq 和 foreach 同时阻止调用者直接访问列表。
您可以通过更多方式利用 List 或 IEnumerable 的强大功能,但通常您可以只使用 List 来满足您的任何需要,很少需要包装一个列表或实现自定义集合的接口。