2010-06-08 11 views
5

In una tupla, se si dispone di più di 7 elementi, è possibile fornire un ottavo elemento che è un'altra tupla e definire fino a 7 elementi, quindi un'altra tupla come ottavo, avanti e indietro lungo la linea. Tuttavia, non vi è alcun vincolo sull'ottavo elemento in fase di compilazione. Ad esempio, questo è il codice legale per il compilatore:Perché TREST in Tupla <T1... TRest> non è vincolato?

var tuple = new Tuple<int, int, int, int, int, int, int, double> 
       (1, 1, 1, 1, 1, 1, 1, 1d); 

Anche se la documentazione intellisense dice che Trest deve essere una tupla. Non si ottiene alcun errore durante la scrittura o la compilazione del codice, non si manifesta fino al runtime sotto forma di ArgumentException.

È possibile implementare una tupla in pochi minuti, completa di un ottavo elemento con vincolo Tupla. Mi chiedo solo perché è stato interrotto dall'attuale implementazione? È forse un problema di compatibilità diretta in cui potrebbero aggiungere più elementi con un ipotetico C# 5?

versione corta del ruvida implementazione

interface IMyTuple { } 

class MyTuple<T1> : IMyTuple 
{ 
    public T1 Item1 { get; private set; } 
    public MyTuple(T1 item1) { Item1 = item1; } 
} 

class MyTuple<T1, T2> : MyTuple<T1> 
{ 
    public T2 Item2 { get; private set; } 
    public MyTuple(T1 item1, T2 item2) : base(item1) { Item2 = item2; } 
} 

class MyTuple<T1, T2, TRest> : MyTuple<T1, T2> where TRest : IMyTuple 
{ 
    public TRest Rest { get; private set; } 
    public MyTuple(T1 item1, T2 item2, TRest rest) 
     : base(item1, item2) 
    { 
     Rest = rest; 
    } 
} 

...

var mytuple = new MyTuple<int, int, MyTuple<int>> 
       (1, 1, new MyTuple<int>(1)); // legal 
var mytuple2 = new MyTuple<int, int, int>(1, 2, 3); // illegal at compile time 
+0

Davvero? Come si potrebbe implementare questo in modo che l'ultimo elemento fosse vincolato ad essere una 'Tupla' di qualsiasi dimensione senza definire una ulteriore classe base o interfaccia che fosse comune tra le varie dimensioni generiche di' Tuple'? Non vedo come pensi che potrebbero farlo in C#. – mquander

+1

@mquander, Tuple implementa ITuple. È possibile definire il proprio tipo di Tupla (MyTuple) che limita l'ultimo elemento a un'interfaccia (IMyTuple) e si ottiene un controllo in fase di compilazione. –

+2

Oh, non sapevo di 'ITuple'. Grazie per la correzione. Prendo atto che 'ITuple' è interno; forse volevano tenerlo interno - se fosse un vincolo qui dovrebbe essere pubblico. – mquander

risposta

1

L'ipotetica ITuple vincolo non sarebbe davvero vincolare ad essere una tupla [1], è vero ? Solo una classe che implementa ITuple.

[1] - Sto definendo "tupla" come una delle classi Tuple<> fornite da BCL.

+0

Questo è un punto interessante. Hai ragione, qualsiasi vecchio tipo potrebbe implementare l'interfaccia (qualunque cosa ciò comporti) e soddisfare i requisiti del vincolo. Ma poi suppongo che porti anche la domanda sul perché limitare il tipo in fase di esecuzione, puoi rilasciare una tupla in uno qualsiasi degli slot esistenti, basta dire "stiamo creando una classe generica a 8 scanalature (max), usala come lo ritieni opportuno. " –

+1

Questo è l'unico modo per vincolarlo veramente a una tupla (controllo in runtime per un'interfaccia 'internal', quindi non possiamo implementarla). L'ultimo slot in realtà deve essere una tupla perché influisce sull'implementazione di 'Size',' GetHashCode', 'ToString', ecc. Viene trattato in modo completamente diverso rispetto agli altri slot. –

7

È una limitazione del sistema di tipi. ITuple è un'interfaccia interna. Se si trattasse di un vincolo generico, dovrebbe essere pubblico, il che consentirebbe a tutti di implementare il proprio ITuple che non potrebbe avere nulla a che fare con le tuple. Limitare l'interno consente al team di BCL di garantire che si tratti di una sorta di tupla, ma i risultati in TRest sono un po 'meno precompilati rispetto a quelli che potrebbero essere.

Problemi correlati