Como usted puede ver en el artículo publicado hace años en el sitio www.codeproject.com, llamado Using generics for calculations, alli se muestra que por ese entonces y durante mucho tiempo, realizar cálculos u operaciones con tipos genéricos no era tan fácil como parecía ser. Esto se debía basicamente a que en .NET, por ese entonces y hasta al advenimiento de los tipos dinámicos, los parámetros de tipo sin restricciones eran asumidos del tipo System.Object, el que no definía operadores (+, *, etc). Sin embargo, a partir del .NET Framework 4, los tipos dinámicos permiten facilmente hacer esto.

Supongamos que queremos crear un método que tome un número, y devuelva su cuadrado, pero deseamos hacerlo de una manera que el mismo método nos permita utilizar diferentes tipos numéricos como parámetro y que devuelva algún otro tipo (por ejemplo pasar un byte y devolver un int, o pasarle un double y devolver un double, etc)

Ahora con el adevenimiento de los tipos dinámicos es fácil hacer esto. Veremos un programa sencillo que les demostrará esto:

Código en C#:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
static class Program
{
    public static void Main()
    {
        long a = 100000;
        Console.WriteLine("El cuadrado de {0:0,0} es {1:0,0}", 
                              a, Cuadrado<long, long>(a));

        double b =200.50;
        Console.WriteLine("El cuadrado de {0:0,0.00} es {1:0,0.00}", 
                              b, Cuadrado<double, double>(b));

        byte c = 255;
        Console.WriteLine("El cuadrado de {0:0,0} es {1:0,0}", 
                              c, Cuadrado<byte, int>(c));

        Decimal d = 2000000000;
        Console.WriteLine("El cuadrado de {0:0,0} es {1:0,0}", 
                              d, Cuadrado<Decimal, Decimal>(d));
    }

    public static R Cuadrado<T, R>(dynamic x)
    {
        return x*x;
    }
}

Código en VB

Option Strict Off
Module Module1
    Sub Main()
        Dim a As Long = 100000
        Console.WriteLine("El cuadrado de {0:0,0} es {1:0,0}", 
                              a, Cuadrado(Of Long, Long)(a))

        Dim b As Double = 200.5
        Console.WriteLine("El cuadrado de {0:0,0.00} es {1:0,0.00}", 
                              b, Cuadrado(Of Double, Double)(b))

        Dim c As Byte = 255
        Console.WriteLine("El cuadrado de {0:0,0} es {1:0,0}", 
                              c, Cuadrado(Of Byte, Integer)(c))

        Dim d As [Decimal] = 2000000000
        Console.WriteLine("El cuadrado de {0:0,0} es {1:0,0}", 
                              d, Cuadrado(Of Decimal, Decimal)(d))
    End Sub

    Function Cuadrado(Of T, R)(x As Object) As R
        Return x * x
    End Function
End Module

La salida de este programa es:

Salida del programa que contiene un método genérico 'Function Cuadrado(Of T)(x as T) as R'
Figura 1- Salida del programa que contiene un método genérico 'Function Cuadrado(Of T, R)(x as T) as R'.

 

 

 


En la especificación C# 4.0, section 7.8.1 Operador Multiplicación, se puede comprobar que sólo los siguientes operadores de producto de números enteros están disponibles:
  • int operator *(int x, int y);
  • uint operator *(uint x, uint y);
  • long operator *(long x, long y);
  • ulong operator *(ulong x, ulong y);
En la misma sección también se dice lo siguiente: Los operandos se convierten a los tipos de parámetros del operador seleccionado, y el tipo del resultado es el tipo de retorno del operador. Esto explica el porque, si hacemos la siguiente llamada :

 

 

 

ushort x = 47000;
Console.WriteLine("El cuadrado de {0:0,0} es {1:0,0}", 
                      x, Cuadrado<ushort, long>(x));
...obtenemos el resultado -2,085,967,296 Según lo definido en el apartado mencionado arriba de la especificación C#, el operador * está definido entre operadores int y/o entre operadores long, por lo que al pasarle dos ushort, automáticamente los convierte a enteros y el tipo de retorno será también un int. Como el tipo entero puede tomar valores en el rango -2,147,483,648 a 2,147,483,647 y debido a que 47,000 al cuadrado es 2,209,000,000 y como 2,209,000,000 - 2,147,483,648 = 61,516,352 y -2,147,483,648 + 61,516,352 = -2,085,967,296, lo que explica por qué el resultado es ese.

 

 

 


Por otra parte, en la especificación del lenguaje Visual Basic versión 10, apartado 11.13.5 (Multiplication Operator), se establece que el operador de multiplicación está definido para los siguientes tipos: · Byte, SByte, UShort, Short, UInteger, Integer, ULong, and Long. Por ese motivo al pasarle el mismo código:

 

 

 

 Dim x As UShort = 47000
        Console.WriteLine("El cuadrado de {0:0,0} es {1:0,0}", 
                              x, Cuadrado(Of UShort, Long)(x))
...obtenemos el resultado correcto: 2,209,000,000
respag
Panamá - © 2012
Haga su donación para colaborar con La Escuela del Programador

La Escuela del Programador es un sitio web sin anuncios, sin ánimo de lucro, no es un sitio web comercial. Es el sueño de compartir con todos, muchos años de una gran pasión. Si realmente encuentra este sitio útil y lo aprovecha, le pido su generosa y no importa cuán modesta colaboración, simplemente para afrontar los costos de mantener este sitio disponible en internet.
No deseo lucrar con este sitio, ya que lo hago desinteresadamente, sólo le pido que, si puede, aporte (desde un dólar hasta lo que crea que puede dar), para afrontar los costos de dominio y hosting. Muchísimas gracias y ojalá juntos podamos hacer un sitio que sea una buena fuente de aprendizaje de programacíon en español.

Si no se siente en condiciones de colaborar, igualmente será bienvenido al sitio, es libre para todos y será un placer que encuentre mis artículos provechosos, pero si realmente me ayuda con una donación minima, seguramente, colaborará para que La Escuela del Programador se mantenga en la Web y crezca, conviertiendo a este sitio hecho con mucha pasión, dedicación y esfuerzo, en una buena fuente de aprendizaje.

Mis saludos cordiales y gracias por interesarse en mi sitio.

Rubén E. Spagnuolo
respag
Panamá - © 2012