Po co używać ogólnej metody z ograniczeniem typu zamiast samego typu?

14

W innym pytaniu StackExchange zauważyłem, że ktoś używa tego prototypu:

void DoSomething<T>(T arg) where T: SomeSpecificReferenceType
{
    //Code....
}

Mając na uwadze, że istnieje tylko ograniczenie jednego typu ( SomeSpecificReferenceType), jaka jest różnica i korzyść z pisania go w ten sposób, zamiast po prostu:

void DoSomething(SomeSpecificReferenceType arg)
{
    //Code....
}

W obu przypadkach argbędzie podlegać kontroli typu kompilacji. W obu przypadkach treść metody może bezpiecznie polegać na wiedzy, która argjest (lub jest potomkiem) określonego typu, który jest znany w czasie kompilacji.

Czy jest to przypadek nadgorliwego programisty, który poznaje generyczne, zanim dowie się o zwykłym dziedzictwie? Czy istnieje uzasadniony powód, dla którego podpis metody zostałby napisany w ten sposób?

John Wu
źródło
Ledwo znam C #, więc jest to tylko przypuszczenie, ale czy nie umożliwia to bardziej wydajnej wysyłki statycznej zamiast dynamicznej?
Anton Barkovsky

Odpowiedzi:

13

Czy to przypadek nadgorliwego programisty, który poznaje generyczne, zanim dowie się o zwykłym dziedzictwie?

Tak, prawdopodobnie tak jest.

Czy istnieje uzasadniony powód, dla którego podpis metody zostałby napisany w ten sposób?

Może . Zasadniczo byłoby bardziej sensowne, gdyby w grę wchodziła zwracana wartość Tlub inny parametr T.

Ale możliwe jest, że wewnętrzne elementy kodu używają T(być może jako argumentu do serializatora?) I muszą używać konkretnie, Ta nie klasy ograniczeń. Czasami zobaczysz, że gdy ograniczenie jest interfejsem sparowanym z newograniczeniem, a wnętrzności metody tworzą Ts z jakiegoś powodu.

Tak więc, chociaż rzadko jest potrzebna wersja z ograniczeniami, zdarza się, że tak jest. I zawsze jest możliwe, że metoda kiedyś tego potrzebowała, ale teraz nie, a programista ją zostawił, aby nie wprowadzać przełomowej zmiany.

Telastyn
źródło
1

Chyba pamiętam, jak wpisałem odpowiedź zawierającą to.

W tym czasie powód był następujący:
(Kod może być inny. Aby zilustrować jeden z możliwych powodów ograniczenia parametru type w metodzie ogólnej).

class SomeSingleton
{
    static Dictionary<Type, List<object>> staticTypeSpecificList;
    public void AddObjectToList<T>(T t) where T : SomeCommonThing
    {
        Type tt = t.GetType();
        List<object> list;
        if (!staticTypeSpecificList.TryGet(tt, out list))
        {
            list = new List<object>();
            staticTypeSpecificList.Add(tt, list);
        }
        list.Add(t);
    }
}

Zasadniczo kod sam się manipuluje ręcznym kodowaniem. Może być również pomieszany z niektórymi elementami refleksyjnymi.

Na przykład, za pomocą Method<T>(T arg) where T : ..., można wymienić arg.GetType()z typeof(T). Nie wiem jednak, czy ten wybór jest dobry, czy zły.

Sądzę, że to tylko przykład autora (być może mnie lub kogoś innego), który nie zastanawia się dokładnie nad wszystkimi możliwościami kodowania, jednocześnie koncentrując się zbytnio na innym pytaniu / problemie.

rwong
źródło
„można zastąpić arg.GetType () typof (T)”. Jest to przydatne, gdy argument może być zerowy, np. W niektórych przypadkach serializacji.
walpen