¿Por qué usar un método genérico con una restricción de tipo en lugar del tipo en sí?

14

En una pregunta diferente de StackExchange, noté que alguien usaba este prototipo:

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

Teniendo en cuenta que solo hay una restricción de tipo único ( SomeSpecificReferenceType), cuál es la diferencia y la ventaja de escribirlo así, en lugar de simplemente:

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

En ambos casos, argestará sujeto a verificación de tipo en tiempo de compilación. En ambos casos, el cuerpo del método puede confiar con seguridad en el conocimiento que arges (o es descendiente de) un tipo específico que se conoce en tiempo de compilación.

¿Es este el caso de un desarrollador entusiasta que aprende sobre genéricos antes de aprender sobre la herencia ordinaria? ¿O hay una razón legítima por la cual una firma de método se escribiría de esta manera?

John Wu
fuente
Apenas conozco C #, así que esto es solo una suposición, pero ¿no permite esto un envío estático más eficiente en lugar del envío dinámico?
Anton Barkovsky

Respuestas:

13

¿Es este el caso de un desarrollador entusiasta que aprende sobre genéricos antes de aprender sobre la herencia ordinaria?

Sí, probablemente lo sea.

¿O hay una razón legítima por la cual una firma de método se escribiría de esta manera?

Tal vez . En general, tendría más sentido si hubiera un valor de retorno involucrado Tu otro parámetro que se utilizara T.

Pero, es posible que los componentes internos del código utilicen T(¿quizás como un argumento para un serializador?) Y necesiten utilizar específicamente Ty no la clase de restricción. Ocasionalmente verá que cuando la restricción es una interfaz emparejada con la newrestricción y las entrañas del método creanT s por alguna razón.

Entonces, aunque es raro ver la versión de restricción necesaria, hay algunas ocasiones en que es así. Y siempre es posible que el método utilizado a necesitarlo, pero ahora no lo hace y el desarrollador dejó como es la de no introducir un cambio importante.

Telastyn
fuente
1

Creo que me recuerdo escribiendo una respuesta que contiene esto.

En ese momento, la razón era la siguiente:
(El código puede ser diferente. Solo para ilustrar una de las posibles razones por las cuales hay una restricción en el parámetro de tipo en un método genérico).

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

Básicamente, el código entra en codificaciones manuales de manipulaciones de tipo. También podría estar mezclado con algunas cosas de reflexión.

Por ejemplo, al usar Method<T>(T arg) where T : ..., uno puede reemplazar arg.GetType()contypeof(T) . Sin embargo, no sé si esa elección es buena o mala.

Supongo que este es solo un ejemplo de que el autor (posiblemente yo u otra persona) no está analizando cuidadosamente todas las posibilidades de codificación, al mismo tiempo centrándose demasiado en una pregunta / problema diferente.

rwong
fuente
"se puede reemplazar arg.GetType () con typeof (T)". Esto es útil cuando arg puede ser válidamente nulo, por ejemplo, en algunos casos de serialización.
walpen