klasa generyczna i interfejs a klauzula where

0

Jeśli zrobiłem interfejs z klauzulą where:

public interface IClass1<T> where T : class
{
    void Insert(T param);
}

to dlaczego do klasy implementującej ten interfejs muszę też dodać klauzulę where:

public class Class1<T> : IClass1<T> where T : class
{
    public virtual void Insert(T param)
    {
        //......
    }
}

bo jak nie dodam to mam błąd:
**The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'ClassLibrary1.IClass1<T>' **

Wydaje mi się, że skoro mam interfejs z klauzulą where gdzie jest wskazane, że T ma być klasą to w klasie implementującej ten interfejs już nie powinno się wskazywać, że T ma być klasą, bo przecież to jest wskazane w interfejsie.

0

Wydaje mi się, że chodzi o to samo co w przypadku zwykłego implementowania interfejsu w klasie.
Jeśli jakaś klasa dziedziczy ten interfejs to musi implementować wszystkie jego metody, analogicznie: jeśli interfejs, który dziedziczy klasa ma jakieś ograniczenie to klasa ta też musi je mieć.. :)
Mogę się mylić bo jeszcze się z tym nie spotkałem ale tak mi się wydaje.

2

Cały artykuł na ten temat:

http://ericlippert.com/2013/07/15/why-are-generic-constraints-not-inherited/

Na przykład:

  1. znalezienie odpowiedniego ograniczenia w nietrywialnych przypadkach może być bardzo trudne / czasochłonne. Skopiowany bezczelnie z artykułu kod:
class Banana<T> where T : Coffee<T> {}
class Coffee<U> : Banana<Giraffe<U>> where U : INewspaper<Coffee<U>> {}
class Giraffe<V> : Coffee<Banana<V>> where V : IVehicle<V> {}
  1. Przy dziedziczeniu z interfejsów dwóch parametrów generycznych można znaleźć przykłady gdzie żaden obiekt nie spełnia ograniczeń - co wtedy powinien zrobić kompilator?

  2. jeśli miałyby być dedukowane parametry przy dziedziczeniu to czemu nie na przykład tutaj:

class Foo<T> where T : class {  }
class Bar<U> { Foo<U> var; }

Wydaje mi się, że chodzi o to samo co w przypadku zwykłego implementowania interfejsu w klasie.
Jeśli jakaś klasa dziedziczy ten interfejs to musi implementować wszystkie jego metody, analogicznie: jeśli interfejs, który dziedziczy klasa ma jakieś ograniczenie to klasa ta też musi je mieć.. :)

To wiadomo, ale chodzi o to dlaczego kompilator sam nie zgaduje jakie powinno być ograniczenie.

0

Wydaje mi się, że skoro mam interfejs z klauzulą where gdzie jest wskazane, że T ma być klasą to w klasie implementującej ten interfejs już nie powinno się wskazywać, że T ma być klasą, bo przecież to jest wskazane w interfejsie.

No ale tak nie jest, źle ci się wydaje, a jest tak jak jest.

C# działa tak jak został zaprojektowany. Ktoś zdecydował że tak ma być; można debatować co mu po głowie wtedy krążyło, ale nie zmieni to rzeczywistości.

0

Abstrahując już od tego konkretnego przypadku: istnieje kilka miejsc w C#, w których kompilator mógłby się wykazać inferencją, a obecnie tego nie robi. Czasem powody są naprawdę prozaiczne - nie było czasu, chęci ani wielkiej potrzeby. Ktoś zadał podobne pytanie na SO i w podobnym tonie odpowiedział Eric Lippert (jeden z byłych programistów kompilatora C#).

1 użytkowników online, w tym zalogowanych: 0, gości: 1