我想用一个可以在运行时设置的枚举器定义一个集合。
我定义了一个枚举器:
public class JuniorEmployeeEnumerator : IEnumerable<Employee> {
List<Employee> list = new List<Employee>();
public JuniorEmployeeEnumerator(List<Employee> emplist) {
list = emplist;
}
public IEnumerator<Employee> GetEnumerator() {
for (int i = 0; i < list.Count; i++) {
if (list[i].Age < 50) {
yield return list[i];
}
}
}
IEnumerator IEnumerable.GetEnumerator() {
return (GetEnumerator());
}
}
该集合接受枚举器:
public class EmployeeCollection : IEnumerable<Employee> {
public List<Employee> Employees { get; set; }
public IEnumerable<Employee> EnumeratorType { get; set; }
public EmployeeCollection() {
Employees = new List<Employee>();
}
public IEnumerator<Employee> GetEnumerator() {
return EnumeratorType.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return (GetEnumerator());
}
}
因此,用法应为:
static void Main(string[] args) {
EmployeeCollection empcoll = new EmployeeCollection();
empcoll.Employees.Add(new Employee("Fatima", 57));
empcoll.Employees.Add(new Employee("Evangeline", 52));
empcoll.Employees.Add(new Employee("Damien", 49));
empcoll.Employees.Add(new Employee("Cameroon", 55));
empcoll.Employees.Add(new Employee("Babu", 24));
Console.Write("Senior Employees \n");
empcoll.EnumeratorType = new JuniorEmployeeEnumerator(empcoll.Employees);
foreach (Employee anEmp in empcoll.GetEnumerator()) {
Console.Write(" " + anEmp.Name + " " + anEmp.Age + "\n");
}
Console.ReadKey();
}
但是我得到了这个编译错误:
foreach语句不能对'System.Collections.Generic.IEnumerator'类型的变量进行操作,因为'System.Collections.Generic.IEnumerator'不包含'GetEnumerator'的公共定义
我该如何解决?
答案 0 :(得分:3)
使用foreach循环IEnumerable,而不是IEnumerator。
因此,而不是
foreach (Employee anEmp in empcoll.GetEnumerator()) {
Console.Write(" " + anEmp.Name + " " + anEmp.Age + "\n");
}
你可以这样做:
foreach (Employee anEmp in empcoll) {
Console.Write(" " + anEmp.Name + " " + anEmp.Age + "\n");
}
基本上,foreach关键字只是语法糖:
using (var enumerator = enumerable.GetEnumerator()) {
T loopVar;
while (enumerator.MoveNext()) {
loopVar = enumerator.Current;
... loop body ...
}
}
也就是说,LINQ运算符(例如Where())可能是您尝试解决的问题的更好解决方案:
List<Employee> emps = ...;
foreach (var junior in emps.Where(e => e.Age < 50)) {
...
}
答案 1 :(得分:0)
你弄错了。枚举器基本上是C#如何处理枚举器的所有部分。您不必担心这些,因为所有集合类都已为您实现了这些。您似乎要寻找的是Enumerable.Where
扩展方法,位于System.Linq
。以下是代码:
public class EmployeeCollection : IEnumerable<Employee>
{
public List<Employee> Employees { get; set; }
public EmployeeCollection()
{
Employees = new List<Employee>();
}
public IEnumerator<Employee> GetEnumerator()
{
return Employees.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return Employees.GetEnumerator();
}
}
public class X
{
static void Main(string[] args)
{
EmployeeCollection empcoll = new EmployeeCollection();
empcoll.Employees.Add(new Employee("Fatima", 57));
empcoll.Employees.Add(new Employee("Evangeline", 52));
empcoll.Employees.Add(new Employee("Damien", 49));
empcoll.Employees.Add(new Employee("Cameroon", 55));
empcoll.Employees.Add(new Employee("Babu", 24));
Console.Write("Senior Employees \n");
foreach (Employee anEmp in empcoll.Where(n => n.Age > 50))
{
Console.WriteLine(" " + anEmp.Name + " " + anEmp.Age);
}
Console.ReadKey(true);
}
}
答案 2 :(得分:0)
你为自己制造的东西太复杂了。 Modern C#确保您基本上从不必须编写自定义枚举器,尤其是对于内置集合类。
这主要是通过LINQ实现的,LINQ提供了许多方法来过滤和将集合的元素投影到新的可枚举中。
例如,根据您的员工名单,如果您想获得所有初级员工,您可以这样做:
foreach (Employee junior in empColl.Employees.Where(emp => emp.Age < 50))
{
// Do something with the junior employee object
}