Qual è il modo migliore per strutturare e denominare i file che contengono classi generiche con lo stesso nome?


14

Nel mio progetto attuale mi sono imbattuto nel requisito di creare classi generiche con lo stesso nome, ma numeri diversi di parametri generici. Per esempio:

MyClass<T1>
MyClass<T1, T2>
MyClass<T1, T2, T3>

Dato che voglio tutto ciò nello stesso spazio dei nomi, sono confuso su come strutturare e denominare le mie classi e i miei file?

Se seguiamo l'idea che dovremmo avere classi limitate a una per file e che i file dovrebbero trovarsi in una struttura di cartelle che rappresenta la gerarchia dello spazio dei nomi e che il nome del file deve corrispondere al nome della classe, come posso gestire questa situazione ?

Quello che sto veramente chiedendo qui è come dovrei nominare il file che contiene MyClass<T1>e come dovrei nominare il file che contiene MyClass<T1, T2>? Non sto chiedendo quali dovrebbero essere i nomi dei parametri di tipo.


Dacci alcuni esempi specifici che descrivono il problema in modo più dettagliato. Gli esempi che hai fornito sono troppo ... erm, generici. Cosa intendi con "come strutturare e nominare le mie classi e i miei file?"
Robert Harvey,

Microsoft lo fa da solo aggiungendo un numero al parametro type. Vedi i documenti Tuple: msdn.microsoft.com/en-us/library/…
Pete

@Pete: Questo vale solo per Tuple. Microsoft utilizza anche la TKey, TValueconvenzione. Func ha un TResultparametro di tipo. Anche se concordo sul fatto che è possibile utilizzare T1, T2ecc. Per un numero variabile di parametri di input che altrimenti non hanno usi specifici come TKeye TValue.
Robert Harvey,

@RobertHarvey Bene, sì, ma solo nel contesto di una vera raccolta chiave / valore come un dizionario. Per tutto ciò che consiste in un numero variabile di tipi, aggiungono un numero. Ecco un altro esempio: msdn.microsoft.com/en-us/library/dd402872(v=vs.110).aspx
Pete

1
Bene, le tue modifiche obsolete alcuni dei commenti. :) Perché non riesci a mantenere le classi nello stesso file fisico? Se sono così diversi che devi tenerli in file separati, puoi dirci cosa li rende diversi?
Pete,

Risposte:


14
MyGenericClass`1.cs
MyGenericClass`2.cs
MyGenericClass`3.cs

E così via, dove il numero dopo il backtick è il numero di parametri di tipo generico. Questa convenzione è utilizzata da Microsoft.

In alternativa, puoi usare qualcosa di simile

MyGenericCollectionClass[TKey, TValue].cs

che conserva non solo il numero di parametri di tipo generico, ma anche i loro nomi specifici. Certo, non conserva le parentesi angolari, ma non possiamo avere tutto nella vita che vogliamo, vero?


1
Il compilatore altera internamente il nome di tipi generici, aggiungendo un backtick e il numero di parametri generici poiché .NET non consente più tipi con lo stesso nome con un numero diverso di parametri generici, ma C # lo fa. Quindi la convenzione di denominazione dei file corrisponde a ciò che fa il compilatore.
Codici A Caos il

1
Volevo dimostrarti che ti sbagli, ma in realtà hai ragione: github.com/dotnet/corefx/tree/master/src/… Non mi piace questa convenzione.
Den,

1
@Den, sembra che ora si siano pentiti di quella convenzione. Forse implicava qualche problema? github.com/dotnet/corefx/commit/…
Sam

@Sam Speriamo non sia un problema di comunicazione tra i team Microsoft. Perché nessun altro lo sta facendo. Inoltre spetta al team del compilatore, non al team delle biblioteche, decidere secondo me.
Den,

Non avrei le palle per usare "` "in un nome di file.
Cristian E.

4

Nel caso di Tuplee Actionche Pete ha menzionato, Microsoft stessa usa un singolo file - vedi Tuple.cs e Action.cs .

Penso che dipenda in parte dal fatto che la funzionalità di tutte le classi sia sostanzialmente la stessa. Personalmente non mi piace raggruppare le classi in un singolo file, ma questa potrebbe essere un'eccezione. Nel codice sorgente in cui lavoro ho aggiunto una NamedTupleclasse generata automaticamente (usando T4) che agisce allo stesso modo Tuple, ma con un nome di stringa come primo argomento nel costruttore.

Per rispondere alla tua domanda, se non vuoi usare un singolo file, forse usa MyClass_1.cs per MyClass<T1>, MyClass_2.cs per MyClass<T1, T2>, ecc.

Nessuna delle due opzioni è l'ideale, quindi sarei propenso a suggerire l'argomento "Microsoft farlo in questo modo, quindi ...".


2
Tuplee Actionsono tutti delegati; non hanno alcun codice di implementazione, quindi mettere tutte le variazioni in file separati sarebbe comunque inutile. Dimostra solo che ogni regola ha un'eccezione.
Robert Harvey,

Sì, in generale, mettere più delegati pubblici nello stesso file è considerato ok (a condizione che siano correlati).
Stephen,

1
@RobertHarvey, Tuplenon è un delegato, ma ogni implementazione è comunque breve.
Arturo Torres Sánchez,

@ ArturoTorresSánchez: giusto, stavo pensando Func.
Robert Harvey,

0

Ti sei chiesto se le lezioni hanno davvero lo stesso intento? Se una classe è più generica dell'altra, allora sarà una GenericClass , una MoreGenericClass e una MostGenericClass . Immagina che ogni parametro di tipo di una classe aggiunga una nuova dimensione alla classe, quindi potrebbe essere utile chiedersi quale dimensione sia.

Facciamo questo esempio:

  • Container<Thing>
  • MetricContainer<Thing, Metric>
  • MetricTransportableContainer<Thing, Metric, Transport>

Sono consapevole che non è l'esempio migliore, ma molto espressivo per mostrare tre dimensioni:

  • Dimensione interna, cosa può caricare
  • dimensione metrica, con quale metrica può essere caricata, solo per conteggio delle cose o per misura quadrata o per capacità cubica o in peso
  • Dimensione esterna, dove può essere caricata.

Quindi puoi modellare il trasporto di auto:

Container<Cars>
MetricContainer<Cars, CountMetric>
MetricTransportableContainer<Cars, CountMetric, Ship>

Trasporto di fluidi:

Container<Fluid>
MetricContainer<Fluid, Volume>
MetricTransportableContainer<Fluid, Volume, Shelf>

Trasporto di energia:

Container<Energy>
MetricContainer<Energy, ElectricPower>
MetricTransportableContainer<Energy, ElectricPower, Box>

Trasporto di zucchero, cereali:

Container<CrumblyMaterial>
MetricContainer<CrumblyMaterial, Weight>
MetricTransportableContainer<CrumblyMaterial, Weight, Silo>

Oh, che sorpresa: a List<T>ha una dimensione che rappresenta le cose che la lista può contenere; e questo è un Map<T, S>con due dimensioni che rappresentano le cose che la mappa può contenere e le chiavi di accesso.


1
Non credo che tu abbia capito la domanda. Guarda l'ultimo paragrafo della domanda.
Robert Harvey,

1
@RobertHarvey Si prega di leggere attentamente la domanda: classname deve essere simile al nome file. È intercambiabile. Il problema sta nell'analisi errata della classe e nella denominazione errata delle classi generiche in generale. Per riassumere la mia risposta: "Chiamalo come è e non come sembra".
shylynx,


1
@RobertHarvey Leggi la mia risposta: metti una classe in un file!
shylynx,

1
Penso che ti stia perdendo il punto. La domanda chiede: come faccio a mettere Tuple<T1>, Tuple<T1, T2>e Tuple<T1, T2, T3>in file separati CS in modo standard, senza nome scontri?
Robert Harvey,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.