2012-04-30 963 views
6

Estoy trabajando en una pequeña biblioteca de clases en el trabajo, y naturalmente implica el uso de genéricos para esta tarea. Pero hay algo que realmente no entiendo con los genéricos: ¿Por qué necesitaría usar parámetros genéricos de tipo y luego restringir el parámetro tipo a una clase base o interfaz específica?¿Cuál es el punto de tener restricciones para los parámetros de tipo en .NET (clase base y restricciones de interfaz)

He aquí un ejemplo de lo que quiero decir:

public class MyGenericClass<T> where T : SomeBaseClass 
{ 
    private T data; 
} 

y aquí está la aplicación sin genéricos

public class MyClass 
{ 
    private SomeBaseClass data; 
} 

¿Son estas dos definiciones del mismo (si es así, entonces no veo la advatage de usar genéricos aquí)?

Si no es así, ¿qué nos beneficiamos del uso de los genéricos aquí?

Respuesta

7

Como con casi todos los usos de los genéricos, el beneficio llega al consumidor. Restringir el tipo le da las mismas ventajas que obtiene al escribir fuertemente su parámetro (o puede hacer otras cosas como asegurarse de que haya un constructor público sin parámetros o asegurarse de que sea un valor o tipo de referencia) mientras conserva las sutilezas de los genéricos para el consumidor de tu clase o función.

El uso de genéricos también, por ejemplo, le permite obtener el tipo real que fue especificado, si eso tiene algún valor en particular.

Este ejemplo es un poco artificial, pero un vistazo a esto:

public class BaseClass 
{ 
    public void FunctionYouNeed(); 
} 

public class Derived : BaseClass 
{ 
    public void OtherFunction(); 
} 

public class MyGenericClass<T> where T: BaseClass 
{ 
    public MyGenericClass(T wrappedValue) 
    { 
     WrappedValue = wrappedValue; 
    } 

    public T WrappedValue { get; set; } 

    public void Foo() 
    { 
     WrappedValue.FunctionYouNeed(); 
    } 
} 

... 

var MyGenericClass bar = new MyGenericClass<Derived>(new Derived()); 

bar.Foo(); 

bar.WrappedValue.OtherFunction(); 
+0

Ya veo. Pero en lo que se refiere a la clase genérica, no hay diferencia real ... ¡De acuerdo, lo entiendo! –

+0

@AviShilon: en su mayor parte, no. La única diferencia entre las restricciones de tipo genérico y el tipado estático normal es que una restricción de tipo genérico puede especificar las palabras clave 'class' y' struct' para restringir a cualquier referencia o tipo de valor, respectivamente. Eso no se puede expresar en la sintaxis de tipeo estático normal. También puede hacer algo como 'typeof (T)' para obtener el tipo * specific * sin recurrir a 'GetType()' (que podría ser más derivado que 'T' o no funcionaría en absoluto si el valor es' null '). –

1

La diferencia es que el primero define la nueva clase como un tipo específico; el último simplemente define una clase simple con un campo de ese tipo.

1

Se trata de seguridad tipo. Usando genéricos puede devolver un tipo concreto (T) en lugar de algún tipo de base que define la API que necesita en su clase genérica. Por lo tanto, la persona que llama de su método no tendrá que convertir el resultado al tipo concreto (que es una operación propensa a errores).

+0

Great Marek. Muchas gracias por la amable ayuda. –

1

La principal diferencia está en el uso. En el primer caso, el uso puede tener:

MyGenericClass<SomeDerivedClass> Variable 
Variable.data.SomeDerivedProperty = X 

Y por lo que cuando se utiliza esa clase, todavía se puede acceder a cualquier cosa, desde SomeDerivedClass sin poner de nuevo a él.

El segundo ejemplo no lo permite.

MyClass.data = SomeDerivedClassInstance 
MyClass.data.SomeDerivedProperty = X //Compile Error 
((SomeDerivedClass)MyClass.data).SomeDerivedProperty = X //Ewwwww 

Usted tendrá que emitir de nuevo hasta la SomeDerivedClass (que no es seguro) para usar algo específico a la clase derivada.

+0

Excelente ejemplo. Como otros han especificado esta respuesta, supongo que esta es realmente la principal diferencia entre las dos definiciones. Y el que puede beneficiarse de ello es el consumidor. Menos que la clase original genérica/no genérica. ¡Gracias! –

1

No creo que hay una enorme cantidad de diferencia, excepto que la versión genérica está limitando su Clase, mientras que el segundo es simplemente una limitación a un miembro de de la clase. Si agregaste más miembros y métodos a tu primera Clase, tendrías la misma restricción en su lugar.

Cuestiones relacionadas