代码改变世界

.NET中一些常用的基本接口IComparable,IComparer,IEnumerable,IEnumerator,IComparable<T>,IList,ICollection,IQueryable,IDictionary

2012-08-03 16:41 by leo.wl2020, ... 阅读, ... 评论, 收藏, 编辑

NET中一些常用的基本接口IComparable,IComparer,IEnumerable,IEnumerator,IComparable<T>,IList,ICollection,IQueryable,IDictionary等等,实现自定义类型的foreach ,实现自定义类型的比较,以及索引器等,到MSDN上可以看到大量的资料。

foreach

我的代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class MyColors : IEnumerable
    {
        string[] colors = { &quot;Red&quot;, &quot;Yellow&quot;, &quot;Blue&quot; };
        /*
         *这样就能使用实现这个接口的对象进行foreach遍历了,
         * 就是这么简单的一个列子,这边可能有的人会有疑问,
         * 我们就实现了IEnumerable接口但却没实现IEnumerator接口,
         * 可是我们不是说只有实现了这两个接口才可以进行foreach遍历吗?
         * 可以这样说当使用forach进行遍历的时候,
         * 编译器会到这个对象的类中去寻找GetEnumerator方法,
         * 找到这个方法后返回这个一个IEnumerator的对象(枚举数),
         * 而我这边返回的是“colors.GetEnumerator()”,
         * 是一个数组对象调用它本身中的“GetEnumerator”方法,
         * 所以说数组本身就实现了IEnumerator接口,那么两个接口都实现了,不就好实现foreach遍历了,
         * 其实在实现遍历枚举数的时候编译器会自动去调用数组中实现枚举数的类中的方法。
         */
        public IEnumerator GetEnumerator()
        {
            return colors.GetEnumerator();
        }
    }
}

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class MyIEnumerator : IEnumerator
    {
        public MyIEnumerator(string[] colors)
        {
            this.colors = new string[colors.Length];
            for (int i = 0; i &lt; this.colors.Length; i++)
                this.colors[i] = colors[i];
        }
        string[] colors;        //定义一个数组,用来存储数据
        int position = -1;      //定义当前项的默认值,也就是索引值,一开始认识数组的索引从“0”开始,
        //怎么默认设置他为“-1”呢,最后才想明白,这样设置是合情合理的!

        public object Current       //根据当前项获取相应的值
        {
            get
            {
                return colors[position];          //返回当前项的值,但是会做一个装箱的操作!
            }
        }

        public bool MoveNext()                  //移动到下一项
        {
            if (position &lt; colors.Length - 1)     //这就是设置默认值为-1的根据
            {
                position++;
                return true;
            }
            else
            {
                return false;
            }
        }

        //重置当前项的值,恢复为默认值
        public void Reset()
        {
            this.position = -1;
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class MyNewColors
    {
        string[] colors = { &quot;Red&quot;, &quot;Yellow&quot;, &quot;Blue&quot; };

        /*
         *上面讲到的IEnumerable接口中GetEnumerator方法是获取要遍历的枚举数,
         *在我们没有创建自己的遍历枚举数的类时,
         *我们使用的是Array的遍历枚举数的方法(关于数组的可枚举类型和枚举数会在下一篇讲到),
         *但这个有的时候不一定适合我们,我们需要为自己定制一个更合适的,所以我们要创建自己的枚举数类(也就是上面的代码),
         * 把第三点和第四点的代码合并起来(改动一点代码),如下:
         */
        public IEnumerator GetEnumerator()
        {
            return new MyIEnumerator(colors);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class MyStudent : IComparable
    {
        public int age;
        public string name;
        public MyStudent()
        {
        }
        public MyStudent(string name, int age)
        {
            this.age = age;
            this.name = name;
        }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (obj is MyStudent)
            {
                MyStudent stu = (MyStudent)obj;
                return this.age - stu.age;
            }
            else
            {
                throw new Exception(&quot;类型不兼容!&quot;);
            }
        }

        #endregion
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class MyStudentDefault : IComparer
    {
        public static MyStudentDefault Default = new MyStudentDefault();
        public int Compare(object x, object y)
        {
            if (x is MyStudent &amp;&amp; y is MyStudent)
            {
                MyStudent s1 = (MyStudent)x;
                MyStudent s2 = (MyStudent)y;
                //return s1.age - s2.age;  //按年龄
                return string.Compare(s1.name ,s2.name);//按名字
            }
            else
            {
                throw new Exception(&quot;类型不兼容&quot;);
            }
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class People : IEnumerable
    {
        private Person[] _people;

        public People(Person[] pArray)
        {
            _people = new Person[pArray.Length];

            for (int i = 0; i &lt; pArray.Length; i++)
            {
                _people[i] = pArray[i];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return (IEnumerator)GetEnumerator();
        }

        public PeopleEnum GetEnumerator()
        {
            return new PeopleEnum(_people);
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class PeopleEnum : IEnumerator
    {
        public Person[] _people;

        // Enumerators are positioned before the first element
        // until the first MoveNext() call.
        int position = -1;

        public PeopleEnum(Person[] list)
        {
            _people = list;
        }

        public bool MoveNext()
        {
            position++;
            return (position &lt; _people.Length);
        }

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

        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }

        public Person Current
        {
            get
            {
                try
                {
                    return _people[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

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

        public string firstName;
        public string lastName;
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] myArray = { 1, 32, 33, 35, 34, 36 };
            IEnumerator myie = myArray.GetEnumerator();
            myie.Reset();
            while(myie.MoveNext())
            {
                int i = (int)myie.Current;
                Console.WriteLine(&quot;Value: {0}&quot;,i);
            }

            Console.WriteLine(&quot;*************************************&quot;);
            foreach (var item in myArray)
            {
                Console.WriteLine(item.ToString());
            }

            Console.WriteLine(&quot;*************************************&quot;);
            MyColors colors = new MyColors();
            foreach (string item in colors)
                Console.WriteLine(item);

            Console.WriteLine(&quot;-------------------------------------&quot;);
            Person[] peopleArray = new Person[3]
            {
                new Person(&quot;John&quot;, &quot;Smith&quot;),
                new Person(&quot;Jim&quot;, &quot;Johnson&quot;),
                new Person(&quot;Sue&quot;, &quot;Rabon&quot;),
            };

            People peopleList = new People(peopleArray);
            foreach (Person p in peopleList)
                Console.WriteLine(p.firstName + &quot; &quot; + p.lastName);
            Console.WriteLine(&quot;-------------------------------------&quot;);
            XClass[] objs = { new XClass(5), new XClass(10) ,new XClass(1)};
            Array.Sort(objs);
            foreach (XClass obj in objs)
                Console.WriteLine(obj.Number);
            Console.WriteLine(&quot;------------------------------------&quot;);
            Student s1 = new Student();
            Student s2 = new Student();
            s1.Name = &quot;张四强&quot;;
            s2.Name = &quot;张四&quot;;
            s1.Score = 112;
            s2.Score = 211;
            Console.WriteLine(s1.CompareTo(s2));// print : -1
            Console.WriteLine(&quot;----------------------------------&quot;);
            SampleCollection&lt;string&gt; stringCollection = new SampleCollection&lt;string&gt;();
            Console.WriteLine(&quot;Length:&quot; + stringCollection.Length() + &quot; Count:&quot; + stringCollection.Count());
            stringCollection[0] = &quot;Hello, World&quot;;
            System.Console.WriteLine(stringCollection[0]);

            Console.WriteLine(&quot;---------------------------------&quot;);
            Student[] myStudents = new Student[2];
            myStudents[0] = s1;
            myStudents[1] = s2;
            foreach (var item in myStudents)
            {
                Console.WriteLine(item.Name + &quot; : &quot; + item.Score);
            }
            Array.Sort(myStudents, new StudentNameComparer());
            foreach (var item in myStudents)
            {
                Console.WriteLine(item.Name + &quot; : &quot; + item.Score);
            }

            Console.WriteLine(&quot;--------------------------------&quot;);

            MyStudent stu = new MyStudent(&quot;秦涛&quot;, 23);
            MyStudent stu1 = new MyStudent(&quot;王涛&quot;, 35);
            MyStudent stu2 = new MyStudent(&quot;张军&quot;, 28);
            ArrayList list = new ArrayList();
            list.Add(stu);
            list.Add(stu1);
            list.Add(stu2);
            foreach (MyStudent var in list)
            {
                Console.WriteLine(var.name + &quot;年龄是&quot; + var.age);
            }
            list.Sort();
            foreach (MyStudent var in list)
            {
                Console.WriteLine(var.name + &quot;年龄是&quot; + var.age);
            }
            list.Sort(MyStudentDefault.Default);
            foreach (MyStudent var in list)
            {
                Console.WriteLine(var.name + &quot;年龄是&quot; + var.age);
            }


            Console.ReadKey();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class SampleCollection&lt;T&gt;
    {
        private T[] arr = new T[100];
        public T this[int i]
        {
            get
            {
                return arr[i];
            }
            set
            {
                arr[i] = value;
            }
        }

        public string Length()
        {
            return   arr.Length.ToString();
            
        }

        public string Count()
        {
            return arr.Count&lt;T&gt;().ToString();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public  class Student: IComparable&lt;Student&gt;
    {
        public string Name { set; get; }
        public int Score { set; get; }
        public int CompareTo(Student obj)
        {
            int result = 0;
            if (this.Score &gt; obj.Score)
                result = 1;
            else if (this.Score == obj.Score)
                result = 0;
            else
                result = -1;
            return result;
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class StudentNameComparer : IComparer
    {
        #region IComparer Members

        public int Compare(object x, object y)
        {
            Student c1 = (Student)x;
            Student c2 = (Student)y;
            return string.Compare(c1.Name, c2.Name);
        }

        #endregion
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2012080201
{
    public class XClass : IComparable 
    {
        public XClass(int data)
        {
            propNumber = data;
        }

        private int propNumber;

        public int Number
        {
            get 
            {
                return propNumber;
            }
        }
        #region IComparable Members

        public int CompareTo(object obj)
        {
            XClass comp = (XClass)obj;
            if (this.Number == comp.Number)
                return 0;
            if (this.Number &lt; comp.Number)
                return -1;
            return 1;
        }

        #endregion
    }
}
IComparable接口要实现CompareTo方法,并且一定要通过值可以排序的类型来实现,例如基本数值类型(整型等),或者字符串,看下面的代码可能易懂一点:
public class Temperature : IComparable
{
protected double temperatureF;

public int CompareTo(object obj) {
if(obj is Temperature)
{
Temperature otherTemperature = (Temperature) obj;
return this.temperatureF.CompareTo(otherTemperature.temperatureF);
}
else
{
throw new ArgumentException("object is not a Temperature");
}
}
}
IComparer接口其实是特定用于Array的Sort和BinarySearch方法以及为SortList提供自定义的排序规则,通过实现IComparer接口的Compare方法以确定Sort如何进行对对象进行排序。
而IComparable中的CompareTo 方法提供了一个默认的排序规则。SorList 只是将Key作为排序对象进行排序。
另外IList<T> 没有排序方法 倒是可以用它存放继承了 IComparable 接口的对象(只支持默认的CompareTo()排序方法)

实现IEnumerable 的类表示其支持迭代其内部对象,也就是在.net中foreach循环,IEnumerable接口只有一个方法GetEnumerator(),其返回一个实现IEnumerator接口的类对象,
IEnumerator有两个方法MoveNext()、Reset()和一个属性Current用于迭代IEnumerator对象中对象集合。
其实把IComparable和Icomparer,IEnumerable和IEnumerator分开为两个接口来定义,是遵从面向对象的思维定向,表示IComparable对象可以比较,IEnumerable对象可以迭代,Icomparer,负责对对象进行比较,IEnumerator负责对对象进行迭代,各司其职罢了。
IEnumerable表明对象是不确定类型的集合并支持简单迭代,是不是定长根本不关心...

IEnumerable<T>表明对象是指定类型的集合并支持简单迭代,是不是定长根本不关心...

ICollection是IEnumerable接口的派生接口,表明对象是不确定类型的集合并支持简单迭代,而且定义了集合的大小、枚举数和同步方法,这里的大小是指可以是定长的也可以是不定长的...

IList是ICollection和IEnumerable的派生接口,表明对象是不确定类型的集合并支持简单迭代,而且定义了集合的大小、枚举数和同步方法,还可以按照索引单独访问,这里的大小是指可以是定长的也可以是不定长的...

ArrayList类是IList接口的实现,表明对象是不确定类型的大小可按需动态增加的数组...

List<T>类是IList<T>接口的实现,是ArrayList类的泛型等效类并增强了功能,表明对象是可通过索引访问的对象的强类型列表...在.NET 2.0以上可以完全代替ArrayList,就是说ArrayList已经被淘汰...

而动态数组和链表在本质上是不同的...在.NET 2.0以上有双向链表LinkedList<T>泛型类,它也是继承自ICollection<T>,IEnumerable<T>,ICollection,IEnumerable...