Skip to content

Instantly share code, notes, and snippets.

@birdinforest
Last active June 7, 2016 00:30
Show Gist options
  • Save birdinforest/c5d72df4dbed10540b331106b387cc0a to your computer and use it in GitHub Desktop.
Save birdinforest/c5d72df4dbed10540b331106b387cc0a to your computer and use it in GitHub Desktop.
Example of IEnumerable and IEnumerator. Show what 'yiled' statement dose.
using UnityEngine;
using System.Collections;
/// <summary>
/// Try to learn IEnumerable and IEnumerator.
/// Find out what 'yiled' statement dose. Ref: https://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx
/// </summary>
namespace Lab.IEnumerableTest {
public class Car
{
public string name;
public int speed;
public string inGarageName;
public Car(string n, int s, string inGarageName) { name = n; speed = s; this.inGarageName = inGarageName; }
public string Print() {
return name + " " + speed + ". in garage: " + inGarageName;
}
}
public class Garage : IEnumerable {
public string name;
// Can go to next garage from this one.
public Garage gotoNext;
public Car[] cars = new Car[4];
public Garage (string name) {
this.name = name;
cars [0] = new Car ("Mazada", 100, name);
cars [1] = new Car ("Toyota", 200, name);
cars [2] = new Car ("SuperMazada", 300, name);
cars [3] = new Car ("SuperToyota", 400, name);
}
public void SetNextGarage(Garage gotoNext) {
this.gotoNext = gotoNext;
}
// Do foreach on a garage instance will loop all cars.
public IEnumerator GetEnumerator() {
return cars.GetEnumerator ();
}
public string PrintCar(Car car) {
return car.name + " " + car.speed + ". in garage name: " + car.inGarageName;
}
}
/// <summary>
/// Contains several garages. They are connected one by one like a single path link.
/// Try to use foreach to loop all garages by IEnumerable interface.
/// </summary>
public class GarageChain : IEnumerable {
public Garage garageA = new Garage ("A");
public Garage garageB = new Garage ("B");
public Garage garageC = new Garage ("C");
public GarageChain () {
// Connect them.
garageA.SetNextGarage (garageB);
garageB.SetNextGarage (garageC);
garageC.SetNextGarage (null); // Don't need this line. Just make it clear.
}
// Do foreach on GarageChian instance will loop cars in all garages.
public IEnumerator GetEnumerator() {
Garage current = garageA;
// NOTE: If don't use 'yield' statement, following code only loop cars in first garage.
// 'When a yield return statement is reached in the iterator method, expression is returned, and the current location in code is retained.
// Execution is restarted from that location the next time that the iterator function is called.'
while (current != null) {
foreach (Car car in current) {
yield return car;
}
current = current.gotoNext;
}
// End
yield break;
}
}
/// <summary>
/// Test script works on Unity3D.
/// </summary>
public class CheckCars : MonoBehaviour {
GarageChain chain = new GarageChain();
void Start() {
// This is internal logic.
Debug.Log ("- Manully Loop - ");
IEnumerator carEnumerator = chain.GetEnumerator ();
while (carEnumerator.MoveNext ()) {
// This is where 'foreach' performance bug happens in Unity3D.
// There are boxing and unboxing operations as carEnumerator.Current is object.
Debug.Log ("cars: " + ((Car)carEnumerator.Current).Print ());
}
// Wrap to foreach statement.
Debug.Log ("- Foreach Loop - ");
foreach (Car c in chain) {
Debug.Log ("cars: " + c.Print ());
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment