C# desde Cero | Utilizando generics
Alfredo Mendoza Fuentes@amefu
Detectando el tipo de objeto
Como sabemos en nuestro método recibimos un parámetro de tipo genérico el cual tiene por nombre socialNetwork
, y para este caso lo declaramos como el tipo de clase SocialNetwork
dentro de la variable socialNetworkItem
, más adelante definimos una condicional para identificar si el objeto pertenece al de tipo SocialNetworkWithGroups
.
1 public string GetSocialNetworkStats<T>(T socialNetwork) 2 { 3 var socialNetworkItem = socialNetwork as SocialNetWork 4 5 if (socialNetworkItem is SocialNetworkWithGroups) 6 { 7 .... 8 } 9 return ... 10 }
Este procedimiento me llevo a pensar una manera de detectar el tipo de objeto que se esta recibiendo sin tener que declararlo directamente socialNetworkItem = socialNetwork as SocialNetWork
, en mi caso para evitar demasiadas declaraciones cuando se tengan distintos tipos. De tal forma que en mi búsqueda encontré las siguientes opciones para realizarlo.
Opción 1
De esta forma solo logre detectar el tipo, más no minificar la declaración para el respectivo tipo del objeto, puesto que una vez detectado, si pertenece a un tipo específico tendré que declarar dentro de la condicional al tipo que pertenece, aún no se acerca a lo que busco.
1 Type tipo = typeof(T); 2 3 if (tipo == typeof(SocialNetworkWithGroups)) 4 { 5 Console.WriteLine("Es una red social con grupos"); 6 } 7 else if (tipo == typeof(SocialNetwork)) 8 { 9 Console.WriteLine("Es una red social"); 10 }
Opción 2
Con esta otra forma evitamos la declaración de un objeto Type
para identificar el tipo de dato que estamos recibiendo en nuestro parámetro, mediante el método .GetType()
, adicionalmente esta opción tiene algo que la distingue de las opciones 1 y 3, que estaré explicando luego. La contra con esta opción es que nuevamente nos topamos con la necesidad de tener que declarar el tipo de dato al que pertenece una vez pasada la condicional, es una opción pero no la que deseo.
1 if (socialNetwork.GetType() == typeof(SocialNetwork)) 2 { 3 Console.WriteLine("Es una red social"); 4 } 5 else if (socialNetwork.GetType() == typeof(SocialNetworkWithGroups)) 6 { 7 Console.WriteLine("Es una red social con grupos"); 8 }
Opción 3
La última de todas es volver al inicio, así es, pero esta vez sin la necesidad de tipar la declaración del tipo de objeto luego de pasar la condición, de esta forma:
1 if (socialNetwork is SocialNetworkWithGroups sng) 2 { 3 Console.WriteLine($"{sng.Name} Es una red social con grupos"); 4 } 5 else if (socialNetwork is SocialNetwork sn) 6 { 7 Console.WriteLine($"{sn.Name} Es una red social"); 8 }
Logrando así declarar el tipo de objeto al que pertenezca e identificarlo mediante la misma condicional, obviando así la declaración antes o después que alguna condicional se cumpla.
1 var socialNetworkItem = socialNetwork as SocialNetWork 2 3 var socialNetworWithGroupItem =socialNetwork as SocialNetworkWithGroups 4
Respecto a la característica que comparten las opciones 2 y 3, es el orden de la condicional, como se vio en esta sesión, nuestra clase SocialNetworkWithGroups
hereda de SocialNetwork
, por lo cual en las opciones mencionadas, si la primera de nuestras condicionales se igual a la clase de la cual se esta heredando y luego le siguen otras clases que heredan de esa misma tendremos el siguiente resultado.
1//Digamos que el socialNetwork que se envía como parámetro es de tipo WithGroups: 2 3 if (socialNetwork is SocialNetwork sn) //Esto es verdadero 4 //se cumple la condicional 5 else if (socialNetwork is SocialNetworkWithGroups sng) //Esto también 6 //No llega hasta aquí 7 else if (socialNetwork is SocialNetworkWithGroups2 sng2) 8 ...
Esto sucede debido al factor de la herencia, es por ello que en la condicional, las clases que heredan de la principal deben de colocarse antes de esta, para que puedan ser evaluadas.
Optimización
Ahora con las declaración de las variables ya simplificadas, en caso que tenga más clases que hereden de SocialNetwork
obtendre un conjunto anidado de condicionales
1 if (socialNetwork is SocialNetworkWithGroups stypefour) 2 ..... 3 else if (socialNetwork is SocialNetworkWithGroupsThree stypethree) 4 ..... 5 else if (socialNetwork is SocialNetworkWithGroupsTwo stypetwo) 6 ..... 7 else if (socialNetwork is SocialNetworkWithGroupsTOne stypeone) 8 ..... 9 else if (socialNetwork is SocialNetwork sn) 10 .....
Mi consulta sería, cual podría ser una solución para evitar un fuerte anidado en ese tipo de situaciones. Si bien esta la alternativa de usar un switch, existe algo más optimizado ? Por ejemplo algo para detectar el tipo de dato directamente sin tener que pasar por demasiadas validaciones.