Jak najlepiej ustrukturyzować i nazwać pliki zawierające klasy ogólne o tej samej nazwie?

14

W moim obecnym projekcie spotkałem się z wymogiem tworzenia klas ogólnych o tej samej nazwie, ale o różnej liczbie parametrów ogólnych. Na przykład:

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

Biorąc pod uwagę, że chcę je wszystkie w tej samej przestrzeni nazw, nie jestem pewien, jak ustrukturyzować i nazwać moje klasy i pliki?

Jeśli podążamy za ideą, że powinniśmy mieć klasy ograniczone do jednej na plik, a pliki powinny mieć strukturę folderów reprezentującą hierarchię przestrzeni nazw i że nazwa pliku powinna pasować do nazwy klasy, jak poradzić sobie z tą sytuacją ?

Naprawdę pytam o to, jak powinienem nazwać plik zawierający MyClass<T1>i co powinienem nazwać plik zawierający MyClass<T1, T2>? Nie pytam, jakie powinny być nazwy parametrów typu.

Stephen
źródło
Podaj nam konkretne przykłady, które bardziej szczegółowo opisują problem. Podane przykłady są zbyt ... eee, ogólne. Co rozumiesz przez „jak ustrukturyzować i nazwać moje klasy i pliki?”
Robert Harvey
Microsoft robi to samo, dodając liczbę do parametru type. Zobacz dokumentację Tuple: msdn.microsoft.com/en-us/library/…
Pete
@ Pet: To naprawdę dotyczy tylko Tuple. Microsoft stosuje również TKey, TValuekonwencję. Func ma TResultparametr typu. Choć zgadzam się, że można użyć T1, T2itp dla zmiennej liczby parametrów wejściowych, które inaczej nie mają szczególnych zastosowań jak TKeyi TValue.
Robert Harvey
@RobertHarvey Cóż, tak, ale tylko w kontekście rzeczywistej kolekcji kluczy / wartości, takiej jak słownik. Do czegokolwiek składającego się ze zmiennej liczby typów dołączają liczbę. Oto inny przykład: msdn.microsoft.com/en-us/library/dd402872(v=vs.110).aspx
Pete
1
Cóż, wasze modyfikacje zdezaktualizowały niektóre komentarze. :) Dlaczego nie możesz po prostu trzymać klas w tym samym fizycznym pliku? Jeśli są tak różne, że musisz je przechowywać w osobnych plikach, to czy możesz nam powiedzieć, co je wyróżnia?
Pete,

Odpowiedzi:

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

I tak dalej, gdzie liczba po znaku wstecz jest liczbą parametrów typu ogólnego. Ta konwencja jest używana przez Microsoft.

Alternatywnie możesz użyć czegoś takiego

MyGenericCollectionClass[TKey, TValue].cs

która zachowuje nie tylko liczbę ogólnych parametrów typu, ale także ich specyficzne nazwy. To prawda, że ​​nie zachowuje nawiasów kątowych, ale nie możemy mieć wszystkiego w życiu, czego chcemy, prawda?

Robert Harvey
źródło
1
Kompilator wewnętrznie zmienia nazwę typów ogólnych, dodając znak wsteczny i liczbę parametrów ogólnych, ponieważ .NET nie zezwala na wiele typów o tej samej nazwie z różną liczbą ogólnych parametrów, ale C # robi. Konwencja nazewnictwa plików jest zgodna z tym, co robi kompilator.
CodesInChaos
1
Chciałem udowodnić, że się mylisz, ale tak naprawdę masz rację: github.com/dotnet/corefx/tree/master/src/ ... Nie lubię tej konwencji.
Den
1
@Den wydaje się, że teraz żałują tej konwencji. Może to sugerowało jakiś problem? github.com/dotnet/corefx/commit/…
Sam
@Sam Mam nadzieję, że nie ma problemu z komunikacją między zespołami Microsoft. Ponieważ nikt inny tego nie robi. Moim zdaniem to zależy od zespołu kompilatorów, a nie od zespołu bibliotek.
Den
Nie miałbym piłek do używania „” w nazwie pliku.
Cristian E.
4

W przypadku Tuplei Actionże Pete wspomniał, Microsoft sami użyć pojedynczego pliku - patrz Tuple.cs i Action.cs .

Myślę, że częściowo zależy to od tego, czy funkcjonalność wszystkich klas jest zasadniczo taka sama. Osobiście nie lubię grupować klas w jeden plik, ale może to być wyjątek. W kodzie źródłowym, w którym pracuję, dodałem automatycznie generowaną (za pomocą T4) NamedTupleklasę, która działa w taki sam sposób Tuple, ale z nazwą łańcucha jako pierwszym argumentem w konstruktorze.

Aby odpowiedzieć na pytanie, jeśli nie chcesz używać jednego pliku, być może użyj MyClass_1.cs dla MyClass<T1>, MyClass_2.cs dla MyClass<T1, T2>itp.

Żadna z tych opcji nie jest jednak idealna, dlatego chętnie zasugeruję argument „Microsoft zrób to w ten sposób, więc ...”.

Wai Ha Lee
źródło
2
Tuplei Actionwszyscy są delegatami; nie mają żadnego kodu implementacji, więc umieszczenie wszystkich odmian w osobnych plikach i tak byłoby trochę bezcelowe. Udowadnia tylko, że każda reguła ma wyjątek.
Robert Harvey
Tak, ogólnie mówiąc, umieszczenie wielu publicznych delegatów w tym samym pliku jest uważane za prawidłowe (pod warunkiem, że są powiązane).
Stephen
1
@RobertHarvey, Tuplenie jest delegatem, ale i tak każda implementacja jest krótka.
Arturo Torres Sánchez
@ ArturoTorresSánchez: Tak, myślałem o tym Func.
Robert Harvey
0

Czy zadawałeś sobie pytanie, czy zajęcia mają taki sam cel? Jeśli jedna klasa jest bardziej ogólna od drugiej, będzie to GenericClass , MoreGenericClass i MostGenericClass . Wyobraź sobie, że każdy parametr typu klasy dodaje nowy wymiar do klasy, więc może pomóc pytanie, jaki to wymiar.

Weźmy ten przykład:

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

Wiem, że nie jest to najlepszy przykład, ale bardzo ekspresyjny, aby pokazać trzy wymiary:

  • Wymiar wewnętrzny, co może załadować
  • wymiar Wymiar, za pomocą którego można go załadować, tylko na podstawie liczby rzeczy lub miary kwadratu, pojemności sześciennej lub wagi
  • Wymiar zewnętrzny, gdzie można go załadować.

Możesz więc modelować transport samochodów:

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

Transport płynów:

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

Transport energii:

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

Transport cukru, zbóż:

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

Och, co za niespodzianka: a List<T>ma jeden wymiar, który reprezentuje rzeczy, które może pomieścić lista; i jest to Map<T, S>z dwoma wymiarami, które reprezentują rzeczy, które może pomieścić mapa i klucze dostępu.

shylynx
źródło
1
Nie sądzę, że zrozumiałeś pytanie. Spójrz na ostatni akapit pytania.
Robert Harvey
1
@RobertHarvey Przeczytaj uważnie pytanie: nazwa klasy powinna być równoważna nazwie pliku. Jest wymiennie. Problem polega na niewłaściwej analizie klasy i ogólnie niewłaściwym nazewnictwie klas ogólnych. Podsumowując moją odpowiedź: „Nazwij to, co to jest, a nie to, czym się wydaje”.
shylynx
1
@RobertHarvey Przeczytaj moją odpowiedź: Umieść jedną klasę w jednym pliku!
shylynx
1
Myślę, że brakuje ci sensu. Pytanie pyta: Jak mogę umieścić Tuple<T1>, Tuple<T1, T2>a Tuple<T1, T2, T3>na oddzielne pliki CS w standardowy sposób, bez nazwy starć?
Robert Harvey