2016-08-05 5 views
0

Ich arbeite an einem C# -Projekt und fand mich selbst versuchen, ein gemeinsames Muster in C++ zu reproduzieren, aber bisher nicht in der Lage. Ein Beispiel dafür, was ich (in C++) zu tun, ich versuche:Äquivalent von C++ 's typedefs/alias Verwendung in Template-Programmierung

enum ProductItemTypes { 
    Product, 
    Family, 
    SubFamily, 
    Department 
}; 

class ProductItem : PanelItem { 
public: 
    using item_type_t = ProductItemTypes; 
    ... 
}; 

enum PaymentItemTypes { 
    Group, 
    Valued, 
    NotValued, 
    Balance 
}; 

class PaymentItem : PanelItem { 
public: 
    using item_type_t = PaymentItemTypes; 
    ... 
}; 

Es gibt verschiedene Klassen, die von PanelItem und haben ihre eigenen item_subtype_t erben. Dann können Klassen, die PanelItem s verwenden, den entsprechenden Elementtyp kennen und generisch arbeiten.

Mit einer ähnlichen Fähigkeit in C# würde mir helfen, viele wiederholte Code zu vermeiden, aber ich möchte nicht alle Typen (ProductItem, ProductItemType, und einige mehr, die ich für die Einfachheit ausgeschlossen habe) übergeben die ganze Zeit.

+1

@Barry, ich habe [tag: C++] hinzugefügt, weil Sie in der Lage sein müssen, diesen Quellcode zu lesen. – Sinatr

+0

Warum nicht: Vorlage Klasse Panel { public: .... }; Dann Panel foo; Schließlich können Sie einen Typ wie oben definieren. – nosbor

+0

@nosbor Yeah, der Panel Teil ist nicht wirklich wichtig, der wichtige Teil ist der 'item_subtype_t' in' ProductItem', da verschiedene 'PanelItem's unterschiedliche Typdefinitionen haben –

Antwort

2

Es ist schwer, genau zu sagen, was hier Ihr Anwendungsfall ist, weil Sie nicht ein Beispiel dafür zur Verfügung gestellt haben:

Dann Klassen, die PanelItems verwenden, wissen den entsprechenden Elementtyp und allgemein arbeiten.

Eine Klasse, die PanelItems direkt verwendet, wäre nicht in der Lage, dies zu tun. Der einzige Weg, um das sein würde, wenn die Klasse eine Template-Klasse ist, die den im direkt nahm (was ich vermute, ist, was Sie wirklich bedeuten geschehen):

template<class T> 
class Foo 
{ 
public: 
    using item_type_t = typename T::item_type_T; 
} 

Sie sind nicht in der Lage sein werden um dies mit C# zu tun. Während syntaktisch Generika und Templates sich sehr ähnlich sehen, handelt es sich um zwei sehr unterschiedliche Biester. C++ - Vorlagen werden einmal für jede von Ihnen vorgenommene Betontypsubstitution kompiliert. Dies ermöglicht auch die Durchführung von SFINAE. Jedes Mal, wenn der Compiler eine Verwendung einer Vorlage sieht, ersetzt er diese in den Typparametern und versucht, die Klasse oder Methode neu zu kompilieren.

Die Generika von C# hingegen sind genau einmal kompiliert und stimmen nicht mit den Typparametern überein. Dies ist der Grund für die Existenz generischer Constraints in C#: Sie können dem Compiler mehr Wissen über die Arten von Typen geben, mit denen er umgehen wird. Es bedeutet auch, dass C# kein SFINAE-Konzept hat, da keine tatsächliche Ersetzung durch den Compiler erfolgt.

Meine Meinung ist, dass Ihr aktueller Ansatz undicht ist. Grundsätzlich sind die verschiedenen item_type_t Typen Implementierungsdetails der abgeleiteten Klassen und Benutzer dieser Klassen müssen wissen, was dieser Typ ist, um mit dem Typ richtig arbeiten zu können. Für mich ist das eine kaputte Kapselung, und C++ bietet nur einen Mechanismus, mit dem Sie diese Undichtigkeit umgehen können, indem Sie das Wissen des Typs vor dem Programmierer verstecken und nur den Compiler brauchen, um ihn wirklich zu kennen.

Ohne weitere Details über genau das, was Sie zu tun versuchen, ist es schwierig, irgendwelche Vorschläge zu alternativen Ansätzen zu geben. Ich bin ziemlich zuversichtlich, dass es ein alternatives Design gibt, das sauber mit Ihrem Problem umgehen wird, aber im Moment ist das ein XY-Problem.

+0

Du haben Recht, und Sie helfen mir zu sehen, dass ich mit meiner gegenwärtigen Idee zu verschlossen war, um sich für eine andere und passendere zu öffnen. Vielen Dank! –

+0

Auch, danke auf den Einblick auf Generika vs Vorlagen! –

+0

@FedericoAllocati Kein Problem, ich arbeite mit vielen Entwicklern von C++ zu C# Entwicklung und die Generika vs. Vorlagen Dinge ist einer der Knackpunkt. Die Entwicklung in C# unterscheidet sich definitiv von C++ und es ist üblich, dass man versuchen möchte, Muster von einem zum anderen zu bringen, aber das ist fast immer ein Fehler (und ist normalerweise nicht möglich, wie hier zu sehen). – Kyle