Dziedzicz z ogólnej klasy bazowej, zastosuj ograniczenie i zaimplementuj interfejs w języku C #

117

To jest pytanie dotyczące składni. Mam klasę ogólną, która dziedziczy z ogólnej klasy bazowej i stosuje ograniczenie do jednego z parametrów typu. Chcę również, aby klasa pochodna implementowała interfejs. Za całe życie nie potrafię znaleźć właściwej składni.

Oto co mam:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar { ... }

Pierwszą rzeczą, która przyszła mi do głowy, było to:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar, IFoo { ... }

Ale to jest niepoprawne, ponieważ powoduje, że T2 musi zaimplementować zarówno IBar, jak i IFoo, a nie DerivedFoo, aby zaimplementować IFoo.

Próbowałem trochę googlować, używać dwukropków, średników itp., Ale wyszedłem krótko. Jestem pewien, że odpowiedź jest banalnie prosta.

Dan Rigby
źródło
Nie mogłem zrozumieć odpowiedzi @ Adama, kiedy spojrzałem raz, ale po 2 minutach mogłem zrozumieć, co to jest, dziękuję za odpowiedź. Klasa pochodna ma więcej niż jedną implementację, być może o to chodzi. W każdym razie chcę pokazać innym jego zapis. „class DerivedClass <Type>: ParentClass gdzie Type: IType”. Nic nie powinno znajdować się między ostatnią zaimplementowaną klasą a klauzulą ​​WHERE.
nurisezgin

Odpowiedzi:

173

Przed zdefiniowaniem ogólnych ograniczeń dołączasz cały podpis swojej klasy.

class DerivedFoo<T1, T2> : ParentFoo<T1, T2>, IFoo where T2 : IBar
{
    ...
}
Adam Robinson
źródło
5
Dla innych zinternalizowałem to jako, że klasa dostaje tylko jedną klauzulę where, a na końcu wszystkie ograniczenia typu ogólnego.
Andy V
@Visser Dozwolone jest posiadanie wielu klauzul gdzie, klasa Test <T1, T2> gdzie T1: Interface1 gdzie T2: Interface2
bwing
@Visser tak, co powiedział bwing, również każda z klauzul może mieć wiele ograniczeń… więc składnia z oryginalnego postu jest poprawna, oznacza po prostu coś innego, czego chciał op. where T2 : IBar, IFoo oznacza po prostu, że T2zamiast DerivedFoo<T1,T2> implementować , musi zaimplementować oba interfejsyIFoo
v01pe
18

Moja rada: jeśli masz pytanie dotyczące składni języka C #, przeczytaj specyfikację; dlatego to publikujemy. Będziesz chciał przeczytać sekcję 10.1.

Aby odpowiedzieć na Twoje konkretne pytanie, kolejność rzeczy w deklaracji klasy jest następująca:

  • atrybuty w nawiasach kwadratowych
  • modyfikatory („publiczne”, „statyczne” itd.)
  • "częściowy"
  • "klasa"
  • nazwa klasy
  • rozdzielona przecinkami lista deklaracji parametrów typu wewnątrz nawiasów kątowych
  • dwukropek następuje po rozdzielonej przecinkami liście typów bazowych (klasa bazowa i zaimplementowane interfejsy, klasa bazowa musi być pierwsza, jeśli istnieje)
  • ograniczenia parametrów typu
  • ciało klasy, otoczone szelkami
  • średnik

Wszystko na tej liście jest opcjonalne z wyjątkiem „klasy”, nazwy i treści, ale wszystko musi pojawić się w tej kolejności, jeśli się pojawi.

Eric Lippert
źródło
95
Eric, chociaż bardzo szanuję cię jako profesjonalistę i doceniam twoją opinię, nie mogę się powstrzymać od frustracji, która wydaje się szorstka. Krytykujesz mnie za to, że zdecydowałem się zadać pytanie w witrynie z pytaniami i odpowiedziami związanymi z programowaniem, zamiast lokalizować, pobierać i przeszukiwać wysoce techniczny 503-stronicowy dokument Word ukryty pod linkiem w MSDN. To dość szorstkie. Było to najbardziej efektywne wykorzystanie mojego czasu i ma tę dodatkową zaletę, że może później komuś pomóc. Link do specyfikacji języka C # dla zainteresowanych to: msdn.microsoft.com/en-us/vcsharp/aa336809.aspx
Dan Rigby
17
Żadna krytyka nie była zamierzona. W komunikacji tekstowej istnieje wszechobecna stronniczość, która sprawia, że ​​proste stwierdzenia faktów brzmią szorstko i szorstko; Staram się czytać życzliwie, gdy otrzymuję listę pomocnych faktów, i polecam, abyś to zrobił. Trzymam się mojej rekomendacji; jeśli masz pytania dotyczące składni, specyfikacja udziela na nie ostatecznej odpowiedzi i zaczyna się od pomocnego spisu treści, umożliwiającego znalezienie definicji określonych składni.
Eric Lippert
3
Dan, znalezienie specyfikacji C # jest tak proste, jak wpisanie „C # Spec” w Google i naciśnięcie przycisku „I am lucky”. A jeśli jesteś profesjonalnym programistą C #, powinieneś już mieć specyfikację C # w formacie PDF na swoim komputerze. Nie chcę też ciebie krytykować. Nie byłem przyzwyczajony do czytania specyfikacji wcześniej, ale zacząłem ją czytać dzięki Jonowi, Ericowi i Pavelowi, którzy zawsze cytują specyfikację C # na każde pytanie. Przekonałem się, że specyfikacja C #, mimo że czasami może być trudna do odczytania, jest świetnym sposobem na poznanie języka.
Rozwiązanie
@Eric Lippert: W porządku. Dziękuję za odpowiedź. Jako konstruktywna sugestia byłoby pomocne, gdyby Microsoft zintegrował zawartość specyfikacji bezpośrednio z MSDN, oprócz posiadania jej osobnego pobrania. Wersja Visual Studio .Net MSDN ma zintegrowaną wersję specyfikacji, ale nie nowsze wersje. Zastanawiałem się nad zakupem książki Andersa Hejlberga, ale mając .Net 4.0 tuż za rogiem, nie chcę jeszcze tego robić. amazon.com/C-Programming-Language-3rd/dp/0321562992 Dzięki.
Dan Rigby,
2
C ++ wymaga, aby deklaracja klasy kończyła się średnikiem. Wielu programistów C # wywodzi się z C ++; czasami ich palce wkładają średnik bez angażowania mózgu. :-) Istnieje wiele konstrukcji w C #, które przyjmują opcjonalny semi, podczas gdy C ++ go wymaga. To po prostu subtelna wygoda. Przypuszczam, że pozwala to również subtelnie wywołać, kiedy deklaracja typu kończy się, a powiedzieć, że deklaracja treści metody.
Eric Lippert
8
public interface IFoo {}
public interface IBar {}

public class ParentFoo<T,T1> { }
public class DerivedFoo<T, T1> : ParentFoo<T, T1>, IFoo where T1 : IBar { }
Stan R.
źródło
2
public class KeyAndValue<T>
{
    public string Key { get; set; }
    public virtual T Value { get; set; }
}

public class KeyAndValue : KeyAndValue<string>
{
    public override string Value { get; set; }
}

To jest rozszerzenie istniejących odpowiedzi. Wartość domyślna to, stringjeśli nie podasz typu. Nie zaimplementowałem interfejsu, ale nie powinno to wymagać niczego innego niż zwykle.

user875234
źródło