2010-07-15 7 views
14

So in C++, ich bin zu der Möglichkeit, zu tun pflegen:Wie alias ein eingebauter Typ in C#?

typedef int PeerId; 

Dies erlaubt mir, eine Art selbsterklärend zu machen, sondern zusätzlich kann auch mir peerID repräsentiert eine andere Art jederzeit machen ohne den gesamten Code zu ändern. Ich könnte PeerId sogar in eine Klasse verwandeln, wenn ich wollte. Diese Art von Erweiterbarkeit ist, was ich in C# haben möchte, aber ich habe Probleme herauszufinden, wie man einen Alias ​​für 'int' in C# erstellen.

Ich denke, ich kann die using-Anweisung verwenden, aber es hat nur Umfang in der aktuellen Datei glaube ich, so dass es nicht funktioniert (Der Alias ​​muss zwischen mehreren Dateien zugegriffen werden, ohne neu definiert werden). Ich kann auch keine Klasse von eingebauten Typen ableiten (aber normalerweise würde ich das tun, um ref-types wie List oder Dictionary zu aliasieren). Ich bin mir nicht sicher, was ich tun kann. Irgendwelche Ideen?

+0

Warum können Sie nicht von integrierten Typen ableiten? – arootbeer

+1

Ich bin nur neugierig? Was wäre eine Situation oder ein Grund, warum jemand das tun möchte? Tut mir leid, wenn das komisch klingt, ich weiß nur nicht warum du Int nicht benutzen willst. Es klingt, als wäre es für einen anderen Entwickler verwirrend, Ihren Code zu lesen. –

+0

Zustimmen, interessiert, dies zu lesen, aber es muss schlechte Praxis sein –

Antwort

6

Sie könnten (ab) verwenden implizite Konvertierungen:

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; 
    } 
} 

Dies hat den gleichen Raum wie ein int nimmt, und Sie können do:

PeerId p = 3; 
int i = p; 

Aber ich stimme zu, dass Sie wahrscheinlich nicht brauchen.

+0

Ich tue dies manchmal für etwas komplexere Werttypen, aber ich würde dies nicht tun, nur um einen Namen zu haben. – ChaosPandion

16

benötigen Sie den vollständigen Typnamen wie folgt zu verwenden:

using DWORD = System.Int32; 
+12

Diese Lösung behandelt diesen Teil seiner Frage nicht: 'Ich denke, ich kann die using-Anweisung verwenden, aber es hat nur Gültigkeitsbereich in der aktuellen Datei, so dass es nicht funktioniert (Der Alias ​​muss zwischen mehreren zugänglich sein Dateien ohne Neudefinition) ' –

11

Zusammenfassung

Hier ist die kurze Antwort:

  • Typedefs sind eigentlich eine Variable, die durch Kompilierung-Code-Generatoren verwendet.
  • C# wurde entwickelt, um das Hinzufügen von Codegenerierungssprachenkonstrukten zu vermeiden.

Daher passt das Konzept von typedefs nicht gut mit der C# -Sprache.

Lange Antwort

In C++, macht es mehr Sinn: C++ als Precompilers begann, die C-Code ausspucken, die dann kompiliert wurde. Dieser "Code-Generator" -Anfang hat immer noch Auswirkungen auf moderne C++ - Funktionen (d. H. Vorlagen sind im Wesentlichen eine Turing-vollständige Sprache zum Erzeugen von Klassen und Funktionen zur Kompilierungszeit). In diesem Kontext ist ein typedef sinnvoll, weil es eine Möglichkeit ist, das "Ergebnis" einer Kompilierzeit-Typfactory oder eines "Algorithmus" zu erhalten, der einen Typ "zurückgibt".

In dieser seltsamen Meta-Sprache (die wenige außerhalb von Boost beherrschen), ist ein typedef eigentlich eine Variable.

Was Sie beschreiben, ist weniger komplex, aber Sie versuchen immer noch, das Typedef als Variable zu verwenden. In diesem Fall wird es als Eingabevariable verwendet. Wenn also anderer Code typedef verwendet, wird dieser Typ nicht direkt verwendet. Es agiert vielmehr als Kompilierzeit-Codegenerator, der Klassen und Methoden basierend auf typdefinierten Eingabevariablen erstellt. Selbst wenn Sie C++ - Vorlagen ignorieren und sich nur C-Typdefinitionen ansehen, ist der Effekt derselbe.

C++ und generatives Programmieren

C++ entwickelt wurde eine Multi-Paradign Sprache (OO und verfahrenstechnischen, aber nicht funktionsfähig, bis Boost-herauskam). Interessanterweise haben Vorlagen ein unerwartetes Paradigma entwickelt: generative Programmierung. (Generative Programmierung war vor C++, aber C++ machte es populär). Generative Programme sind eigentlich Meta-Programme, die - wenn sie kompiliert werden - die benötigten Klassen und Methoden generieren, die wiederum zu ausführbaren Dateien kompiliert werden.

C# und Generative Programmierung

Unsere Werkzeuge entwickeln sich langsam in die gleiche Richtung. Natürlich kann die Reflexion emittiert werden für "manuelle" generative Programmierung, aber es ist ziemlich schmerzhaft. Die Art und Weise, wie LINQ-Anbieter Expressionsbäume verwenden, ist sehr generativer Natur. T4-Vorlagen werden sehr nah, aber immer noch knapp. Der "Compiler als Dienst", der hoffentlich Teil von C# vNext sein wird, erscheint am vielversprechendsten, wenn er mit einer Art von Typvariablen (wie typedef) kombiniert werden könnte.

Dieses Stück des Puzzles ist still missing: generative Programme eine Art von automatischem Auslösemechanismus benötigen (in C++, dies durch implizite template Instanziierung gehandhabt wird).

Es ist jedoch ausdrücklich nicht ein Ziel von C#, jede Art von „Code-Generator“ zu haben, in der C# Sprache wie C++ Vorlagen (wahrscheinlich aus Gründen der Verständlichkeit, sehr wenige C++ Programmierer verstehen C++ Vorlagen). Dies wird wahrscheinlich eine Nische sein, die von T4 und nicht von C# befriedigt wird.

Schlussfolgerung (Wiederholung der Zusammenfassung)

Alle der oben genannten ist folgendes zu sagen:

  • Typedefs sind eine Variable von Codegeneratoren verwendet.
  • C# wurde entwickelt, um das Hinzufügen von Codegenerierungssprachenkonstrukten zu vermeiden.

Daher passt das Konzept von typedefs nicht gut mit der C# -Sprache.

+3

Sehr informative Antwort, aber es enthält keine Informationen, die ich nicht bereits kannte, noch beantwortet es meine ursprüngliche Frage tatsächlich. Ich habe nur typedefs erwähnt, um jedem ein Beispiel zu geben, was ich denke/erwarte. Aliase müssen nicht notwendigerweise kompiliert werden und können viele Formen annehmen, wie zum Beispiel die Ableitung. Wenn ich dies tun könnte: "public class PeerId: int {}", würde das ausreichen und mein Problem perfekt lösen. –

+0

Auch +1 für interessante und nützliche Informationen –

1

Grundlegende Typen neu zu definieren, nur um den Namen zu ändern, ist C++ gedacht und passt nicht gut zu dem reineren Objektorientierten C#. Wann immer Sie den Drang verspüren, ein Konzept von einer Sprache in eine andere zu schüren, müssen Sie aufhören und darüber nachdenken, ob es sinnvoll ist und versuchen, auf der Plattform nativ zu bleiben.

Die Anforderung, den zugrunde liegenden Typ einfach ändern zu können, kann durch die Definition eines eigenen Wertetyps erfüllt werden. In Verbindung mit impliziten Konvertierungsoperatoren und arithmetischen Operatoren können Sie sehr leistungsfähige Typen definieren. Wenn Sie über die Leistung zum Hinzufügen von Ebenen auf einfache Typen besorgt sind, tun Sie dies nicht. 99% Chance, dass es nicht, und die 1% Chance ist, dass, falls es tut, wird es nicht sein "niedrig hängenden Früchte" der Leistungsoptimierung.

3

Ich habe auch manchmal das Gefühl, ich brauche (integer) typedefs für ähnliche Zwecke mit dem OP.

Wenn Sie die Modelle sind explizit nichts ausmacht (ich will, dass sie tatsächlich sein), dies tun:

enum PeerId : int {};

funktioniert auch für byte, sbyte, short, ushort, uint, long, oder ulong (offensichtlich).

Nicht genau die beabsichtigte Verwendung von enum, aber es funktioniert.