码迷,mamicode.com
首页 > 编程语言 > 详细

C# IEnumerator与 IEnumerable

时间:2014-10-17 20:29:49      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   ar   使用   for   sp   

1、 接口的使用

    (1)  首先定义接口

          public interface IBattleMapManager : 
          {
                Stages CurrentStage { get; }
                 event EventHandler<BeginFightEventArgs> EnterFight;
          }

    (2) 用定义实现类- 实现接口

public class BattleMapManager : IBattleMapManager, IDisposable
{

    public Stages CurrentStage { get; private set; }
    public event EventHandler<BeginFightEventArgs> EnterFight;
    protected virtual void OnEnterFight(BeginFightEventArgs e)
    {
        var handler = EnterFight;
        if (handler != null)
            handler(this, e);
    }

    private void trigger_Triggered(object sender, TriggerEvent.ColliderEventArgs e)
    {
        var trigger = (TriggerEvent)sender;
        var index = fightTriggerEvents.IndexOf(trigger);
        trigger.enabled = false;
        OnEnterFight(new BeginFightEventArgs(index));
    }
}

 (3)  用接口定义对象  用接口实现类对对象实例化 -多态化

partial class RootBattleState
{
    private IBattleMapManager battleMapManager;
    private IEnumerator InitializeBattleAsync()
   {
        battleMapManager = new BattleMapManager();
        battleMapManager.EnterFight += battleMapManager_EnterFight;
battleMapManager.LoadMap(Stages.BattleStage1); } }

 

 

IEnumerator: 提供在普通集合中遍历的接口,有Current,MoveNext(),Reset(),其中Current返回的是object类型。

IEnumerable: 暴露一个IEnumerator,支持在普通集合中的遍历。

IEnumerator<T>:继承自IEnumerator,有Current属性,返回的是T类型。

IEnumerable<T>:继承自IEnumerable,暴露一个IEnumerator<T>,支持在泛型集合中遍历。

1. 要使自定义的集合类型支持foreach访问,就要实现IEnumerable接口。

2. 在很多地方有讨论为什么新增加的泛型接口IEnumerable<T>要继承IEnumerable,这是为了兼容。

理论上所有的泛型接口都要继承自所有的非泛型接口。然而特殊的是IList<T>没有继承自IList接口:

因为如果让IList<T>继承IList的话,那么是实现IList<int>的类就需要实现两个Insert方法,

 一个是IList<int>的void Insert(int index, int item),

 一个是IList的void Insert(int index, object item),

这是就有一个接口可以把object类型的数据插入到IList<int>集合中了,这是不对的,所以不继承。
而IEnumerable<T>不同的是,它只有”输出“的作用,也就是说我们只会从它里面取数据,所以不会有上面描述的混乱出现。

3. 下面的例子描述了如何使用
首先,有一个Person类:

public class Person
{
    public string firstName;
    public string lastName;
    public Person(string fName, string lName)
    {
       this.firstName = fName;
       this.lastName = lName;
    }
 }

第一种方式实现People集合

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
       _people = new Person[pArray.Length];
       for (int i = 0; i < pArray.Length; i++)
       {
           _people[i] = pArray[i];
       }
    }
    public IEnumerator GetEnumerator()
    {
       return new PeopleEnum(_people);
    }
 }
 public class PeopleEnum : IEnumerator
 {
      public Person[] _people;
      int position = -1;
      public PeopleEnum(Person[] list)
      {
        _people = list;
      }
      public bool MoveNext()
      {
         position++;
         return (position < _people.Length);
      }
      public void Reset()
      {
        position = -1;
      }
      public object Current
      {
         get
         {
           try
           {
              return _people[position];
           }
           catch (IndexOutOfRangeException)
           {
              throw new InvalidOperationException();
           }
          }
}
}

第二种方式,让People自己也实现IEnumerator接口:

public class People : IEnumerable, IEnumerator
{
        private Person[] _people;
        int position = -1;
        public People(Person[] pArray)
        {
            _people = new Person[pArray.Length];
            for (int i = 0; i < pArray.Length; i++)
            {
                _people[i] = pArray[i];
            }
        }
        #region IEnumerable Members
        public IEnumerator GetEnumerator()
        {
            return this;
        }
        #endregion
        #region IEnumerator Members
        public object Current
        {
            get 
            {
                try
                {
                    return _people[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new IndexOutOfRangeException();
                }
            }
        }
        public bool MoveNext()
        {
            position++;
            return (position < _people.Length);
        }
        public void Reset()
        {
            position = -1;
        }
        #endregion
}

 第三种方式,用泛型指定了类型:

public class People : IEnumerable<Person>, IEnumerator<Person>
{
        private Person[] _people;
        int position = -1;
        public People(Person[] pArray)
        {
            _people = new Person[pArray.Length];

            for (int i = 0; i < pArray.Length; i++)
            {
                _people[i] = pArray[i];
            }
        }
        #region IEnumerable<Person> Members
        public IEnumerator<Person> GetEnumerator()
        {
            return this;
        }
        #endregion
        #region IEnumerable Members
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this;
        }
        #endregion
        #region IEnumerator<Person> Members
        public Person Current
        {
            get
            {
                try
                {
                    return _people[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new IndexOutOfRangeException();
                }
            }
        }
        #endregion
        #region IDisposable Members
        public void Dispose()
        {}
        #endregion
        #region IEnumerator Members
        object IEnumerator.Current
        {
            get
            {
                try
                {
                    return _people[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new IndexOutOfRangeException();
                }
            }
        }
        public bool MoveNext()
        {
            position++;
            return (position < _people.Length);
        }
        public void Reset()
        {
            position = -1;
        }
        #endregion
}

 
然后就可以用foreach对自定义集合访问了:

Person[] peopleArray = new Person[3]
 {
      new Person("John", "Smith"),
      new Person("Jim", "Johnson"),
      new Person("Sue", "Rabon"),
};
 People peopleList = new People(peopleArray);
 foreach (Person p in peopleList)
     Console.WriteLine(p.firstName + " " + p.lastName);

 

下面介绍yield关键字的用法:

注意两点:

第一: 它只能用在一个iterator的方法中,也就是说这个方法的返回值类型只能是IEnumerable,IEnumerator,IEnumerable<T>或IEnumerator<T>;

第二: 它只有两种语法:yield return 表达式;或者是yield break; 

(1) 下面用yield return返回循环中每一个满足条件的值,但是并不退出方法:

public static class NumberList
{
   public static int[] ints = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377 }; 
   // Define a property that returns only the even numbers.
   public static IEnumerable<int> GetEven()
   {
        foreach (int i in ints)
          if (i % 2 == 0)
             yield return i;
    }
}

调用的地方如下:

// Display the even numbers.
Console.WriteLine("Even numbers");
foreach (int i in NumberList.GetEven())
   Console.WriteLine(i);

在这种用iterator的循环中,只能用yield break退出循环(也退出了整个方法),若是用break是编译不过的:

public static IEnumerable<int> GetEven()
{
   foreach (int i in ints)
       if (i % 2 == 0)
          yield break;
       Console.WriteLine();
}

如果yield break;会被执行到的话,则后面的Console.WriteLine();是不会被执行的,整个方法体已经在yield break被执行后就退出了。

(2) 另外下面这种写法:

IEnumerable<int> GetValues()
{
     yield return 1;
     yield return 2;
     yield return 3;
     yield return 4;
 }
则可以用
foreach (int i in this.GetValues())
{
    Console.WriteLine(i);
}

来输出,第一次取第一个yield return的值1,第二次取第二个yield return的值2,依此类推

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C# IEnumerator与 IEnumerable

标签:style   blog   color   io   os   ar   使用   for   sp   

原文地址:http://www.cnblogs.com/liusj/p/4031874.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!