el Guille, la Web del Visual Basic, C#, .NET y más...

Definición de una estructura para operar sobre tipos anulables

Librería con tipos anulables para usar con Visual Basic 2005 basados en Nullable(Of T) para simular los tipos anulables de VB 9.0 y C# 2.0

 

Publicado: 14/Abr/2006
Actualizado: 19/Ene/2007
Autor: Guillermo 'guille' Som

Librería con tipos anulables para usar con Visual Basic 2005 basados en Nullable(Of ...) para simular los tipos anulables de VB 9.0 y C# 2.0



 

Introducción

Revisando el artículo de Octavio Hernández sobre los nuevos tipos anulables de la próxima versión de VB 9.0 (Orcas) que publicará próximamente en la revista dotNetManía, (que dicho sea de paso, así como quién no quiere la cosa, si resides en España y quieres conseguirla al mejor precio, pues usa mi oferta de suscripción), me decidí a crear tipos de datos en Visual Basic 2005 que simulen los tipos anulables, al menos como será en la próxima versión de Visual Basic (VB 9.0 / Orcas) y como lo son actualmente en C#.

 

Por si no sabes de que va esto de los tipos anulables:
En realidad la explicación la he puesto aparte, pulsa aquí para verla.
Ahí mismo tendrás ejemplos para Visual Basic y para C# 2005, en este último con un ejemplo de los nuevos tipos anulables, en particular de int?.

 

Crear un nuevo tipo de datos con sobrecarga de operadores y conversiones personalizadas

No vamos a ver todos los tipos definidos en la DLL (elGuille.NumericNullable), solo veremos el tipo IntegerNullable con el que nos haremos una idea de cómo están definidos los demás tipos, que son:

Tipo definido en elGuille.NumericNullable Tipo usado internamente
SByteNullable Nullable(Of SByte)
ByteNullable Nullable(Of Byte)
ShortNullable Nullable(Of Short)
UShortNullable Nullable(Of UShort)
IntegerNullable Nullable(Of Integer)
UIntegerNullable Nullable(Of UInteger)
LongNullable Nullable(Of Long)
ULongNullable Nullable(Of ULong)
DecimalNullable Nullable(Of Decimal)
SingleNullable Nullable(Of Single)
DoubleNullable Nullable(Of Double)

 

Todos los tipos tienen una serie de métodos y propiedades, que son:

Miembros de la clase Descripción
New(v) Constructor con parámetros.
Recibe el valor a asignar.
Métodos y propiedades compartidas
Null Propiedad compartida de solo lectura para obtener un valor nulo (Nothing o null).

En C# si queremos asignar un valor nulo a uno de estos tipos debemos hacerlo así:
IntegerNullable i1 = IntegerNullable.Null;
Que sería el equivalente a:
int? i1 = null;

Not(v) Método compartido para usar como el operador Not de VB.
Si hacemos esto: n = Not 5, n valdrá -6.
Pow(v1, v2) Eleva v1 a la potencia indicada por v2.
Este método compartido es el equivalente al operador ^ de VB.
Métodos y propiedades de instancia
ToString() Propiedad reemplazada.
Devuelve el valor en formato cadena.
Si el valor que contiene es nulo, devuelve la palabra "Nothing".
Value Propiedad de solo lectura que devuelve el valor o Nothing si no tiene nada asignado.
HasValue Propiedad de solo lectura que devuelve un valor verdadero o falso según tenga un valor o no.
GetValueOrDefault() Devuelve el valor que contiene o cero (el valor por defecto del tipo interno) si el contenido es nulo.
GetValueOrDefault(defaultValue) Devuelve el valor que contiene o el valor indicado en el argumento si el contenido es nulo.
Pow(n) Eleva el valor de la instancia actual al valor indicado por v.
Sobrecargas
Están todos los operadores sobrecargados excepto Like, (ver nota).
Los siguientes operadores aritméticos están sobrecargados:
suma (+), resta (-), multiplicación (*), división (/), división entera (\), exponenciación (^),
desplazamiento de bits (<< y >>)

Nota:
En la DLL distribuida a fecha del 14 de Abril (v1.0.0.1) no están implementados todas las sobrecargas de todos los operadores, pero si los más usados.
Las únicas clases que los tienen todos son: IntegerNullable y DoubleNullable.

En futuras actualizaciones incluiré todas las sobrecargas.
Los operadores lógicos o a nivel de bits: And, Or, Xor y Not.
También AndAlso y OrElse.
Los 6 operadores de comparaciones: >, <, >=,  <=, = y <>
El operador de concatenación (&), (para unir los tipos como si fueran cadenas).
Los operadores unarios + y -
Se pueden usar en expresiones boolean, ya que True y False están sobrecargados, por tanto, podemos hacer algo como:
If i1 Then ... o
If i1 = False Then ...

Esto en realidad es lo mismo que si usáramos HasValue:
If i1.HasValue Then ... o
If i1.HasValue = False Then ...
Conversiones
Se permiten conversiones implícitas entre tipos que están "por debajo", siguiendo el mismo criterio que en los tipos numéricos, con el valor añadido de que podemos convertir de LongNUllable a ULongNullable, (y lo mismo con el resto de tipos con y sin signo), algo que con los tipos normales no podemos hacer.
El orden de "privilegios", (empezando por el de menos), es: SByte, Byte, Short, UShort, Integer, UInteger, Long, ULong, Decimal, Single y Double.
Esto quiere decir que cualquier tipo se puede convertir implícitamente (sin necesidad de usar CType) a Double, pero, por ejemplo, a Short solo se podrán convertir implícitamente los dos tipos que están "por debajo": Byte y SByte.
El resto de conversiones hay que hacerlas de forma explícita usando CType( valor, TIPO )
Ver ejemplo.

 

Por ejemplo, para convertir un valor ShortNullable a ByteNullable debemos hacerlo así:

Dim s1 As ShortNullable = 125
Dim sb1 As SByteNullable = -105
Dim b1 As ByteNullable = 200

' A ShortNullable podemos asignar directamente valores de tipos "menores"
s1 = sb1
s1 = b1
' Pero al revés hay que hacer la conversión explícita
b1 = CType(s1, ByteNullable)

 

De todas formas, el propio IDE de Visual Basic te recomienda esa conversión si ve que no se puede hacer la asignación directamente, tal como vemos en la figura 1:

Figura 1: El IDE de VB2005 se encarga de convertir los tipos
Figura 1: El IDE de VB2005 se encarga de convertir los tipos

 

Nota:
Estos tipos también se pueden usar en C#, el único inconveniente es que si queremos asignar un valor null debemos usar la propiedad compartida (estática) Null que está definida en cada tipo.

 

Un par de clases (estructuras) de la librería NumericNullable

Ahora vamos a ver cómo están definidos los tipos IntegerNullable y DecimalNullable, para que veas todo lo referente a las conversiones y como en ciertos tipos no tenemos que hacerlas todas.

También te muestro un par de ejemplos de cómo se pueden usar estas clases en Visual Basic y en C#.
En los proyectos de prueba de cada lenguaje hay más ejemplos.

 

Pues espero que te sea de utilidad, que es de lo que siempre se trata.

Nos vemos.
Guillermo

El ZIP con la DLL compilada y los ejemplos de VB y C#: pruebaAnulable_pub.zip - 81.4 KB

(MD5 checksum: B9BC648081CE5C5A88F9208C740167C0)


El ZIP con el código completo de la DLL: NumericNullable_src.zip - 50.1 KB

(MD5 checksum: 5E6E911405449F10EB507AD5C9919447)


Un par de ejemplos de cómo usar estas clases

 

 

Visual Basic 2005

Private Sub operadoresLogicos()
    Dim i1 As IntegerNullable = 15
    Dim i2 As IntegerNullable = 25
 
    Console.WriteLine()
    Console.WriteLine("Usando AndAlso en dos tipos IntegerNullable")
    Console.WriteLine("===========================================")
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2)
    If i1 AndAlso i2 Then
        Console.WriteLine("If i1 AndAlso i2 Then := True")
    Else
        Console.WriteLine("If i1 AndAlso i2 Then := False")
    End If
    Console.WriteLine()
 
    Console.WriteLine("Después de hacer: i1 = Nothing")
    i1 = Nothing
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2)
    If i1 AndAlso i2 Then
        Console.WriteLine("If i1 AndAlso i2 Then := True")
    Else
        Console.WriteLine("If i1 AndAlso i2 Then := False")
    End If
 
    Console.WriteLine()
    Console.WriteLine("Usando Not")
    i1 = Not i2
    Console.WriteLine("Después de hacer: i1 = Not i2")
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2)
 
    Console.WriteLine()
    i1 = Nothing ' o IntegerNullable.Null
    Console.WriteLine("i1= {0}", i1)
    ' Esto en realidad asignará -1 que es lo mismo que Not 0
    i1 = Not i1
    Console.WriteLine("Después de hacer: i1 = Not i1")
    Console.WriteLine("i1= {0}", i1)
 
    Console.WriteLine()
    Console.WriteLine("Usando Mod")
    Console.WriteLine("Después de hacer i1 = i2 Mod 5, (i2 = {0})", i2)
    i1 = i2 Mod 5
    Console.WriteLine("i1= {0}", i1)
    Console.WriteLine("Después de hacer i1 = i2 Mod 3, (i2 = {0})", i2)
    i1 = i2 Mod 3
    Console.WriteLine("i1= {0}", i1)
    Console.WriteLine("Después de hacer i1 = i2 Mod 2, (i2 = {0})", i2)
    i1 = i2 Mod 2
    Console.WriteLine("i1= {0}", i1)
 
    Console.WriteLine()
    Console.WriteLine("Con valores de tipo Integer")
    Dim n1 As Integer
    Dim n2 As Integer = 25
    Console.WriteLine("Después de hacer n1 = n2 Mod 5, (n2 = {0})", n2)
    n1 = n2 Mod 5
    Console.WriteLine("n1= {0}", n1)
    Console.WriteLine("Después de hacer n1 = n2 Mod 3, (n2 = {0})", n2)
    n1 = n2 Mod 3
    Console.WriteLine("n1= {0}", n1)
    Console.WriteLine("Después de hacer n1 = n2 Mod 2, (n2 = {0})", n2)
    n1 = n2 Mod 2
    Console.WriteLine("n1= {0}", n1)
 
    Console.WriteLine()
    Console.WriteLine("Usando ^")
    i1 = i2 ^ 2
    Console.WriteLine("Después de hacer: i1 = i2 ^ 2")
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2)
    '
    Dim i3 As IntegerNullable
    Dim ui3 As UIntegerNullable
    i1 = 10
    i3 = i1 ^ i2
    Console.WriteLine("Después de hacer: i3 = i1 ^ i2")
    Console.WriteLine("i1= {0}, i2= {1}, i3= {2}", i1, i2, i3)
 
    ui3 = i1 ^ i2
    Console.WriteLine("Después de hacer: ui3 = i1 ^ i2")
    Console.WriteLine("i1= {0}, i2= {1}, ui3= {2}", i1, i2, ui3)
 
    Console.WriteLine()
    Console.WriteLine("Usando ^ (con Integer)")
    n1 = CInt(n2 ^ 2)
    Console.WriteLine("Después de hacer: n1 = CInt(n2 ^ 2)")
    Console.WriteLine("n1= {0}, n2= {1}", n1, n2)
 
    Console.WriteLine()
    Console.WriteLine("Usando <<")
    'i2 = Nothing
    i1 = i2 << 2
    Console.WriteLine("Después de hacer: i1 = i2 << 2")
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2)
 
    Console.WriteLine()
    Console.WriteLine("Usando >>")
    i1 = i2 >> 2
    Console.WriteLine("Después de hacer: i1 = i2 >> 2")
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2)
 
    Console.WriteLine()
    n1 = n2 << 2
    Console.WriteLine("Después de hacer: n1 = n2 << 2")
    Console.WriteLine("n1= {0} n2= {1}", n1, n2)
 
    n1 = n2 >> 2
    Console.WriteLine("Después de hacer: n1 = n2 >> 2")
    Console.WriteLine("n1= {0} n2= {1}", n1, n2)
 
    Console.WriteLine()
    Console.WriteLine("Concatenación")
    Dim str As String
    str = i1 & i2
    Console.WriteLine("i1= {0} i2= {1}", i1, i2)
    Console.WriteLine("Dim str As String = i1 & i2")
    Console.WriteLine(str)
    i1 = Nothing
    str = i1 & i2
    Console.WriteLine("i1= {0} i2= {1}", i1, i2)
    Console.WriteLine("Dim str As String = i1 & i2")
    Console.WriteLine(str)
    '
    ' Esta se puede hacer independientemente de que
    ' sobrecarguemos &
    str = "El valor de n2 = " & n2
    Console.WriteLine("str = 'El valor de n2 = ' & i2")
    Console.WriteLine(str)
 
    Console.WriteLine()
    i1 = -i2
    Console.WriteLine("Después de hacer: i1 = -i2")
    Console.WriteLine("i1= {0} i2= {1}", i1, i2)
 
    Console.WriteLine()
    Console.WriteLine("Divisiones")
    i1 = i2 / 2.5
    Console.WriteLine("Después de hacer: i1 = i2 / 2.5")
    Console.WriteLine("i1= {0} i2= {1}", i1, i2)
    i1 = i2 / 3
    Console.WriteLine("Después de hacer: i1 = i2 / 3")
    Console.WriteLine("i1= {0} i2= {1}", i1, i2)
 
    Console.WriteLine()
    Dim d1 As DoubleNullable
    Dim d2 As DoubleNullable = 25.0
    ' Esta llama a la sobrecarga de DoubleNullable
    d1 = d2 / 2.5
    Console.WriteLine("Después de hacer: d1 = d2 / 2.5")
    Console.WriteLine("d1= {0} d2= {1}", d1, d2)
    d1 = d2 / 2.0
    Console.WriteLine("Después de hacer: d1 = d2 / 2.0")
    Console.WriteLine("d1= {0} d2= {1}", d1, d2)
 
    Console.WriteLine()
    ' Esta llama a la sobrecarga de IntegerNullable
    d1 = i2 / 2.5
    Console.WriteLine("Después de hacer: d1 = i2 / 2.5")
    Console.WriteLine("d1= {0} i2= {1}", d1, i2)
    ' Esta llama a la sobrecarga de IntegerNullable
    d1 = i2 / 2
    Console.WriteLine("Después de hacer: d1 = i2 / 2")
    Console.WriteLine("d1= {0} i2= {1}", d1, i2)
 
    Console.WriteLine()
    i1 = CType(d2 ^ 2, IntegerNullable)
    Console.WriteLine("Después de hacer: i1 = CType(d2 ^ 2, IntegerNullable)")
    Console.WriteLine("i1= {0}, d2= {1}", i1, d2)
    d1 = d2 ^ 2.5
    Console.WriteLine("Después de hacer: d1 = d2 ^ 2.5")
    Console.WriteLine("d1= {0}, d2= {1}", d1, d2)
 
    Console.WriteLine("Con valores Double")
    Dim nd1 As Double
    Dim nd2 As Double = 25
    nd1 = nd2 ^ 2.5
    Console.WriteLine("Después de hacer: nd1 = nd2 ^ 2.5")
    Console.WriteLine("nd1= {0}, nd2= {1}", nd1, nd2)
 
 
    Console.WriteLine()
End Sub

 

 

C# 2005 (C# 2.0)

En C# hay cosas que no se pueden usar y otras habrá que hacerlo mediante métodos expresamente creados por el propio .NET para los casos en los que C# no soporta esa característica, como es el caso de la concatenación (&) o la exponenciación (^), lo mismo ocurre con otros operadores, por ejemplo Not que equivale a !, en C# solo opera con valores bool y devuelve también un valor bool, pero en mis clases está implementado como para devolver un valor entero, por ejemplo, i = 5, Not i será -6.
Para solventar los casos de Not y ^ he creado dos métodos estáticos (compartidos) para que tenga esa misma funcionalidad:
Pow(n1, n2) para elevar el valor de n1 a la potencia indicada por n2, también se puede usar como res = n1.Pow(n2)
Not(n1) hace lo mismo que Not n1 de Visual Basic.

private static void operadoresLogicos()
{
    IntegerNullable i1 = 15;
    IntegerNullable i2 = 25;

    Console.WriteLine();
    Console.WriteLine("Usando AndAlso en dos tipos IntegerNullable");
    Console.WriteLine("===========================================");
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2);
    if (i1 && i2)
    {
        Console.WriteLine("If i1 AndAlso i2 Then := True");
    }
    else
    {
        Console.WriteLine("If i1 AndAlso i2 Then := False");
    }
    Console.WriteLine();

    Console.WriteLine("Después de hacer: i1 = Nothing");
    i1 = IntegerNullable.Null; // null;
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2);
    if (i1 && i2)
    {
        Console.WriteLine("If i1 AndAlso i2 Then := True");
    }
    else
    {
        Console.WriteLine("If i1 AndAlso i2 Then := False");
    }

    Console.WriteLine();
    Console.WriteLine("Usando Not");
    bool b1 =  ! Convert.ToBoolean(i2);
    Console.WriteLine( _
	"Después de hacer: bool b1 = Not i2, en C#: bool b1 =  ! Convert.ToBoolean(i2);");
    Console.WriteLine("b1= {0}, i2= {1}", b1, i2);

    Console.WriteLine();
    i1 = IntegerNullable.Null;
    Console.WriteLine("i1= {0}", i1);
    // Esto en realidad asignará -1 que es lo mismo que Not 0
    b1 = ! Convert.ToBoolean(i1);
    Console.WriteLine("Después de hacer: b1 = Not i1, en C#: b1 = ! Convert.ToBoolean(i1);");
    Console.WriteLine("b1= {0}", b1);

    Console.WriteLine();
    Console.WriteLine("Usando Mod");
    Console.WriteLine("Después de hacer i1 = i2 Mod 5, (i2 = {0})", i2);
    i1 = i2 % 5;
    Console.WriteLine("i1= {0}", i1);
    Console.WriteLine("Después de hacer i1 = i2 Mod 3, (i2 = {0})", i2);
    i1 = i2 % 3;
    Console.WriteLine("i1= {0}", i1);
    Console.WriteLine("Después de hacer i1 = i2 Mod 2, (i2 = {0})", i2);
    i1 = i2 % 2;
    Console.WriteLine("i1= {0}", i1);

    Console.WriteLine();
    Console.WriteLine("Con valores de tipo Integer");
    int n1;
    int n2 = 25;
    Console.WriteLine("Después de hacer n1 = n2 Mod 5, (n2 = {0})", n2);
    n1 = n2 % 5;
    Console.WriteLine("n1= {0}", n1);
    Console.WriteLine("Después de hacer n1 = n2 Mod 3, (n2 = {0})", n2);
    n1 = n2 % 3;
    Console.WriteLine("n1= {0}", n1);
    Console.WriteLine("Después de hacer n1 = n2 Mod 2, (n2 = {0})", n2);
    n1 = n2 % 2;
    Console.WriteLine("n1= {0}", n1);

    Console.WriteLine();
    Console.WriteLine("Usando ^");
    i1 = i2 ^ 2;
    Console.WriteLine("Después de hacer: i1 = i2 ^ 2");
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2);
    //
    IntegerNullable i3;
    UIntegerNullable ui3;
    i1 = 10;
    i3 = i1 ^ i2;
    Console.WriteLine("Después de hacer: i3 = i1 ^ i2");
    Console.WriteLine("i1= {0}, i2= {1}, i3= {2}", i1, i2, i3);

    ui3 = i1 ^ i2;
    Console.WriteLine("Después de hacer: ui3 = i1 ^ i2");
    Console.WriteLine("i1= {0}, i2= {1}, ui3= {2}", i1, i2, ui3);

    Console.WriteLine();
    Console.WriteLine("Usando ^ (con Integer)");
    n1 = Convert.ToInt32(n2 ^ 2);
    Console.WriteLine("Después de hacer: n1 = CInt(n2 ^ 2)");
    Console.WriteLine("n1= {0}, n2= {1}", n1, n2);

    Console.WriteLine();
    Console.WriteLine("Usando <<");
    //i2 = Nothing
    i1 = i2 << 2;
    Console.WriteLine("Después de hacer: i1 = i2 << 2");
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2);

    Console.WriteLine();
    Console.WriteLine("Usando >>");
    i1 = i2 >> 2;
    Console.WriteLine("Después de hacer: i1 = i2 >> 2");
    Console.WriteLine("i1= {0}, i2= {1}", i1, i2);

    Console.WriteLine();
    n1 = n2 << 2;
    Console.WriteLine("Después de hacer: n1 = n2 << 2");
    Console.WriteLine("n1= {0} n2= {1}", n1, n2);

    n1 = n2 >> 2;
    Console.WriteLine("Después de hacer: n1 = n2 >> 2");
    Console.WriteLine("n1= {0} n2= {1}", n1, n2);

    Console.WriteLine();
    Console.WriteLine("Concatenación");
    string str;
    str = IntegerNullable.op_Concatenate(i1, i2);
    Console.WriteLine("i1= {0} i2= {1}", i1, i2);
    Console.WriteLine("Dim str As String = i1 & i2");
    Console.WriteLine(str);
    i1 = IntegerNullable.Null;
    str = IntegerNullable.op_Concatenate(i1, i2);
    Console.WriteLine("i1= {0} i2= {1}", i1, i2);
    Console.WriteLine("Dim str As String = i1 & i2");
    Console.WriteLine(str);
    //
    // Esta se puede hacer independientemente de que
    // sobrecarguemos &
    str = "El valor de n2 = " + n2;
    Console.WriteLine("str = 'El valor de n2 = ' & i2");
    Console.WriteLine(str);

    Console.WriteLine();
    i1 = -i2;
    Console.WriteLine("Después de hacer: i1 = -i2");
    Console.WriteLine("i1= {0} i2= {1}", i1, i2);

    Console.WriteLine();
    Console.WriteLine("Divisiones");
    i1 = i2 / 2.5;
    Console.WriteLine("Después de hacer: i1 = i2 / 2.5");
    Console.WriteLine("i1= {0} i2= {1}", i1, i2);
    i1 = i2 / 3;
    Console.WriteLine("Después de hacer: i1 = i2 / 3");
    Console.WriteLine("i1= {0} i2= {1}", i1, i2);

    Console.WriteLine();
    DoubleNullable d1;
    DoubleNullable d2 = 25.0;
    // Esta llama a la sobrecarga de DoubleNullable
    d1 = d2 / 2.5;
    Console.WriteLine("Después de hacer: d1 = d2 / 2.5");
    Console.WriteLine("d1= {0} d2= {1}", d1, d2);
    d1 = d2 / 2.0;
    Console.WriteLine("Después de hacer: d1 = d2 / 2.0");
    Console.WriteLine("d1= {0} d2= {1}", d1, d2);

    Console.WriteLine();
    // Esta llama a la sobrecarga de IntegerNullable
    d1 = i2 / 2.5;
    Console.WriteLine("Después de hacer: d1 = i2 / 2.5");
    Console.WriteLine("d1= {0} i2= {1}", d1, i2);
    // Esta llama a la sobrecarga de IntegerNullable
    d1 = i2 / 2;
    Console.WriteLine("Después de hacer: d1 = i2 / 2");
    Console.WriteLine("d1= {0} i2= {1}", d1, i2);

    Console.WriteLine();
    i1 = IntegerNullable.op_Exponent((IntegerNullable)d2, 2);
    Console.WriteLine("Después de hacer: i1 = CType(d2 ^ 2, IntegerNullable)");
    Console.WriteLine("i1= {0}, d2= {1}", i1, d2);
    d1 = DoubleNullable.op_Exponent(d2, 2.5);
    Console.WriteLine("Después de hacer: d1 = d2 ^ 2.5");
    Console.WriteLine("d1= {0}, d2= {1}", d1, d2);

    Console.WriteLine();
}

 

 

 

La clase IntegerNullable

'------------------------------------------------------------------------------
' IntegerNullable                                                   (11/Abr/06)
' Estructura para simular el tipo Integer? de VB 9.0 o int? de C# 2.0
'
' Ejemplo de tipos anulables para Visual Basic 2005
' Inicialmente como complemento del artículo de Octavio Hernández
' para dotNetManía.
'
' ©Guillermo 'guille' Som, 2006
'------------------------------------------------------------------------------

Imports Microsoft.VisualBasic
Imports System

''' <summary>
''' Estructura del tipo Nullable(Of Integer)
''' Con sobrecargas para facilitar el trabajo con este tipo de números.
''' Así se podrá usar como Integer? de VB 9.0
''' </summary>
''' <remarks></remarks>
Public Structure IntegerNullable

    ''' <summary>
    ''' Campo del tipo Nullable(Of Integer)
    ''' </summary>
    ''' <remarks>Este campo es el que realmente contiene el valor.</remarks>
    Private valor As Nullable(Of Integer)

    ''' <summary>
    ''' Propiedad compartida de solo lectura para asignar un valor nulo
    ''' </summary>
    ''' <value></value>
    ''' <returns>Nothing (null)</returns>
    ''' <remarks>
    ''' Es por si se usa en C#, ya que no podremos asignarle directamente un valor null.
    ''' </remarks>
    Public Shared ReadOnly Property Null() As IntegerNullable
        Get
            Return Nothing
        End Get
    End Property

    ''' <summary>
    ''' El constructor parametrizado para crear un valor indicando un valor entero
    ''' </summary>
    ''' <param name="v"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal v As Integer)
        valor = v
    End Sub

    ''' <summary>
    ''' Conversión implícita de Integer a IntegerNullable
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Widening Operator CType(ByVal v As Integer) As IntegerNullable
        Return New IntegerNullable(v)
    End Operator

    ''' <summary>
    ''' Conversión implícita de IntegerNullable a Integer
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Widening Operator CType(ByVal v As IntegerNullable) As Integer
        Return v.GetValueOrDefault()
    End Operator

    ''' <summary>
    ''' Convertir los demás tipos a DoubleNullable sin pérdida de información
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Widening Operator CType(ByVal v As SByteNullable) As IntegerNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As ByteNullable) As IntegerNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As ShortNullable) As IntegerNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As UShortNullable) As IntegerNullable
        Return v.Value
    End Operator


    '
    ' Conversiones explícitas
    '
    Public Shared Narrowing Operator CType(ByVal v As IntegerNullable) As ByteNullable
        Return CByte(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As IntegerNullable) As SByteNullable
        Return CSByte(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As IntegerNullable) As ShortNullable
        Return CShort(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As IntegerNullable) As UShortNullable
        Return CUShort(v.Value)
    End Operator


    '
    ' Operadores aritméticos
    '
    ''' <summary>
    ''' Los operadores aritméticos
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator +(ByVal v1 As IntegerNullable, _
			  ByVal v2 As IntegerNullable) As IntegerNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return New IntegerNullable(v1.Value + v2.Value)
    End Operator

    Public Shared Operator -(ByVal v1 As IntegerNullable, _
			 ByVal v2 As IntegerNullable) As IntegerNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return New IntegerNullable(v1.Value - v2.Value)
    End Operator

    Public Shared Operator *(ByVal v1 As IntegerNullable, _
			 ByVal v2 As IntegerNullable) As IntegerNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return New IntegerNullable(v1.Value * v2.Value)
    End Operator

    Public Shared Operator \(ByVal v1 As IntegerNullable, _
			  ByVal v2 As IntegerNullable) As IntegerNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return New IntegerNullable(v1.Value \ v2.Value)
    End Operator

    Public Shared Operator /(ByVal v1 As IntegerNullable, _
			 ByVal v2 As DoubleNullable) As IntegerNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return CType(v1.Value / v2.Value, IntegerNullable)
    End Operator

    Public Shared Operator ^(ByVal v1 As IntegerNullable, _
			 ByVal v2 As IntegerNullable) As IntegerNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return CType((v1.Value ^ v2.Value), IntegerNullable)
    End Operator

    ''' <summary>
    ''' Elevar un valor a una potencia, equivalente al operador ^ de Visual Basic.
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function Pow(ByVal v1 As IntegerNullable, _
			   ByVal v2 As IntegerNullable) As IntegerNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return CType(v1.Value ^ v2.Value, IntegerNullable)
    End Function

    ''' <summary>
    ''' Método de instancia para elevar el valor actual a una potencia.
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Pow(ByVal v As IntegerNullable) As IntegerNullable
        If Me.HasValue = False OrElse v.HasValue = False Then
            Return Nothing
        End If
        Return CType(Me.Value ^ v.Value, IntegerNullable)
    End Function

    ''' <summary>
    ''' Sobrecarga de Mod
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator Mod(ByVal v1 As IntegerNullable, _
			   ByVal v2 As IntegerNullable) As IntegerNullable
        Return v1.Value Mod v2.Value
    End Operator


    ''' <summary>
    ''' Desplazamiento de bits
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator <<(ByVal v1 As IntegerNullable, _
			   ByVal v2 As Integer) As IntegerNullable
        If v1.HasValue = False Then
            Return Nothing
        End If
        Return v1.Value << v2
    End Operator
    Public Shared Operator >>(ByVal v1 As IntegerNullable, _
			  ByVal v2 As Integer) As IntegerNullable
        If v1.HasValue = False Then
            Return Nothing
        End If
        Return v1.Value >> v2
    End Operator

    ''' <summary>
    ''' Sobrecarga del operador de concatenación
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' Esto solo es necesario para concatenar dos valores de este tipo
    ''' </remarks>
    Public Shared Operator &(ByVal v1 As IntegerNullable, ByVal v2 As IntegerNullable) As String
        Return v1.valor.ToString & v2.valor.ToString
    End Operator


    '
    ' Operadores de comparaciones
    '
    '''' <summary>
    '''' Los operadores lógicos
    '''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    '''' <returns></returns>
    '''' <remarks></remarks>
    Public Shared Operator =(ByVal v1 As IntegerNullable, ByVal v2 As IntegerNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return True
        End If

        Return CType(v2, IntegerNullable).GetValueOrDefault() = v1.GetValueOrDefault()
    End Operator
    Public Shared Operator <>(ByVal v1 As IntegerNullable, ByVal v2 As IntegerNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return CType(v2, IntegerNullable).GetValueOrDefault() <> v1.GetValueOrDefault()
    End Operator

    Public Shared Operator <(ByVal v1 As IntegerNullable, ByVal v2 As IntegerNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return v1.GetValueOrDefault() < CType(v2, IntegerNullable).GetValueOrDefault()
    End Operator
    Public Shared Operator >(ByVal v1 As IntegerNullable, ByVal v2 As IntegerNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return v1.GetValueOrDefault() > CType(v2, IntegerNullable).GetValueOrDefault()
    End Operator

    Public Shared Operator <=(ByVal v1 As IntegerNullable, ByVal v2 As IntegerNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return v1.GetValueOrDefault() <= CType(v2, IntegerNullable).GetValueOrDefault()
    End Operator
    Public Shared Operator >=(ByVal v1 As IntegerNullable, ByVal v2 As IntegerNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return v1.GetValueOrDefault() >= CType(v2, IntegerNullable).GetValueOrDefault()
    End Operator

    '
    ' Operadores de manejos de bits (lógicos)
    '

    ''' <summary>
    ''' Sobrecarga de And y AndAlso, ya que tenemos definido IsFalse
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator And(ByVal v1 As IntegerNullable, _
			   ByVal v2 As IntegerNullable) As IntegerNullable
        'Return New IntegerNullable(v1.Value And v2.Value)
        Return v1.Value And v2.Value
    End Operator

    ''' <summary>
    ''' Sobrecarga de Or y OrElse, ya que tenemos definido IsTrue
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator Or(ByVal v1 As IntegerNullable, _
			  ByVal v2 As IntegerNullable) As IntegerNullable
        'Return New IntegerNullable(v1.Value Or v2.Value)
        Return v1.Value Or v2.Value
    End Operator

    ''' <summary>
    ''' Sobrecarga de Xor
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator Xor(ByVal v1 As IntegerNullable, _
			   ByVal v2 As IntegerNullable) As IntegerNullable
        'Return New IntegerNullable(v1.Value Xor v2.Value)
        Return v1.Value Xor v2.Value
    End Operator

    ''' <summary>
    ''' Sobrecarga del operador Not, actúa directamente con el valor interno
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator Not(ByVal v As IntegerNullable) As IntegerNullable
        'Return New IntegerNullable(Not v.Value)
        Return Not v.Value
    End Operator

    ''' <summary>
    ''' Método compartido equivalente al operador Not de Visual Basic.
    ''' <summary>
    ''' <param name="v"></param>
    ''' <returns><returns>
    ''' <remarks><remarks>
    Public Shared Function [Not](ByVal v As IntegerNullable) As IntegerNullable
        Return Not v.Value
    End Function

    '
    ' Operadores unarios (+ y -)
    '
    Public Shared Operator +(ByVal v As IntegerNullable) As IntegerNullable
        Return +v.Value
    End Operator
    Public Shared Operator -(ByVal v As IntegerNullable) As IntegerNullable
        Return -v.Value
    End Operator


    ''' <summary>
    ''' Operadores para valores boolean (True y False)
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator IsTrue(ByVal v As IntegerNullable) As Boolean
        If v.HasValue Then
            Return True
        Else
            Return False
        End If
    End Operator
    Public Shared Operator IsFalse(ByVal v As IntegerNullable) As Boolean
        If v.HasValue Then
            Return False
        Else
            Return True
        End If
    End Operator

    '
    ' Métodos de instancia
    '
    ''' <summary>
    ''' Devuelve el valor que contiene o el valor por defecto
    ''' </summary>
    ''' <param name="defaultValue"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' Si el valor contenido es nulo, devolverá el predeterminado de Integer: cero
    ''' </remarks>
    Public Function GetValueOrDefault(ByVal defaultValue As Integer) As Integer
        Return valor.GetValueOrDefault(defaultValue)
    End Function
    Public Function GetValueOrDefault() As Integer
        Return valor.GetValueOrDefault()
    End Function

    ''' <summary>
    ''' Comprueba si tiene algún valor
    ''' </summary>
    ''' <value></value>
    ''' <returns>True si tiene un valor o False si es nulo</returns>
    ''' <remarks></remarks>
    Public ReadOnly Property HasValue() As Boolean
        Get
            Return valor.HasValue
        End Get
    End Property

    ''' <summary>
    ''' Devuelve el valor interno
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Value() As Integer
        Get
            If valor.HasValue = False Then
                Return Nothing
            End If
            Return valor.Value
        End Get
    End Property

    ''' <summary>
    ''' Sobrecarga del método ToString algo que SIEMPRE deberíamos hacer.
    ''' </summary>
    ''' <returns>
    ''' Devuelve una cadena con el valor o la palabra Nothing si contiene un valor nulo
    ''' </returns>
    ''' <remarks></remarks>
    Public Overrides Function ToString() As String
        If valor.HasValue = False Then
            Return "Nothing"
        End If
        Return valor.GetValueOrDefault().ToString()
    End Function
End Structure

 

 

La clase DoubleNullable

'------------------------------------------------------------------------------
' DoubleNullable                                                    (12/Abr/06)
' Estructura para simular el tipo Double? de VB 9.0 o double? de C# 2.0
'
' ©Guillermo 'guille' Som, 2006
'------------------------------------------------------------------------------

Imports Microsoft.VisualBasic
Imports System

''' <summary>
''' Estructura del tipo Nullable(Of Double)
''' Con sobrecargas para facilitar el trabajo con este tipo de números.
''' Así se podrá usar como Double? de VB 9.0
''' </summary>
''' <remarks></remarks>
Public Structure DoubleNullable

    ''' <summary>
    ''' Campo del tipo Nullable(Of Double)
    ''' </summary>
    ''' <remarks>Este campo es el que realmente contiene el valor.</remarks>
    Private valor As Nullable(Of Double)

    ''' <summary>
    ''' Propiedad compartida de solo lectura para asignar un valor nulo
    ''' </summary>
    ''' <value></value>
    ''' <returns>Nothing (null)</returns>
    ''' <remarks>
    ''' Es por si se usa en C#, ya que no podremos asignarle directamente un valor null.
    ''' </remarks>
    Public Shared ReadOnly Property Null() As DoubleNullable
        Get
            Return Nothing
        End Get
    End Property

    ''' <summary>
    ''' El constructor parametrizado para crear un valor indicando un valor entero
    ''' </summary>
    ''' <param name="v"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal v As Double)
        valor = v
    End Sub

    '
    ' Las conversiones
    '
    ''' <summary>
    ''' Conversión implícita de Double a DoubleNullable
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Widening Operator CType(ByVal v As Double) As DoubleNullable
        Return New DoubleNullable(v)
    End Operator

    ''' <summary>
    ''' Conversión implícita de DoubleNullable a Double
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Widening Operator CType(ByVal v As DoubleNullable) As Double
        Return v.GetValueOrDefault()
    End Operator

    ''' <summary>
    ''' Convertir los demás tipos a DoubleNullable sin pérdida de información
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Widening Operator CType(ByVal v As SByteNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As ByteNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As ShortNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As UShortNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As IntegerNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As UIntegerNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As LongNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As ULongNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As DecimalNullable) As DoubleNullable
        Return v.Value
    End Operator

    Public Shared Widening Operator CType(ByVal v As SingleNullable) As DoubleNullable
        Return v.Value
    End Operator

    '
    ' Conversiones explícitas desde DoubleNullable al resto de tipos de esta DLL
    '
    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As ByteNullable
        Return CByte(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As SByteNullable
        Return CSByte(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As ShortNullable
        Return CShort(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As UShortNullable
        Return CUShort(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As IntegerNullable
        Return CInt(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As UIntegerNullable
        Return CUInt(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As LongNullable
        Return CLng(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As ULongNullable
        Return CULng(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As DecimalNullable
        Return CDec(v.Value)
    End Operator

    Public Shared Narrowing Operator CType(ByVal v As DoubleNullable) As SingleNullable
        Return CSng(v.Value)
    End Operator


    '
    ' Los operadores aritméticos
    '
    ''' <summary>
    ''' Los operadores aritméticos
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator +(ByVal v1 As DoubleNullable, _
			 ByVal v2 As DoubleNullable) As DoubleNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return New DoubleNullable(v1.Value + v2.Value)
    End Operator

    Public Shared Operator -(ByVal v1 As DoubleNullable, _
			 ByVal v2 As DoubleNullable) As DoubleNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return New DoubleNullable(v1.Value - v2.Value)
    End Operator

    Public Shared Operator *(ByVal v1 As DoubleNullable, _
			 ByVal v2 As DoubleNullable) As DoubleNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return New DoubleNullable(v1.Value * v2.Value)
    End Operator

    Public Shared Operator \(ByVal v1 As DoubleNullable, _
			 ByVal v2 As DoubleNullable) As DoubleNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return New DoubleNullable(CLng(v1.Value) \ CLng(v2.Value))
    End Operator

    Public Shared Operator /(ByVal v1 As DoubleNullable, _
			 ByVal v2 As DoubleNullable) As DoubleNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return v1.Value / v2.Value
    End Operator

    Public Shared Operator ^(ByVal v1 As DoubleNullable, _
			 ByVal v2 As DoubleNullable) As DoubleNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return v1.Value ^ v2.Value
    End Operator

    ''' <summary>
    ''' Elevar un valor a una potencia, equivalente al operador ^ de Visual Basic.
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function Pow(ByVal v1 As DoubleNullable, _
			   ByVal v2 As DoubleNullable) As DoubleNullable
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return Nothing
        End If
        Return v1.Value ^ v2.Value
    End Function

    ''' <summary>
    ''' Método de instancia para elevar el valor actual a una potencia.
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Pow(ByVal v As DoubleNullable) As DoubleNullable
        If Me.HasValue = False OrElse v.HasValue = False Then
            Return Nothing
        End If
        Return Me.Value ^ v.Value
    End

    ''' <summary>
    ''' Sobrecarga de Mod
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator Mod(ByVal v1 As DoubleNullable, _
			   ByVal v2 As DoubleNullable) As DoubleNullable
        Return v1.Value Mod v2.Value
    End Operator


    ''' <summary>
    ''' Desplazamiento de bits
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator <<(ByVal v1 As DoubleNullable, ByVal v2 As Integer) As DoubleNullable
        If v1.HasValue = False Then
            Return Nothing
        End If
        Return CLng(v1.Value) << v2
    End Operator
    Public Shared Operator >>(ByVal v1 As DoubleNullable, ByVal v2 As Integer) As DoubleNullable
        If v1.HasValue = False Then
            Return Nothing
        End If
        Return CLng(v1.Value) >> v2
    End Operator

    ''' <summary>
    ''' Sobrecarga del operador de concatenación
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' Esto solo es necesario para concatenar dos valores de este tipo
    ''' </remarks>
    Public Shared Operator &(ByVal v1 As DoubleNullable, ByVal v2 As DoubleNullable) As String
        Return v1.valor.ToString & v2.valor.ToString
    End Operator


    ''' <summary>
    ''' Los operadores lógicos
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator =(ByVal v1 As DoubleNullable, ByVal v2 As DoubleNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return True
        End If

        Return CType(v2, DoubleNullable).GetValueOrDefault() = v1.GetValueOrDefault()
    End Operator
    Public Shared Operator <>(ByVal v1 As DoubleNullable, ByVal v2 As DoubleNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return CType(v2, DoubleNullable).GetValueOrDefault() <> v1.GetValueOrDefault()
    End Operator

    Public Shared Operator <(ByVal v1 As DoubleNullable, ByVal v2 As DoubleNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return v1.GetValueOrDefault() < CType(v2, DoubleNullable).GetValueOrDefault()
    End Operator
    Public Shared Operator >(ByVal v1 As DoubleNullable, ByVal v2 As DoubleNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return v1.GetValueOrDefault() > CType(v2, DoubleNullable).GetValueOrDefault()
    End Operator

    Public Shared Operator <=(ByVal v1 As DoubleNullable, ByVal v2 As DoubleNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return v1.GetValueOrDefault() <= CType(v2, IntegerNullable).GetValueOrDefault()
    End Operator
    Public Shared Operator >=(ByVal v1 As DoubleNullable, ByVal v2 As DoubleNullable) As Boolean
        If v1.HasValue = False OrElse v2.HasValue = False Then
            Return False
        End If

        Return v1.GetValueOrDefault() >= CType(v2, IntegerNullable).GetValueOrDefault()
    End Operator

    '
    ' Operadores de manejos de bits (lógicos)
    '

    ''' <summary>
    ''' Sobrecarga de And y AndAlso, ya que tenemos definido IsFalse
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator And(ByVal v1 As DoubleNullable, _
			   ByVal v2 As DoubleNullable) As LongNullable
        'Return New IntegerNullable(v1.Value And v2.Value)
        Return CLng(v1.Value) And CLng(v2.Value)
    End Operator

    ''' <summary>
    ''' Sobrecarga de Or y OrElse, ya que tenemos definido IsTrue
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator Or(ByVal v1 As DoubleNullable, _
			  ByVal v2 As DoubleNullable) As LongNullable
        'Return New IntegerNullable(v1.Value Or v2.Value)
        Return CLng(v1.Value) Or CLng(v2.Value)
    End Operator

    ''' <summary>
    ''' Sobrecarga de Xor
    ''' </summary>
    ''' <param name="v1"></param>
    ''' <param name="v2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator Xor(ByVal v1 As DoubleNullable, _
			   ByVal v2 As DoubleNullable) As LongNullable
        'Return New IntegerNullable(v1.Value Xor v2.Value)
        Return CLng(v1.Value) Xor CLng(v2.Value)
    End Operator

    ''' <summary>
    ''' Sobrecarga del operador Not, actúa directamente con el valor interno
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator Not(ByVal v As DoubleNullable) As LongNullable
        'Return New IntegerNullable(Not v.Value)
        Return Not CLng(v.Value)
    End Operator

    ''' <summary>
    ''' Método compartido equivalente al operador Not de Visual Basic.
    ''' </summary>
    ''' <param name="v">Valor de tipo DoubleNullable</param>"
    ''' <returns>Devuelve un valor de tipo LongNullable</returns>
    ''' <remarks></remarks>
    Public Shared Function [Not](ByVal v As DoubleNullable) As LongNullable
        Return Not CLng(v.Value)
    End Function

    '
    ' Operadores unarios (+ y -)
    '
    Public Shared Operator +(ByVal v As DoubleNullable) As DoubleNullable
        Return +v.Value
    End Operator
    Public Shared Operator -(ByVal v As DoubleNullable) As DoubleNullable
        Return -v.Value
    End Operator



    ''' <summary>
    ''' Operadores para valores boolean (True y False)
    ''' </summary>
    ''' <param name="v"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Operator IsTrue(ByVal v As DoubleNullable) As Boolean
        If v.HasValue Then
            Return True
        Else
            Return False
        End If
    End Operator
    Public Shared Operator IsFalse(ByVal v As DoubleNullable) As Boolean
        If v.HasValue Then
            Return False
        Else
            Return True
        End If
    End Operator

    '
    ' Métodos de instancia
    '
    ''' <summary>
    ''' Devuelve el valor que contiene o el valor por defecto
    ''' </summary>
    ''' <param name="defaultValue"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' Si el valor contenido es nulo, devolverá el predeterminado de Double: cero
    ''' </remarks>
    Public Function GetValueOrDefault(ByVal defaultValue As Double) As Double
        Return valor.GetValueOrDefault(defaultValue)
    End Function
    Public Function GetValueOrDefault() As Double
        Return valor.GetValueOrDefault()
    End Function

    ''' <summary>
    ''' Comprueba si tiene algún valor
    ''' </summary>
    ''' <value></value>
    ''' <returns>True si tiene un valor o False si es nulo</returns>
    ''' <remarks></remarks>
    Public ReadOnly Property HasValue() As Boolean
        Get
            Return valor.HasValue
        End Get
    End Property

    ''' <summary>
    ''' Devuelve el valor interno
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Value() As Double
        Get
            If valor.HasValue = False Then
                Return Nothing
            End If
            Return valor.Value
        End Get
    End Property

    ''' <summary>
    ''' Sobrecarga del método ToString algo que SIEMPRE deberíamos hacer.
    ''' </summary>
    ''' <returns>
    ''' Devuelve una cadena con el valor o la palabra Nothing si contiene un valor nulo
    ''' </returns>
    ''' <remarks></remarks>
    Public Overrides Function ToString() As String
        If valor.HasValue = False Then
            Return "Nothing"
        End If
        Return valor.GetValueOrDefault().ToString()
    End Function
End Structure

 



 


La fecha/hora en el servidor es: 12/10/2024 10:45:53

La fecha actual GMT (UTC) es: 

©Guillermo 'guille' Som, 1996-2024