2012-11-23 27 views
9

Sono un neofita dei generici e sto avendo qualche problema nell'implementare un piccolo codice di auto-pratica.Come faccio a trasmettere un valore int a un parametro di tipo generico equivalente come char?

Sto creando un elenco collegato. Voglio che memorizzi i valori char o int. Così ho deciso di fare l'implementazione generica:

public class Node<T> where T : struct, IConvertible 
{ 
    public Node<T> next = null; 
    public T data = default(T); 

    public Node(T value) { this.data = value; } 
} 

Ho un metodo che crea la lista collegata, generando valori casuali nell'intervallo [33.127), convertendo il valore del tipo specificato dal T (per esempio, se 86 è generato e T è Char, quindi il valore da memorizzare nel nodo dell'elenco collegato sarà 'V'; Se T è Int32, il valore sarà semplicemente 86). Sono di fronte a due problemi:

static Node<IConvertible> CreateList<T>(int len) where T : struct, IConvertible 
    { 
     Random r = new Random((int)DateTime.Now.Ticks); 
     T value = (T)r.Next(33, 127);  // Problem #1 

     Node<T> head = new Node<T>(value); 
     Node<T> n = head; 

     for (int i = 1; i < len; i++) 
     { 
      n.next = new Node<T>(value); 
      n = n.next; 
     } 
     return head; // Problem #2 
    } 

Questi sono i problemi:

1) Normalmente ciò è possibile: (int) Valore = (char) r.Next (33, 127). Perché se T è di tipo Char, il compilatore dice "Impossibile convertire il tipo 'int' in 'T'", anche se avessi specificato "dove T: struct, IConvertible"?

2) "Impossibile implicitamente tipo convertire 'LinkedList.Node<T>' a 'LinkedList.Node<System.IConvertible>'" Se T è uno Int32 o Char e ciascuno di essi implementare IConvertible, qual è il modo per lanciare Node<Int32> o Node<Char>-Node<IConvertible>?

Grazie mille!

risposta

1

Usa

T value = (T)Convert.ChangeType(r.Next(33, 127), typeof(T)); 
2

L'utilizzo del Random per generare alcuni dati è una sorta di in contrasto con l'utilizzo di farmaci generici. Vorrei separare le due cose in questo modo:

static Node<T> CreateList<T>(int len, Func<T> dataProvider) where T : struct, IConvertible 
{ 
    Node<T> head = new Node<T>(dataProvider()); 
    Node<T> n = head; 

    for (int i = 1; i < len; i++) 
    { 
     n.next = new Node<T>(dataProvider()); 
     n = n.next; 
    } 
    return head; 
} 

codice chiamando:

Random r = new Random(); 
Node<char> list = CreateList(10,() => (char)r.Next(33, 127)); 

La seconda questione è Node<IConvertible> non è consentito dalla vostra struct vincolo Node<T>. Basta restituire un Node<T>. Anche se si rimuove il vincolo struct da Node<T>, non sarebbe possibile restituire un Node<IConvertible> perché le classi generiche non supportano la varianza.

6

Il problema è che T potrebbe essere una qualsiasi struttura, ad es. Guid, SByte ... o custom-new-one. e mentre possiamo essere sicuri che T è struct e IConvertible, ci non deve essere operatore di cast esplicito

public static explicit operator AnyStruct(int i) 

La seconda questione scacciando Node<System.IConvertible>-Node<System.IConvertible> è usuale. Qualsiasi lista List<T> non può essere convertita in List<System.IConvertible>.

Ciò di cui abbiamo bisogno è la dichiarazione di covarianza sull'interfaccia: INode<out T>. Quindi il INode<T> potrebbe essere convertito in INode<System.IConvertible>

Problemi correlati