2011-07-01 11 views
5

Sto provando a scrivere classi che gestiscono diversi tipi di numeri. So che C# (e .Net, in generale, credo) non ha alcuna interfaccia INumber, quindi non posso usare qualcosa di simile al seguente:Come posso scrivere una singola classe per compilare più volte con diversi tipi di numeri?

public class Adder<T> where T:INumber 
    { 
     public T Add(T a, T b) 
     { 
      return a + b; 
     } 
    } 

va bene così, però, perché mi piacerebbe evitare la boxe/unboxing di ognuno dei miei numeri. Potrei, tuttavia, utilizzare la compilazione condizionale per ogni tipo Voglio sostenere:

#if FLOAT 
    public class AdderF 
    { 
     public float Add(float a, float b) 
#else 
    public class Adder 
    { 
     public int Add(int a, int b) 
#endif 
     { 
      return a + b; 
     } 
    } 

Ciò significa che avrò bisogno di compilare un diverso Library.dll e LibraryF.dll, tuttavia. C'è una soluzione più elegante a questo?

Ovviamente, nel mio esempio, posso semplicemente scrivere il codice due volte. Vorrei utilizzare questo processo, tuttavia, per creare grandi strutture dati complesse con una versione intera e una versione a virgola mobile, quindi non voglio la possibilità di errori di copia-incolla quando aggiorno la mia struttura. Né voglio che la perdita di velocità avvolga la struttura a virgola mobile in un wrapper integrale e converta inutilmente tutti gli input nel tipo di dati più sfavorevole.

risposta

3

Immagino che dipenda da quanto sia severo lo si voglia. Vuoi un metodo Add che richiede solo due parametri dello stesso tipo esatto (int e int, float e float) ...? In caso contrario, e le prestazioni non sono super-importanti, puoi semplicemente implementare la tua soluzione con decimal e tutto funzionerà.

Se deve essere rigoroso e si desiderano versioni specifiche per tipo, è possibile esaminare la generazione del codice T4. È simile ai modelli di C++ (alcune persone pensano che i modelli C++ e i generici C# siano gli stessi, ma non lo sono).

Scott Hanselman ha scritto an interesting article a riguardo.

+0

Come ho detto, sto cercando di convincere più prestazioni dalle mie strutture dati, e non lo faccio Penso che usare 'decimal's dappertutto quando potrei usare' int's invece sarebbe efficace per quello. T4 è sicuramente una tecnologia interessante di cui non ero a conoscenza e sicuramente la esaminerò! – dlras2

3

Forse questo potrebbe essere utile: Is there a C# generic constraint for "real number" types?.

Sembra che non sia direttamente possibile come hai detto tu. Sarebbe utile averlo.

+0

Grazie! Stavo cercando un collegamento del genere da includere nella mia domanda. So che posso usare calcolatori astratti del genere per lavorare con vari tipi di numeri, ma il mio punto qui è quello di convincere più prestazioni dalle strutture intere quando la precisione in virgola mobile non è necessaria. – dlras2

2

La sfida principale qui è che il jitter deve emettere diversi codici opzionali a seconda che si aggiungano float o int, quindi, anche se il codice sembra simile, in realtà è molto diverso dietro le quinte. Questo è fattibile in C++ (perché i modelli sono compilati separatamente per ogni definizione di tipo), ma i generici .NET funzionano diversamente. Dai uno sguardo a T4 templates come una possibile soluzione (se hai davvero bisogno di compilare come float o int separatamente).

+0

+1 per la spiegazione di modelli C++ rispetto a .Net generici e per il suggerimento T4. – dlras2

+1

In realtà ho sbagliato un po ', in quanto il compilatore poteva, in teoria, supportare un vincolo' numero 'che consentiva l'emissione dell'OppCode Aggiungi IL (anziché provare a risolvere un operatore' add '), con un jype specifico del tipo che gestiva le differenze . Ciò causerebbe comunque alcune limitazioni, in quanto vi è un'istruzione Add.Ovf separata per i numeri interi, quindi è possibile supportare solo l'aggiunta senza il controllo di overflow di interi.Il compilatore avrebbe anche bisogno del supporto di casi speciali per comprendere un "numero primitivo" che non è ancora un tipo specifico, creando divertenti nuovi casi limite per Mr. Lippert. –

Problemi correlati