zoukankan      html  css  js  c++  java
  • 枚举数与可枚举类型(笔记)

    要使用foreach遍历类,必须让类实现IEnumerable接口,并且创建一个继承了Enumerator的类接收IEnumerable接口中GetEnumerator()方法的返回值.

    那为什么数组可以直接用foreach遍历其中的数组的项呢?
    因为在声明数组时.net已经隐式的让数组继承了IEnumertabel接口,并且创建了一个继承了IEnumramertor接口的类.(猜想)

    那么现在假设Person类有一个记忆功能,现在我想用foreach遍历person类读取,记忆中的数据,并把数据显示出来..
    所以我先声明一个Person类,他有Name,Age,Memory字段,还有一个构造函数以及一个See方法,模拟人从外界得到记忆,并实现了IEnumerable接口,now,let us begin...

    class Person
    {
    private string name;
    private int age;
    private List<string> memory = new List<string>();
    public string Name
    {
    get
    {
    return name;
    }
    }

    public int Age
    {
    get
    {
    return age;
    }
    }

    public string[] Memory
    {
    get
    {
    return memory.ToArray();
    }
    }

    public Person(string name, int age)
    {
    this.name = name;
    this.age = age;
    }

    public void See(string data)
    {
    memory.Add(data);
    }

    public void See(string[] data)
    {
    memory.AddRange(data);
    }
    }

     //现在如果我们要直接遍历p中的记忆并等到他的记忆,是没有办法的。

     static void Main(string[] args)
    {
    //假设这些就是外界记忆
    string[] data = { "sky", "ok", "mother", "father", "good", "wonderful" };
    Person p = new Person("tom", 18);

    //将p记住了很多单词
    p.See(data);
    //p在又一次记住了一个新的单词
    p.See("wather");
    //现在如果我们先要直接遍历p中的记忆并等到他的记忆,是没有办法的。

    foreach (string item in p)
    {
    Console.WriteLine(item);
    }

    Console.ReadKey();
    }

    上面的代码会报错:

    错误 1 “枚举数和迭代器.Person”不包含“GetEnumerator”的公共定义,因此 foreach 语句不能作用于“枚举数和迭代器.Person”类型的变量 C:\Users\Administrator.think-THINK\Documents\Visual Studio 2008\Projects\c sharp图解教程\枚举数和迭代器\Program.cs 30 13 枚举数和迭代器

    所以我们要让Person类实现IEnumerable接口,IEnumerable接口中有且只有一个GetEnumerator方法,该方法返回IEnumerator类型参数,所以我们要创建了一个继承了IEnumramertor接口的类.用来接收GetEnumerator方放得返回值.

    class Person:IEnumerable
    {
    private string name;
    private int age;
    private List<string> memory = new List<string>();
    public string Name
    {
    get
    {
    return name;
    }
    }

    public int Age
    {
    get
    {
    return age;
    }
    }

    public string[] Memory
    {
    get
    {
    return memory.ToArray();
    }
    }

    public Person(string name, int age)
    {
    this.name = name;
    this.age = age;
    }

    public void See(string data)
    {
    memory.Add(data);
    }

    public void See(string[] data)
    {
    memory.AddRange(data);
    }

    public IEnumerator GetEnumerator()
    {
    return new PersonEnumerator(memory);
    }
    }

    class PersonEnumerator : IEnumerator
    {
    List<string> data = new List<string>();
    public PersonEnumerator(List<string> list)
    {
    data = list;
    }
    private int positon = -1;
    public object Current
    {
    get
    {
    return data[positon];
    }
    }

    public bool MoveNext()
    {
    positon++;
    return positon < data.Count;
    }

    public void Reset()
    {
    positon = -1;
    }
    }

    在此运行代码

    static void Main(string[] args)
    {
    //假设这些就是外界记忆
    string[] data = { "sky", "ok", "mother", "father", "good", "wonderful" };
    Person p = new Person("tom", 18);

    //将p记住了很多单词
    p.See(data);
    //p在又一次记住了一个新的单词
    p.See("wather");
    //现在可行了,因为我们Person实现了IEnumerable接口,并且创建了一个用于接收IEnumramerable方法的继承IEnumerator的类

    foreach (string item in p)
    {
    Console.WriteLine(item);
    }

    Console.ReadKey();
    }

    为什么数组可以直接用foreach遍历其中的item呢?
    因为在声明数组时.net已经隐式的让数组继承了IEnumertabel接口,并且创建了一个继承了IEnumramertor接口的类.(猜想)

    现在我们来模拟下foreach是如何工作的

    static void Main(string[] args)
    {

    string[] data = { "sky", "ok", "mother", "father", "good", "wonderful" };
    Person p = new Person("tom", 18);
    p.See(data);
    p.See("wather");

    //现在让我们模拟foreach是如何工作的

    IEnumerable ieble = (IEnumerable)p;
    IEnumerator itor = ieble.GetEnumerator();

    while (itor.MoveNext())
    {
    string item = (string)itor.Current;
    Console.WriteLine(item);
    }


    Console.ReadKey();
    }

    结果跟上面的一样。。

    完全的代码如下:

    View Code
      1 static void Main(string[] args)
    2 {
    3
    4 string[] data = { "sky", "ok", "mother", "father", "good", "wonderful" };
    5 Person p = new Person("tom", 18);
    6 p.See(data);
    7 p.See("wather");
    8 //现在如果我们先要直接遍历p中的记忆并等到他的记忆,是没有办法的。
    9 //所以我们让person实现了Ienumrabel接口,并且创建一个继承了IEnumerator接口的类来接收IEnumerable方法的返回值,因此我们终于可以用foreach遍历p,得到p 的记忆
    10 //为什么数组可以直接用foreach遍历其中的item呢?
    11 //因为在声明数组时.net已经隐式的为数组让数组继承了IEnumertabel接口,并且创建了一个继承了IEnumramertor接口的类.
    12 foreach (string item in p)
    13 {
    14 Console.WriteLine(item);
    15 }
    16
    17 //现在让我们模拟foreach是如何工作的
    18        //其实这里利用了多态的性质,因为Person继承了IEnumerable接口,所以可以通过接口变量来调用GetEnumerator()方法,这是有理由的...foreach不可能知道你传递过来的是数据是什么类型的,如果你直接用Person来调用,那下次传递过来的是Dog类.那foreach就不能工作了
    19 IEnumerable ieble = (IEnumerable)p;
    20        //为什么不用这个的原因,如上..
    21        //p.GetEnumerator();
    22 IEnumerator itor = ieble.GetEnumerator();//这里也利用了多态,为什么不用PersonEnumerator,而用接口变量,理由是一样的...
    23
    24 while (itor.MoveNext())
    25 {
    26 string item = (string)itor.Current;
    27 Console.WriteLine(item);
    28 }
    29
    30
    31 Console.ReadKey();
    32 }
    33 }
    34 //那么现在假设Person类有一个记忆功能,现在我想用foreach遍历person类读取,记忆中的数据,并把数据显示出来..
    35 //所以我先声明一个Person类,他有Name,Age,Memory字段,还有一个构造函数以及一个See方法,模拟人从外界得到记忆,并实现了IEnumerable接口,now,let us begin...
    36
    37 class Person:IEnumerable
    38 {
    39 private string name;
    40 private int age;
    41 private List<string> memory = new List<string>();
    42 public string Name
    43 {
    44 get
    45 {
    46 return name;
    47 }
    48 }
    49
    50 public int Age
    51 {
    52 get
    53 {
    54 return age;
    55 }
    56 }
    57
    58 public string[] Memory
    59 {
    60 get
    61 {
    62 return memory.ToArray();
    63 }
    64 }
    65
    66 public Person(string name, int age)
    67 {
    68 this.name = name;
    69 this.age = age;
    70 }
    71
    72 public void See(string data)
    73 {
    74 memory.Add(data);
    75 }
    76
    77 public void See(string[] data)
    78 {
    79 memory.AddRange(data);
    80 }
    81
    82 public IEnumerator GetEnumerator()
    83 {
    84 return new PersonEnumerator(memory);
    85 }
    86 }
    87
    88 class PersonEnumerator : IEnumerator
    89 {
    90 List<string> data = new List<string>();
    91 public PersonEnumerator(List<string> list)
    92 {
    93 data = list;
    94 }
    95 private int positon = -1;
    96 public object Current
    97 {
    98 get
    99 {
    100 return data[positon];
    101 }
    102 }
    103
    104 public bool MoveNext()
    105 {
    106 positon++;
    107 return positon < data.Count;
    108 }
    109
    110 public void Reset()
    111 {
    112 positon = -1;
    113 }
    114 }




  • 相关阅读:
    向表中添加列 ALTER TABLE ADD Column_name
    向表中添加列 ALTER TABLE ADD Column_name
    C#类和结构(C# 编程指南)
    C#类和结构(C# 编程指南)
    SQL大小写转换
    SQL大小写转换
    (最新)IIS Express发布网站,实现IP,域名访问站点
    (最新)IIS Express发布网站,实现IP,域名访问站点
    IIS Express允许外部访问(外部调试)
    IIS Express允许外部访问(外部调试)
  • 原文地址:https://www.cnblogs.com/shysky77/p/2275547.html
Copyright © 2011-2022 走看看