• C#泛型接口


      为泛型集合类或表示集合中项的泛型类定义接口通常很有用。对于泛型类,使用泛型接口十分可取,例如使用 IComparable<T> 而不使用 IComparable,这样可以避免值类型的装箱和取消装箱操作。.NET Framework 2.0 类库定义了若干新的泛型接口,以用于 System.Collections.Generic 命名空间中新的集合类。

    将接口指定为类型参数的约束时,只能使用实现此接口的类型。下面的代码示例显示从 GenericList<T> 类派生的 SortedList<T> 类。SortedList<T> 添加了约束 where T : IComparable<T>。这将使SortedList<T> 中的 BubbleSort 方法能够对列表元素使用泛型 CompareTo 方法。在此示例中,列表元素为简单类,即实现 IComparable<Person> 的 Person

    C#
    //Type parameter T in angle brackets.
    public class GenericList<T> : System.Collections.Generic.IEnumerable<T>
    {
    protected Node head;
    protected Node current = null;

    // Nested class is also generic on T
    protected class Node
    {
    public Node next;
    private T data; //T as private member datatype

    public Node(T t) //T used in non-generic constructor
    {
    next = null;
    data = t;
    }

    public Node Next
    {
    get { return next; }
    set { next = value; }
    }

    public T Data //T as return type of property
    {
    get { return data; }
    set { data = value; }
    }
    }

    public GenericList() //constructor
    {
    head = null;
    }

    public void AddHead(T t) //T as method parameter type
    {
    Node n = new Node(t);
    n.Next = head;
    head = n;
    }

    // Implementation of the iterator
    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
    {
    Node current = head;
    while (current != null)
    {
    yield return current.Data;
    current = current.Next;
    }
    }

    // IEnumerable<T> inherits from IEnumerable, therefore this class
    // must implement both the generic and non-generic versions of
    // GetEnumerator. In most cases, the non-generic method can
    // simply call the generic method.
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
    return GetEnumerator();
    }
    }

    public class SortedList<T> : GenericList<T> where T : System.IComparable<T>
    {
    // A simple, unoptimized sort algorithm that
    // orders list elements from lowest to highest:

    public void BubbleSort()
    {
    if (null == head || null == head.Next)
    {
    return;
    }
    bool swapped;

    do
    {
    Node previous = null;
    Node current = head;
    swapped = false;

    while (current.next != null)
    {
    // Because we need to call this method, the SortedList
    // class is constrained on IEnumerable<T>
    if (current.Data.CompareTo(current.next.Data) > 0)
    {
    Node tmp = current.next;
    current.next = current.next.next;
    tmp.next = current;

    if (previous == null)
    {
    head = tmp;
    }
    else
    {
    previous.next = tmp;
    }
    previous = tmp;
    swapped = true;
    }
    else
    {
    previous = current;
    current = current.next;
    }
    }
    } while (swapped);
    }
    }

    // A simple class that implements IComparable<T> using itself as the
    // type argument. This is a common design pattern in objects that
    // are stored in generic lists.
    public class Person : System.IComparable<Person>
    {
    string name;
    int age;

    public Person(string s, int i)
    {
    name = s;
    age = i;
    }

    // This will cause list elements to be sorted on age values.
    public int CompareTo(Person p)
    {
    return age - p.age;
    }

    public override string ToString()
    {
    return name + ":" + age;
    }

    // Must implement Equals.
    public bool Equals(Person p)
    {
    return (this.age == p.age);
    }
    }

    class Program
    {
    static void Main()
    {
    //Declare and instantiate a new generic SortedList class.
    //Person is the type argument.
    SortedList<Person> list = new SortedList<Person>();

    //Create name and age values to initialize Person objects.
    string[] names = new string[]
    {
    "Franscoise",
    "Bill",
    "Li",
    "Sandra",
    "Gunnar",
    "Alok",
    "Hiroyuki",
    "Maria",
    "Alessandro",
    "Raul"
    };

    int[] ages = new int[] { 45, 19, 28, 23, 18, 9, 108, 72, 30, 35 };

    //Populate the list.
    for (int x = 0; x < 10; x++)
    {
    list.AddHead(new Person(names[x], ages[x]));
    }

    //Print out unsorted list.
    foreach (Person p in list)
    {
    System.Console.WriteLine(p.ToString());
    }
    System.Console.WriteLine("Done with unsorted list");

    //Sort the list.
    list.BubbleSort();

    //Print out sorted list.
    foreach (Person p in list)
    {
    System.Console.WriteLine(p.ToString());
    }
    System.Console.WriteLine("Done with sorted list");
    }
    }

    可将多重接口指定为单个类型上的约束,如下所示:

    C#
    class Stack<T> where T : System.IComparable<T>, IEnumerable<T>
    {
    }

    一个接口可定义多个类型参数,如下所示:

    interface IDictionary<K, V>
    {
    }

    类之间的继承规则同样适用于接口:

    C#
    interface IMonth<T> { }

    interface IJanuary : IMonth<int> { } //No error
    interface IFebruary<T> : IMonth<int> { } //No error
    interface IMarch<T> : IMonth<T> { } //No error
    //interface IApril<T> : IMonth<T, U> {} //Error

    如果泛型接口为逆变的,即仅使用其类型参数作为返回值,则此泛型接口可以从非泛型接口继承。在 .NET Framework 类库中,IEnumerable<T> 从 IEnumerable 继承,因为 IEnumerable<T> 仅在 GetEnumerator 的返回值和当前属性 getter 中使用 T。

    具体类可以实现已关闭的构造接口,如下所示:

    C#
    interface IBaseInterface<T> { }

    class SampleClass : IBaseInterface<string> { }

    只要类参数列表提供了接口必需的所有参数,泛型类便可以实现泛型接口或已关闭的构造接口,如下所示:

    C#
    interface IBaseInterface1<T> { }
    interface IBaseInterface2<T, U> { }

    class SampleClass1<T> : IBaseInterface1<T> { } //No error
    class SampleClass2<T> : IBaseInterface2<T, string> { } //No error

    对于泛型类、泛型结构或泛型接口中的方法,控制方法重载的规则相同。

  • 相关阅读:
    CentOS 6.4 系统下的MySQL的主从库配置
    扫盲: JAVA基本常识
    ant学习
    Linux一些命令
    redis学习
    扫盲:注册表和绿色软件常识
    Java.前端.Layer.open.btn验证无效
    Java.数据结构.集合体系详解
    PageHelper踩坑
    Scrum.站立会议介绍
  • 原文地址:https://www.cnblogs.com/liangxiaofeng/p/5853441.html
Copyright © 2020-2023  润新知