Inside.Net

自由与繁荣的国度

博客园 首页 新随笔 联系 订阅 管理

范型和迭代器

.NET Framework 2.0IEnumerableIEnumerator接口都提供了一种范型形态。

namespace System.Collections.Generic
{
    [System.Runtime.InteropServices.ComVisibleAttribute(
false)]
    [Systen,CLSCompliantAttribute(
false)]
    
public interface IEnumerable<T>
{
System.Collections.Generic.IEnumerator
<T> GetEnumerator();
}

[System.Runtime.InteropServices.ComVisibleAttribute(
false)]
[Systen,CLSCompliantAttribute(
false)]
public interface IEnumerator<T> : System.Idisposable
{
    T Current
    
{
        
get;
    }

    
bool MoveNext();
}

}

 

我们注意到IEnumerator接口实现了IDisposable接口,同时还注意到IEnumerator.Reset()方法已经被去掉了。现在我们能告诉编译器它枚举的是一个字符串集合而不是一个对象集合。

using System;
using Systen,Collections.Generic;
public class Persons : IEnumerable<string>
{
    
string[] m_Names;
    
public Persons(params string[] Names)
    
{
        m_Names 
= new string[Names.Length];
        Names.CopyTo(m_Names,
0);
    }

    
public IEnumerator<string> GetEnumerator()
    
{
        
foreach (string s in m_Names)
            yield 
return s;
    }

}



单一枚举包含多个枚举构造器

using System;
using Systen,Collections.Generic;
public class Persons : IEnumerable<string>
{
    
string[] m_Names;
    
public Persons(params string[] Names)
    
{
        m_Names 
= new string[Names.Length];
        Names.CopyTo(m_Names,
0);
    }

    
public IEnumerable<string> Reverse
    
{
        
get
        
{
            
for (int i = m_Names.Length - 1; i >= 0; i--)
                yield 
return m_Names[i];
        }

    }

    
public IEnumerable<string> PositionsPaires
    
{
        
get
        
{
            
for (int i= 0; i<= m_Names.Length; i++,i++)
                yield 
return m_Names[i];
        }

    }

    
public IEnumerable<string> Concat
    
{
        
get
        
{
            
foreach (string s in Reverse)
                yield 
return s;
            
foreach (string s in PositionsPaires)
                yield 
return s;
        }

    }

}

class Program
{
    
static void Main (string[] args)
    
{
Persons arrPersons 
= new Persons("Michel","Christine","Mathieu","Julien");
Console.WriteLine("-->Iterator Reverse");
foreach (string s in arrPersons.Reverse)            Console.WriteLine(s);
Console.WriteLine("-->Iterator PositionPaires");
foreach (string s in arrPersons. PositionPaires)    Console.WriteLine(s);
Console.WriteLine("-->Iterator Concat");
foreach (string s in arrPersons.Concat)            Console.WriteLine(s);
Console.ReadLine();
    }

}


程序将产生以下输出:

-->Iterator Reverse
Julien
Mathieu
Christine
Michel
-->Iterator PositionsPaires
Michel
Mathieu
-->Iterator Concat
Julien
Mathieu
Christine
Michel
Michel
Mathieu


yield break
关键字

你如果希望枚举集合中的一些子元素,在这个例子中,yield break关键字正确的告知客户它将中止循环。

public IEnumerator<string> GetEnumerator()
{
    
for (int I = 0;I < 2; I++)
        yield 
return m_Names[i];
    yield 
break;
    Console.WriteLine(“Hello”);  
//警告:检测到一个不能到达的代码段
}


程序将会输出:

Michel
Christine

 

结果是,书写在yield break指令后的代码不会被编译,编译器如果发现这些不能到达的语句将发出一个警告信息。

yield return yield break关键字的语法约束

l         yield returnyield break关键字只能用于一个方法,一个属性访问器或者一个操作符(重载方法)的内部;

l         任何使用了yield returnyield break关键字的方法都必须返回一个以下的接口System.Collections.Generic.IEnumerable<T>,System.Collections.IEnumerable,System.Collections.Generic.IEnumerator<T> 或者 System.Collections.IEnumerator

l         yield returnyield break关键字不能用在匿名方法的内;

l         yield returnyield break关键字不能用在finally块使用;

l         yield returnyield break关键字不能用在try块(至少具有一个catch块);

yield returnyield break关键字不能用在含有refout参数的方法中,可以预示的是包含refout这些关键字的方法并不能返回任何yield关键字约束的内容信息。

一个递归迭代器的例子:

下面这个例子有力的展示了使用C# 2.0迭代器枚举一个non-flat集合,就像一个二叉树:

using System;
using System.Collections.Generic;

public class Node<T>
{
    
public Node ( T item, Node<T> leftNode, Node<T> rightNode)
    
{
        m_Item 
= item;
        m_LeftNode 
= leftNode;
        m_RightNode 
= rightNode;
    }

    
public Node<T> m_LeftNode;
    
public Node<T> m_RightNode;
    
public T m_Item;
}

public class BinaryTree<T>
{
    Node
<T> m_Root;
    
public BinaryTree(Node<T> Root)
    
{
        m_Root 
= Root;
    }

    
public IEnumerable<T> InOrder
    
{
        
get
        
{
            
return PrivateScanInOrder(m_Root);
        }

    }

    
private IEnumerable<T> PrivateScanInOrder(Node<T> root)
    
{
        
if (root.m_LeftNode != null)
            
foreach (T item in PrivateScanInOrder(root.m_LeftNode))
            
{
                yield 
return item;
            }

        yield 
return root.m_Item;
        
if (root.m_RightNode != null)
            
foreach (T item in PrivateScanInOrder(root.m_RightNode))
            
{
                yield 
return item;
            }

    }

}

class Program
{
    
static void Main(string[] args)
    
{
        BinaryTree
<string> binaryTree = new BinaryTree<string>(new Node<string>("A",new Node<string>("B",null,null),new Node<string>("C",new Node<string>("D",null,null),new Node<string>(“D”,null,null))));
        
foreach (string s in binaryTree.InOrder)
        
{
            Console.WriteLine(s);
            Console.ReadLine();
        }

    }

}


Main方法中二叉树如下表示:

该程序输出:

B
A
D
C
E

未完待续

posted on 2005-03-31 09:35  Bluefee.Net  阅读(1280)  评论(3编辑  收藏  举报