2015-07-16 16 views
7

Sto facendo an interval collection extension della famosa libreria C# C5. L'interfaccia IInterval definisce un intervallo con endpoint comparabili (membri irrilevanti rimossi):Esiste un'interfaccia in C# per i valori scalari a intervalli?

public interface IInterval<T> where T : IComparable<T> 
{ 
    T Low { get; } 
    T High { get; } 
} 

Questo funziona bene in generale, poiché endpoint intervallo può essere qualsiasi cosa simile come interi, date o addirittura stringhe.

Tuttavia, a volte è opportuno essere in grado di calcolare la durata di un intervallo. L'intervallo [3:5) ha una durata di 2 e l'intervallo [1PM, 9PM) ha una durata di 8 ore. Questo non è possibile con comparabili, dal momento che ci fornisce solo l'ordine degli elementi, non la loro distanza, ad es. è difficile dare la distanza tra due corde. Il tipo di endpoint deve essere fondamentalmente interval-scaled values.

C'è un'interfaccia come IComparable<T>, che mi consente di confrontare gli endpoint in generale, ma anche fare cose come sottrarre due endpoint per ottenere una durata e aggiungere una durata a un endpoint basso per ottenere l'endpoint alto che potrebbe essere utilizzato per un'interfaccia ereditaria, per esempio IDurationInterval<T> : IInterval<T>?

O più conciso: esiste un'interfaccia per valori a intervallo di intervallo?

risposta

4

Nessuna interfaccia esiste. Alcuni linguaggi, come Scala, hanno astrazioni su questi tipi di operazioni, ma .NET non ne ha. Inoltre, ho trovato che i progettisti di librerie .NET sono piuttosto prudenti quando si tratta di aggiungere livelli di astrazione: sembra che tendano a preferire il semplice e il concreto a complessi e astratti. Non hanno mai aggiunto questa astrazione presumibilmente perché non c'è mai stata una necessità urgente in nessuna delle librerie di .NET Framework. Inoltre, è un'astrazione che può causare un sovraccarico se usata in modo improprio.

Tuttavia, nulla nel sistema di tipi di .NET preclude un'interfaccia di questo tipo. Avrebbero bisogno di due parametri di tipo invece di uno: uno per il tipo di implementazione e uno del tipo di risultato. L'interfaccia di base potrebbe essere simile a questo:

interface IAlgebraic<T, R> { 
    T Add(R value) 
    R Subtract(T value) 
} 

Purtroppo, non c'è modo di aggiungere questa interfaccia per i tipi esistenti, come Int32 e DateTime. Per questi tipi, è necessario un corollario allo Comparer<T> .

interface IAlgebraicOps<T, R> { 
    T Add(T x, R y) 
    R Subtract(T x, T y) 
} 
+0

Questa è anche la mia migliore idea finora. Le mie preoccupazioni sono che questo aggiunga troppo di un sovraccarico, ma potrebbe solo avere abbastanza senso farlo. Probabilmente potresti creare un'interfaccia come 'IDurationInterval ' con i metodi 'T Add (differenza R)', 'T Subtract (R difference)' e 'R Difference (T other)'. Questo, tuttavia, ha ancora i suoi lati negativi, poiché non si è ancora in grado di trovare il valore medio di un intervallo. Ma mi piace l'idea generale! –

+0

L'overhead di effettuare una chiamata di metodo virtuale tramite un'interfaccia è grande solo se confrontato con una semplice istruzione add processor che può essere utilizzata per tipi di dati semplici come gli inte. A meno che non ti aspetti di fare milioni di calcoli al secondo, dubito che noterai la differenza. – Nimrand

+0

La menzione del punto medio mostra un altro buon punto. Mentre puoi astrarre operazioni matematiche come addizione e sottrazione, è difficile sapere dove fermarsi. L'interfaccia generica di Scala, Numeric, ha operazioni di confronto, addizione, sottrazione, moltiplicazione, dissolvenza, uno e zero. Int, Long, Float e Double possono supportare tutti questi, ma solo i primi 3 hanno senso per DateTime. In realtà, c'è una gerarchia di interfacce che potrebbero essere fatte. Alla sua base è comparabile. C'è un supporto per l'interfaccia add, sottrarre e operazioni simili. – Nimrand

Problemi correlati