2010-07-15 12 views
14

Quindi, in C++, io sono abituato ad essere in grado di fare:Come alias di un tipo predefinito in C#?

typedef int PeerId; 

Questo mi permette di fare un tipo più auto-documentazione, ma in più permette anche a me di fare peerID rappresentano un tipo diverso in qualsiasi momento senza cambiare tutto il codice. Potrei persino trasformare PeerId in una classe se volessi. Questo tipo di estensibilità è ciò che voglio avere in C#, tuttavia ho difficoltà a capire come creare un alias per "int" in C#.

Penso di poter usare l'istruzione using, ma nel file corrente ho solo uno scope, quindi non funzionerà (l'alias deve essere accessibile tra più file senza essere ridefinito). Non riesco nemmeno a ricavare una classe dai tipi built-in (ma normalmente questo è ciò che farei per gli alias ref-types, come List o Dictionary). Non sono sicuro di cosa posso fare. Qualche idea?

+0

Perché non è possibile derivare dai tipi predefiniti? – arootbeer

+1

Sono solo curioso? Quale sarebbe una situazione o una ragione qualcuno vorrebbe fare questo? Scusa se questo suona strano, sono solo ignorante sul motivo per cui non vorrai usare int. Sembra che sarebbe confuso per un altro sviluppatore leggere il tuo codice. –

+0

D'accordo, interessato a leggere questo, ma deve essere una cattiva pratica –

risposta

6

Si potrebbe (ab) usare le conversioni implicite:

struct PeerId 
{ 
    private int peer; 

    public static implicit operator PeerId(int i) 
    { 
     return new PeerId {peer=i}; 
    } 

    public static implicit operator int(PeerId p) 
    { 
     return p.peer; 
    } 
} 

Questo prende lo stesso spazio di un int, ed è possibile do:

PeerId p = 3; 
int i = p; 

Ma sono d'accordo che probabilmente non ne hai bisogno.

+0

A volte lo faccio per tipi di valori leggermente più complessi ma non lo farei solo per avere un nome. – ChaosPandion

16

È necessario utilizzare il nome di tipo completo come questo:

using DWORD = System.Int32; 
+12

Questa soluzione non gestisce questa parte della sua domanda: 'Penso di poter usare l'istruzione using, ma ha solo scope nel file corrente, credo, quindi non funzionerà (l'alias deve essere accessibile tra più file senza essere ridefinito) ' –

11

Sommario

Ecco la risposta breve:

  • typedef sono in realtà una variabile utilizzata dai generatori di codice in fase di compilazione.
  • C# è stato progettato per evitare l'aggiunta di costrutti del linguaggio di generazione del codice.

Pertanto, il concetto di typedef non si adatta bene al linguaggio C#.

risposta Lunghi

In C++, ha più senso: C++ iniziato come un pre-compilatore che sputare codice C, che è stato poi compilato. Questo principio di "generatore di codice" ha ancora effetti nelle moderne caratteristiche del C++ (cioè i template sono essenzialmente un linguaggio completo di Turing per generare classi e funzioni in fase di compilazione). In questo contesto, un typedef ha senso perché è un modo per ottenere il "risultato" di una fabbrica di tipo in fase di compilazione o "algoritmo" che "restituisce" un tipo.

In questo strano meta-linguaggio (che pochi al di fuori di Boost hanno imparato), un typedef è in realtà una variabile.

Quello che stai descrivendo è meno complesso, ma stai ancora cercando di usare il typedef come variabile. In questo caso, viene utilizzato come variabile di input. Quindi, quando un altro codice usa typedef, non usa realmente quel tipo direttamente. Piuttosto, agisce come un generatore di codice in fase di compilazione, costruendo classi e metodi basati su variabili di input tipizzate. Anche se si ignorano i modelli C++ e si guardano solo i typedef, l'effetto è lo stesso.

C++ e generativa Programmazione

C++ è stato progettato per essere un linguaggio multi-paradign (OO e procedurale, ma non funzionale fino Boost è uscito). È interessante notare che i modelli hanno evoluto un paradigma inaspettato: la programmazione generativa. (La programmazione generativa era prima del C++, ma il C++ lo rendeva popolare). I programmi generativi sono in realtà meta-programmi che, una volta compilati, generano le classi e i metodi necessari, che sono a loro volta compilati in file eseguibili.

C# e generativa Programmazione

I nostri strumenti sono lentamente evolvendo nella stessa direzione. Naturalmente, la riflessione emessa può essere utilizzata per la programmazione generativa "manuale", ma è piuttosto dolorosa. Il modo in cui i provider LINQ usano gli alberi di espressione è di natura molto generativa. I modelli T4 si avvicinano molto ma non riescono ancora. Il "compilatore come servizio" che si spera faccia parte di C# vNext sembra molto promettente, se potesse essere combinato con un tipo di variabile di tipo (come un typedef).

Questo pezzo del puzzle è still missing: programmi generativi hanno bisogno di un qualche tipo di meccanismo automatico di riferimento (in C++, questo viene gestito da implicito modello di istanza).

Tuttavia, non è esplicitamente non un obiettivo di C# per avere qualsiasi tipo di "generatore di codice" nel linguaggio C# come i template C++ (probabilmente per il bene della comprensibilità; pochissimi programmatori C++ capiscono C modelli ++). Questa sarà probabilmente una nicchia soddisfatta da T4 piuttosto che da C#.

Conclusione (ripetendo la sintesi)

Tutto quanto sopra è dire questo:

  • typedef sono una variabile utilizzata dai generatori di codice.
  • C# è stato progettato per evitare l'aggiunta di costrutti del linguaggio di generazione del codice.

Pertanto, il concetto di typedef non si adatta bene al linguaggio C#.

+3

Risposta estremamente informativa, tuttavia non comporta alcuna informazione che non conoscevo già, né risponde effettivamente alla mia domanda iniziale. Stavo semplicemente citando typedef per dare a tutti un esempio di ciò che sto pensando/aspettandomi. Gli alias non devono necessariamente essere compilati e possono assumere molte forme, come la derivazione. Se potessi fare questo: "public class PeerId: int {}", che sarebbe sufficiente e risolvere perfettamente il mio problema. –

+0

Inoltre +1 alla risposta per informazioni interessanti e utili –

1

La ridefinizione dei tipi fondamentali per il solo scopo di modificare il nome è C++ che non si adatta bene al C# più puro orientato agli oggetti. Ogni volta che ti viene voglia di calzare un concetto da una lingua all'altra, devi fermarti e pensare se abbia o meno senso e cercare di rimanere nativo alla piattaforma.

Il requisito di poter modificare facilmente il tipo sottostante può essere soddisfatto definendo il proprio tipo di valore. Insieme agli operatori impliciti di conversione e agli operatori aritmetici, hai il potere di definire tipi molto potenti. Se sei preoccupato delle prestazioni per l'aggiunta di livelli sopra a tipi semplici, non farlo. Il 99% di probabilità che non lo faccia, e la possibilità dell'1% è che, in caso affermativo, non sarà il "basso appeso frutto" dell'ottimizzazione delle prestazioni.

3

A volte mi sembra di aver bisogno (integer) di typedef per scopi simili all'OP.

Se non ti dispiace i calchi essere esplicita (Io in realtà voglio che siano) si può fare questo:

enum PeerId : int {};

funzionerà anche per byte, sbyte, short, ushort, uint, long, o ulong (ovviamente).

Non esattamente l'utilizzo previsto di enum, ma funziona.

Problemi correlati