• 泛型约束


     

    9.5 约束

    有的时候,您必须确保添加进泛型列表中的元素拥有某些约束(例如,它们从一个给定的基类继承或它们实现了指定的接口)。在下面的例子中,我们实现了一个简单的可排序的单链表。链表由多个Node组成,每个Node必须保证添加进去的元素实现了IComparer接口。您可以这样声明:

    public class Node<T> : IComparable<Node<T>> where T : IComparable<T>

    这句代码定义了一个泛型Node,它操作类型TNode中的T实现了IComparable<T>接口,这意味着两个NodeT可以进行对比。Node类通过约束(where T : IComparable<T>)来操作那些实现了IComparable接口的类型。因此您可以使用任何类型来替代T,只要那种类型实现了IComparable接口

    9-12举例说明了完整的接口实现,并进行分析如下。

    9-12 使用约束


    using System;
    using System.Collections.Generic;

    namespace UsingConstraints
    {
        
    public class Employee : IComparable<Employee>
        {
            
    private string name;
            
    public Employee(string name)
            {
                
    this.name = name;
            }
            
    public override string ToString()
            {
                
    return this.name;
            }
            
    //实现接口
            public int CompareTo(Employee rhs)
            {
                
    return this.name.CompareTo(rhs.name);
            }
            
    public bool Equals(Employee rhs)
            {
                
    return this.name == rhs.name;
            }
        }
        
    //节点必须实现Node<T>的IComparable接口。
        
    //通过where关键字约束Node只接收实现了IComparable接口的项
        public class Node<T> : IComparable<Node<T>> where T : IComparable<T>
        {
            
    //成员变量
            private T data;
            
    private Node<T> next = null//下一个节点
            private Node<T> prev = null//前一个节点
            
    //构造方法
            public Node(T data)
            {
                
    this.data = data;
            }
            
    //属性
            public T Data 
            { 
                
    get { return this.data; } 
            }
            
    public Node<T> Next
            {
                
    get { return this.next; }
            }
            
    public int CompareTo(Node<T> rhs)
            {   
    //这样使用是因为约束
                return data.CompareTo(rhs.data);
            }
            
    public bool Equals(Node<T> rhs)
            {
                
    return this.data.Equals(rhs.data);
            }
            
    //方法
            public Node<T> Add(Node<T> newNode)
            {   
    //下面的“我”代表类的当前实例
                if (this.CompareTo(newNode) > 0//小于我则放在我前面
                {
                    newNode.next 
    = this//新节点的下一节点指向我
                    
    //如果我有前一个节点,则新节点的前一个节点指向它
                    
    //新节点做为它的下一个节点
                    if (this.prev != null)
                    {
                        
    this.prev.next = newNode;
                        newNode.prev 
    = this.prev;
                    }
                    
    //设置我的前一个节点为新节点
                    this.prev = newNode;
                    
    //从下面的LinkedList<T>代码可以得知,添加都是从
                    
    //头节点开始判断,只有新节点为头节点时才返回它
                    return newNode;
                }
                
    else //大于等于我则放在我后面
                {
                    
    //如果我有下一个,则跟下一个进行对比
                    
    //这里使用了递归,直到新节点找到比它大的节点为止
                    if (this.next != null)
                    {
                        
    this.next.Add(newNode);
                    }
                    
    //如果我没有下一个节点,则设置新节点为我的下一个
                    
    //节点,并把它的上一个节点指向我
                    else
                    {
                        
    this.next = newNode;
                        newNode.prev 
    = this;
                    }
                    
    return this;
                }
            }
            
    public override string ToString()
            {
                
    string output = data.ToString();
                
    if (next != null)
                {   
    //这里也使用了递归打印链表上的所有元素
                    output += "" + next.ToString();
                }
                
    return output;
            }
        }
        
    public class LinkedList<T> where T : IComparable<T>
        {
            
    //成员变量
            private Node<T> headNode = null;
            
    //索引器
            public T this[int index]
            {
                
    get
                {   
    //由于是链表,这里需要从头遍历
                    int ctr = 0;
                    Node
    <T> node = headNode;
                    
    while (node != null && ctr <= index)
                    {
                        
    if (ctr == index)
                        {
                            
    return node.Data;
                        }
                        
    else
                        {
                            node 
    = node.Next;
                        }
                        
    ++ctr;
                    }
                    
    throw new ArgumentOutOfRangeException();
                }
            }
            
    //默认构造方法
            public LinkedList()
            {
            }
            
    //方法
            public void Add(T data)
            {
                
    if (headNode == null)
                {
                    headNode 
    = new Node<T>(data);
                }
                
    else
                {
                    headNode 
    = headNode.Add(new Node<T>(data));
                }
            }
            
    public override string ToString()
            {
                
    if (this.headNode != null)
                {
                    
    return this.headNode.ToString();
                }
                
    else
                {
                    
    return string.Empty;
                }
            }
        }
        
    //测试类
        class Test
        {
            
    static void Main()
            {   
    //创建一个实例来进行方法
                Test t = new Test();
                t.Run();
            }
            
    public void Run()
            {
                LinkedList
    <int> myLinkedList = new LinkedList<int>();
                Random rand 
    = new Random();
                Console.Write(
    "Adding: ");
                
    for (int i = 0; i < 10; i++)
                {
                    
    int nextInt = rand.Next(10);
                    Console.Write(
    "{0} ", nextInt);
                    myLinkedList.Add(nextInt);
                }

                LinkedList
    <Employee> employees = new LinkedList<Employee>();
                employees.Add(
    new Employee("John"));
                employees.Add(
    new Employee("Paul"));
                employees.Add(
    new Employee("George"));
                employees.Add(
    new Employee("Ringo"));

                Console.WriteLine(
    "\nRetrieving collections");
                Console.WriteLine(
    "Integers: " + myLinkedList);
                Console.WriteLine(
    "Employees: " + employees);
            }
        }
    }

     

    运行结果:

    Adding2 1 2 6 1 5 9 0 5

    Retrieving collections…

    Integers0,1,1,1,2,2,5,5,6,9

    EmployeesGeorge, John, Paul, Ringo

    本例的开头声明了一个可以放到链表中的类:

    public class Employee : IComparable<Employee>

    这个声明指出Employee对象是可以进行对比的,可以看到Employee类实现了CompareToEquals方法。注意:这些方法是类型安全的(从参数传递进去的类是Employee类型)。LinkedList本身声明为只操作实现了IComparable接口的类型:

    public class LinkedList<T> where T : IComparable<T>

    这样就可以保证对列表进行排序。LinkedList操作Node类型的对象。Node也实现了IComparable接口,并要求它本身所操作的数据也实现了IComparable接口:

    public class Node<T> : IComparable<Node<T>> where T : IComparable<T>

    这些约束使得Node实现CompareTo方法变得安全而简单,因为Node知道它将和其它Node的数据进行对比:

    public int CompareTo(Node<T> rhs)

    {

        // 这样使用是因为约束

        return data.CompareTo(rhs.data);

    }

    注意,我们不需要测试rhs从而得知它是否实现了IComparable接口;我们已经约束了Node只能操作实现了IComparable接口的数据。
  • 相关阅读:
    bzoj3033: 太鼓达人
    CH Round #24
    王志明:编辑部不送审,把你的投稿直接拒掉了,怎么办?
    用TinyXml做XML解析示例 TinyXml查找唯一节点及修改节点操作
    QT XML文档的解析 QXmlStreamReader, DOM,SAX 三种解析方法 简单示例
    QT 使用QUdpSocket QUdpServer UDP 建立客户端与服务器端
    QT 使用QTcpServer QTcpSocket 建立TCP服务器端 和 客户端
    Qt QThread 线程创建,线程同步,线程通信 实例
    Qt QT的IO流 QT输入输出
    Qt QSortFilterProxyModel示例代码, 使用方法
  • 原文地址:https://www.cnblogs.com/abatei/p/1066216.html
Copyright © 2020-2023  润新知