Jaka jest dobra konwencja nazewnictwa dla typów ogólnych w C #? [Zamknięte]

16

Postanowiłem zadać to pytanie tutaj zamiast przepełnienia stosu, ponieważ jest to raczej subiektywne.

W języku C # zazwyczaj widzę typy ogólne o bardzo złych nazwach. W szczególności „T” jest powszechnie używane, ale samo w sobie nie jest znaczącą nazwą. Na przykład:

class Fruit<T>
{
    T fruit;
}

Chociaż jest to typowe podejście, czy ktoś by tego nie zalecił? A jeśli tak, to jaka byłaby rozsądna konwencja nazewnictwa dla typów ogólnych w kontekście C # dla funkcji ogólnych i klas?

W poprzednim przykładzie załóżmy, że rodzaj ogólny Tmusi zawsze być rodzajem owocu, takim jak Applelub Orange. Ten typ Tmusi wyraźnie wskazywać FruitType, że jest to rodzaj owocu, więc być może lepsza nazwa to , więc otrzymamy:

class Fruit<FruitType>
{
    FruitType fruit;
}

To po prostu dać wam wyobrażenie o tym, czego szukam. Jaka jest akceptowalna „ogólna zasada” dla tego problemu?

void.pointer
źródło
3
To nie jest konstruktywne pytanie. Otrzyma odpowiedzi tylko w ulubionym stylu plakatu.
Michael K,
1
Spójrz na ograniczenia, biorąc pod uwagę twój przykład: msdn.microsoft.com/en-us/library/d5x73970.aspx#Y426
Matthieu
2
@Michael będzie wiele odpowiedzi, a zaakceptowana odpowiedź będzie ulubiona przez Roberta, ale różne inne odpowiedzi zostaną poddane pod głosowanie.
StuperUser
5
@Michael Subiektywne pytanie otrzymuje subiektywną odpowiedź. Pytanie jest nadal konstruktywne, ponieważ służy jako punkt odniesienia dla każdego, kto chce różnorodnych pomysłów / rozwiązań tego konkretnego problemu. Ten, który zaznaczam jako odpowiedź, nie reprezentuje jedynego użytecznego fragmentu informacji.
void.pointer
Być może zamienisz ją w wiki społeczności, jako dobry, choć subiektywny zasób?
tylermac

Odpowiedzi:

22

To jest rzeczywiście subiektywne ... ish .
Ponieważ niektórzy ludzie uważają, że ijest całkowicie poprawny dla zmiennej pętli for, niektórzy uważają, że Tjest całkowicie poprawny dla typu zastępczego w klasie ogólnej.

Osobiście popieram to podejście, jest to wspólna konwencja i ludzie ogólnie wiedzą, co masz na myśli.

Tam, gdzie typ jest znaczący, użyłbym znaczącej nazwy, ale generalnie zacznę od T. Ostatnio opracowałem ogólną klasę słownika (nie pytaj) i deklaracja była

public class Dictionary<TKey, TValue>

Jednak w przypadku czegoś takiego jak Tuple, w którym typy są w zasadzie bez znaczenia, uważam następujące za całkowicie do przyjęcia.

public class Tuple<T1, T2, T3>
Binarny Worrier
źródło
2
W ogóle nie uważam tego za subiektywne. ii Tpracy, i jest to w zasadzie mierzalne (tj. można zmierzyć, czy zrozumienie kodu źródłowego wzrasta, jeśli powiedzmy, że indeksy pętli otrzymują różne identyfikatory). To, że trudno to zmierzyć, nie oznacza, że ​​musimy oznaczać etykietę „subiektywną” na wszystkim. Biorąc pod uwagę szerokie zastosowanie bez oczywistych problemów, całkiem rozsądne jest stwierdzenie nawet bez pomiaru, że to faktycznie działa.
Konrad Rudolph
2
@Konrad: Masz rację. . . jednak pytanie nie jest oznaczone jako subiektywne, pytający przyznaje, że jest to subiektywny temat, zakładając, że ludzie mają własne preferencje dotyczące konwencji nazewnictwa. Więc chociaż pytanie może nie być subiektywne (a tak naprawdę nie jest, ponieważ istnieje prawidłowa odpowiedź, tj. Odpowiedź, która prowadzi do oficjalnych wytycznych Microsoft), temat jest subiektywny, ponieważ jestem pewien, że ktoś opublikuje „ ii Tźli . Nigdy nie wolno używać nazw jednoliterowych” odpowiedź typu. Dodałem ish, aby wszyscy zadowalali się :)
Binary Worrier
1
Myślę, że same komentarze dodane do tego postu sprawiają, że jest to bardzo cenna odpowiedź, chociaż sama odpowiedź jest bardzo pomocna. Tma sens, gdy mówimy o typie bez ograniczeń, TFruitma sens, ponieważ mówi mi „Każdy typ z ograniczeniem, że jest owocem”. Wydaje się to dobrą „praktyczną zasadą” do nazywania parametrów typu ogólnego. Dzięki!!
void.pointer
1
Należy zauważyć, że jest to zgodne z Wytycznymi projektowania .NET Framework dla programistów bibliotek z MSDN. Zobacz: Nazwy parametrów typu ogólnego .
Grant Thomas,
7

Myślę, że masz rację, chociaż T stało się standardem. Prawdopodobnie pochodzi ze starych czasów C ++ i słowa „typu T”. Uważam, że dobrą praktyką jest jak najbardziej opisowe, ale to subiektywne.

Możesz wybrać T jako prefiks, podobnie jak wiele osób wybiera I dla interfejsów. A zatem

class Juice<TFruit> where TFruit...

byłoby moim zdaniem dobrym imieniem. W większości przypadków wolę prefiksy niż sufiksy, ponieważ od razu widać, co się dzieje, gdy się na nie natkniesz, i łatwiej jest wyszukiwać za pomocą takich funkcji, jak Intellisense. Jest to dobra praktyka również w przypadku kontrolek interfejsu użytkownika, gdy najprawdopodobniej zawsze znasz typ (np. TextBox), ale nie jesteś w 100% pewien co do opisowej nazwy, którą mu nadałeś.

Negatywną stroną tego jest to, że źle wygląda, gdy sam typ zaczyna się od T. Dlatego myślę, że dobrze byłoby sufikować typ ogólny w szczególnych przypadkach, takich jak ten poniżej.

class SomeAlgorithm<TypeT> where TypeT : Type

Pamiętaj, że to tylko moja opinia i bardzo subiektywna. Ale myślę, że mam drobny problem z tym, że wolę prefiks niż sufiks.

Sokół
źródło
Użycie Tprzedrostka dla parametrów typu i Inazw interfejsów jest wyraźnie wymagane ( reguły „ DO ...”) w Wytycznych dotyczących projektowania ram.
Richard
1
Wątpliwe jest, co zastosowanie TFruittutaj przynosi na stół T. Używanie nazwy takiej jak TTypelub z TypeTpewnością jest nonsensem. Nie dodaje żadnych informacji, a jedynie T. Przekazywane są dokładnie te same informacje.
Konrad Rudolph
@Konrad Rudolph: Przyjrzyj się uważnie mojemu przykładowi TypeT, dotyczy on szczególnego przypadku w przypadku System.Type. Wydaje mi się, że moje imiona mają wyższą entropię niż tylko użycie T dla tego typu, szczególnie jeśli ogólne jest również ograniczone.
Falcon,
7

Firma Microsoft ma oficjalne wytyczne dotyczące leków generycznych: Nazwy klas, struktur i interfejsów (cytowane tutaj oraz w formie książkowej: Wytyczne dotyczące projektowania ram ).

W odniesieniu do konkretnego pytania napisano:

Nazwij parametry typu ogólnego za pomocą nazw opisowych, chyba że nazwa jednoliterowa jest całkowicie zrozumiała, a nazwa opisowa nie dodałaby wartości.

IDictionary<TKey, TValue> 

jest przykładem interfejsu zgodnego z tymi wytycznymi.

Rozważ użycie litery T jako nazwy parametru typu dla typów z jednym jednoliterowym parametrem typu.

Czy przedrostek nazw parametrów opisowych należy wpisać literą T.

Rozważ wskazanie ograniczeń nałożonych na parametr typu w nazwie parametru. Na przykład parametr ograniczony do ISession można nazwać TSession.

Matthieu
źródło
Lepszym odniesieniem byłaby książka Wytyczne dotyczące projektowania ram lub (podsumowanie) MSDN, zwłaszcza Nazwy klas, Struktur i Interfejsów .
Richard
@Richard: dostosowałem moją odpowiedź, biorąc pod uwagę twój komentarz, dziękuję!
Matthieu,
2

Chodzi przede wszystkim o delegowanie funkcjonalności - klasa ogólna robi jedną rzecz, jej argument robi inną. Przykład podręcznika to ogólna kolekcja: kolekcja przechowuje „rzeczy”, ale nie obchodzi ich, czym one są. Nazwa ogólna (sic!) Ma zatem pewną logikę - nie chcemy, aby była opisowa, ponieważ nie ma nic do opisania poza „to argument typu rodzajowego”, który to określenie Tobejmuje wyczerpująco (biorąc pod uwagę Konwencji). Bycie opisowym jest dobre, ale zbyt opisowe sugeruje ograniczenia, których nie ma.

Czasami jednak ogólna klasa lub metoda ma więcej niż jeden parametr typu, i w tym momencie sensowne jest nadanie im bardziej opisowych nazw, aby ich rola stała się oczywista. Dobrym przykładem może być typ kolekcji klucz-wartość, w którym zarówno klucz, jak i wartość są rodzajowe; dzwonienie do nich Ti S(lub Qcokolwiek innego) byłoby mniej przydatne niż dzwonienie do nich, mówienie, KeyTypei ValueType, lub TKeyi TVal.

tdammers
źródło
1

Odpowiedź jest rzeczywiście subiektywna. Ma jednak sens jako pytanie, ponieważ kod powinien samok dokumentować, i moglibyśmy wszyscy nauczyć się lepszych sposobów na zrobienie tego.

Oto konwencje, których się nauczyłem i których przestrzegam:

  • Ogólne parametry typu nigdy nie powinny być mylone z konkretnymi klasami. Zasadniczo zachęca to do wstępu na temat Ttego, co następuje, podobnie jak interfejsy są zazwyczaj poprzedzone I.

  • Pojedynczy parametr typu ogólnego w klasie lub metodzie powinien być zazwyczaj oznaczony T. To prawie powszechnie rozumiana konwencja sięgająca szablonów C ++.

  • Wiele parametrów typu ogólnego w tej samej deklaracji klasy lub metody powinno zaczynać się od T, ale powinno być zróżnicowane za pomocą zwięzłych, ale zrozumiałych środków. TIni TOut, na przykład, są powszechnymi i dobrze zrozumiałymi GTP dla metody, która akceptuje typowe dane wejściowe o silnym typie i generuje dane wyjściowe o silnym typie.

  • Wiele zróżnicowanych, ale nieistotnych typów, takich jak klasa zawierająca, takich jak Tuple .Net lub typy delegatów, takie jak Func, Predicate i Action, mogą być oznaczone jako T1, T2, T3 itp. Jednak „niezwykłe” deklaracje GTP (mające określony cel i / lub bardzo specyficzne ograniczenia typów) powinny mieć coś bardziej opisowego.

  • Pojedynczy typ ogólny w metodzie, który różni się od ogólnego typu zawierającej klasy, może albo postępować zgodnie z poprzednią regułą dotyczącą wielu typów w klasie lub metodzie, LUB jeśli typ jest nietypowy, inny niż inny, można mu podać inny jedna litera, często Ulub V. To znowu konwencja sięgająca szablonów C ++.

  • Cokolwiek wybierzesz, zachowaj spójność; nie oznaczaj GTP dla jednej klasy T, a następnej TParam, chyba że druga klasa jest zagnieżdżona w pierwszej, co uniemożliwi jej Tużycie w drugiej.

KeithS
źródło