Skip to main content
 首页 » 编程设计

c#之为什么编译器无法推断自定义集合的循环变量类型

2024年01月26日26Terrylee

有时编译器无法推断变量类型。例如,如果我定义一个 string 列表,如下所示:

或者字符串数组List:

显然编译器会推断项目的类型。但是如果我这样做:

 public class Foo  
    : IEnumerable 
{ 
    List<string> _fooRecords = new List<string>(); 
 
    public IEnumerator GetEnumerator() 
    { 
        return _fooRecords.GetEnumerator(); 
    } 
} 

或者这个:

public class Foo  
    : IEnumerable 
{ 
    List<string> _fooRecords = new List<string>(); 
 
    public IEnumerator GetEnumerator() 
    { 
        foreach (var item in _fooRecords) 
        { 
            yield return item; 
        } 
    } 
} 

编译器无法推断变量类型:

然后我想也许我需要实现 IEnumerator 接口(interface),我做了这样的事情:

public class FooEnumerator : IEnumerator 
{ 
    private List<string> recordsList; 
    private int index; 
    private string current; 
    public FooEnumerator(List<string> list) 
    { 
        recordsList = list; 
    } 
 
    public object Current 
    { 
        get { return current; } 
    } 
 
    public bool MoveNext() 
    { 
        if (index != recordsList.Count - 1) 
        { 
            current = recordsList[index]; 
            index++;  
            return true; 
        } 
        return false; 
    } 
 
    public void Reset() 
    { 
        index = 0; 
    } 
} 

像这样使用它(在 Foo 类中):

public IEnumerator GetEnumerator() 
{ 
     return new FooEnumerator(_fooRecords); 
} 

但是什么都没有改变。现在我想知道为什么编译器不能为自定义类型推断循环变量类型?当然Foo类只是一个例子,.NET Framework中有很多自定义集合。例如Form类的ControlCollection:

当我循环遍历 Form 控件时,我不能这样做:

foreach (var item in this.Controls) 
{ 
     item.Name = "bla bla bla.."; //error 
} 

我需要指定类型或者我需要使用OfType扩展方法:

foreach (Control item in this.Controls) 
{ 
     item.Name = "bla bla bla.."; // OK! 
} 
 
foreach (var item in this.Controls.OfType<Control>()) 
{ 
     item.Name = "bla bla bla.."; // OK! 
} 

现在我只是想知道真正的原因是什么,编译器不够聪明?或者在循环执行之前无法确定返回类型?

请您参考如下方法:

A non-generic enumerator可以返回任何对象(Current 字段的类型是对象),所以编译器无法推断任何东西。在 generic enumerator类型 T,推断元素类型 T。幸运的是,foreach 构造支持指定类型并且不进行任何编译时验证,因此可以轻松处理非泛型枚举数。