Perché utilizzare un metodo generico con un vincolo di tipo anziché il tipo stesso?


14

In una domanda StackExchange diversa, ho notato qualcuno che utilizza questo prototipo:

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

Tenendo presente che esiste un solo tipo di vincolo ( SomeSpecificReferenceType), qual è la differenza e il vantaggio di scriverlo in questo modo, anziché semplicemente:

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

In entrambi i casi, argsarà soggetto al controllo del tipo in fase di compilazione. In entrambi i casi, il corpo del metodo può fare affidamento in modo sicuro sulla conoscenza che argè (o è un discendente di) un tipo specifico che è noto al momento della compilazione.

È questo il caso di uno sviluppatore troppo zelante che impara a conoscere i generici prima di imparare l'eredità ordinaria? Oppure esiste un motivo legittimo per cui una firma del metodo verrebbe scritta in questo modo?


Conosco a malapena C # quindi questa è solo un'ipotesi, ma ciò non consente una spedizione statica più efficiente invece della spedizione dinamica?
Anton Barkovsky

Risposte:


13

È questo il caso di uno sviluppatore troppo zelante che impara a conoscere i generici prima di imparare l'eredità ordinaria?

Sì, probabilmente lo è.

Oppure esiste un motivo legittimo per cui una firma del metodo verrebbe scritta in questo modo?

Forse . In generale, avrebbe più senso se esistesse un valore restituito To un altro parametro utilizzato T.

Ma è possibile che gli interni del codice utilizzino T(forse come argomento per un serializzatore?) E debbano usare specificamente Te non la classe di vincolo. Occasionalmente vedrai che quando il vincolo è un'interfaccia accoppiata con il newvincolo e il coraggio del metodo crea Ts per qualche motivo.

Quindi, sebbene sia raro vedere la versione del vincolo necessaria, ci sono alcune volte in cui lo è. Ed è sempre possibile che il metodo l'abbia usato , ma ora non lo fa e lo sviluppatore lo ha lasciato per non introdurre un cambiamento di rottura.


1

Penso di ricordarmi di aver scritto una risposta contenente questo.

A quel tempo il motivo era così:
(Il codice potrebbe essere diverso. Solo per illustrare uno dei possibili motivi per cui c'è un vincolo sul parametro type in un metodo generico.)

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);
    }
}

Fondamentalmente, il codice entra in codice manualmente manipolazioni del tipo stesso. Potrebbe anche essere confuso con alcune cose di riflessione.

Ad esempio, usando Method<T>(T arg) where T : ..., si può sostituire arg.GetType()con typeof(T). Tuttavia, non so se questa scelta sia buona o cattiva.

Immagino che questo sia solo un esempio dell'autore (forse io o qualcun altro) che non sta riflettendo attentamente su tutte le possibilità di codifica, concentrandosi allo stesso tempo troppo su una domanda / questione diversa.


"si può sostituire arg.GetType () con typeof (T)". Ciò è utile quando arg può validamente essere nullo, ad esempio in alcuni casi di serializzazione.
Walpen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.