2011-10-27 4 views
0

Microsoft donne comme exemple de tri des bulles pour l'apprentissage des génériques. Cela a du sens jusqu'à ce que j'arrive aux lignes 76 et 77. Comment ces déclarations sont-elles possibles? Le noeud est une classe. Ne devez-vous pas l'instancier avec du nouveau? Comment optimiseriez-vous le tri? Quelle partie est générique et qui est non générique?Generics Déclaration de noeud

1 public class GenericList<T> : System.Collections.Generic.IEnumerable<T> 
2  { 
3   protected Node head; 
4   protected Node current = null; 
5 
6   // Nested class is also generic on T 
7   protected class Node 
8   { 
9    public Node next; 
10    private T data; //T as private member datatype 
11 
12    public Node(T t) //T used in non-generic constructor 
13    { 
14     next = null; 
15     data = t; 
16    } 
17 
18    public Node Next 
19    { 
20     get { return next; } 
21     set { next = value; } 
22    } 
23 
24    public T Data //T as return type of property 
25    { 
26     get { return data; } 
27     set { data = value; } 
28    } 
29   } 
30 
31   public GenericList() //constructor 
32   { 
33    head = null; 
34   } 
35 
36   public void AddHead(T t) //T as method parameter type 
37   { 
38    Node n = new Node(t); 
39    n.Next = head; 
40    head = n; 
41   } 
42 
43   // Implementation of the iterator 
44   public System.Collections.Generic.IEnumerator<T> GetEnumerator() 
45   { 
46    Node current = head; 
47    while (current != null) 
48    { 
49     yield return current.Data; 
50     current = current.Next; 
51     
52    } 
53   } 
54 
55   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
56   { 
57    return GetEnumerator(); 
58   } 
59  } 
60 
61  public class SortedList<T> : GenericList<T> where T : System.IComparable<T> 
62  { 
63   // A simple, unoptimized sort algorithm that 
64   // orders list elements from lowest to highest: 
65 
66   public void BubbleSort() 
67   { 
68    if (null == head || null == head.Next) 
69    { 
70     return; 
71    } 
72    bool swapped; 
73 
74    do 
75    { 
76     Node previous = null; 
77     Node current = head; 
78 
79     
80     //Console.WriteLine(previous.GetType()); 
81     //Console.ReadLine(); 
82 
83     swapped = false; 
84     
85     
86     //Debug.WriteLine(p); 
87     //Debug.WriteLine("Testing " + current.ToString()); 
88 
89     while (current.next != null) 
90     { 
91      // Because we need to call this method, the SortedList 
92      // class is constrained on IEnumerable<T> 
93      if (current.Data.CompareTo(current.next.Data) > 0) 
94      { 
95       Node tmp = current.next; 
96       current.next = current.next.next; 
97       tmp.next = current; 
98 
99       if (previous == null) 
100       { 
101        head = tmp; 
102       } 
103       else 
104       { 
105        previous.next = tmp; 
106       } 
107       previous = tmp; 
108       swapped = true; 
109      } 
110      else 
111      { 
112       previous = current; 
113       current = current.next; 
114      } 
115     } 
116    } while (swapped); 
117   } 
118  } 

Répondre

0

Nous assignons previous et next à null et head respectivement. C'est une opération d'assignation, comme n'importe quelle autre. Vous n'avez pas besoin d'utiliser new sauf si vous créez réellement une nouvelle instance de l'objet.

Les parties génériques sont tout ce qui se réfère à T. C'est un type générique fourni lorsque la classe est instanciée. Un bon exemple est List<T>, qui crée une liste d'objets de type T. Vous pourriez par exemple ce que List<string> pour une liste de chaînes, List<int> pour une liste des ints, etc.

2

Un type class en C# peut être initialisé avec null ou une valeur qui est d'un type compatible avec la déclaration. Les lignes 76 et 77 ressemblent donc

Node previous = null; 
Node current = head; 

Ici la valeur null est légale. Il dit essentiellement "Je n'ai aucune valeur". L'affectation à head est également légale car head est également de type Node. Le résultat est les deux références head et current se réfèrent à la même valeur d'objet Node. La modification de l'instance Node via l'une des références sera visible par l'autre.

0

Ce sont références qui pourraient pointer vers cas d'une classe ou peut être juste null.

Vous pouvez attribuer des références à d'autres références:

Foo f1 = new Foo(); 
Foo f2 = f1; 
Foo f3 = null; 
0

Aucun objets sont instanciés sur les lignes 76 et 77 dans ce code. Comme vous l'avez dit, Node est une classe. Classes .NET sont toujours référence types qui signifie que:

  1. La valeur d'une variable d'un type de référence est une référence à un objet (ou rien).
  2. Les variables d'un type de référence peuvent recevoir la valeur null, ce qui signifie que la variable ne fait référence à rien.
  3. L'affectation d'une variable d'un type de référence à une autre variable d'un type de référence copie la référence, pas l'objet.