2

我想用一个可以在运行时设置的枚举器定义一个集合。

我定义了一个枚举器:

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”的公共定义

我该如何解决?

4

3 回答 3

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)) {
   ...
}
于 2013-06-22T17:32:27.633 回答
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);
    }
}
于 2013-06-22T17:29:42.773 回答
0

你把事情弄得太复杂了。现代 C# 确保您基本上不必编写自定义枚举器,尤其是对于内置集合类。

这主要是通过 LINQ 实现的,它提供了多种方法来过滤集合的元素并将其投影到新的枚举中。

例如,给定您的员工列表,如果您想获取所有初级员工,您可以这样做:

foreach (Employee junior in empColl.Employees.Where(emp => emp.Age < 50))
{
    // Do something with the junior employee object
}
于 2013-06-22T17:30:35.867 回答