Pues eso… y por si no lo sabes, esto de los métodos de extensión (Extension Methods en inglés) sirve para ampliar la funcionalidad de clases existentes, ya sean definidas en el propio .NET (String, Integer, TextBox, etc.) como en otras librerías (bibliotecas) que tengamos referenciadas en nuestro proyecto.
NOTA:
Aquí no te voy a explicar en detalle de qué va esto de los métodos de extensión, solo decirte cómo crear los tuyos propios, con código de Visual Basic y de C#, para ello te pondré unos ejemplos.
NOTA2:
¡Vaya despiste!
Pues eso… que se ve que en septiembre del año pasado (5-sep-2019) ya publiqué algo sobre los métodos de extensión… y es que lo tenía apuntado (en mi cabeza) y se ve que después de publicarlo no lo borré… jajaja… en fin… Más vale 2 que nada… 😉
En este artículo voy a ponerte un par de ejemplos para añadir una nueva función a la clase String y algunos métodos de conversión a la clase TextBox, de forma que puedas usarlos para convertir el contenido de la propiedad Text en un valor entero, un valor decimal, etc.
Crear métodos de extensión en Visual Basic
En Visual Basic necesitamos una importación a System.Runtime.CompilerServices y crear los métodos en un módulo (no se pueden crear en clases).
La definición del método empezará con el atributo <Extension> y después seguirá la definición de la función ( o método), pero en el primer parámetro indicaremos la clase que queremos ampliar (o extender) y después, opcionalmente, podemos usar más parámetros.
Crear método de extensión en C#
Para crear métodos de extensión en C# necesitamos una clase definida como static y definir los métodos de extensión también como compartidos (static), pero no es necesario usar la importación de CompilerServices ni añadir el atributo Extension, ya que el compilador sabe que es un método de extensión si el primer argumento de la función (o método) empieza con this y el tipo que queremos extender.
Un par de ejemplos de métodos de extensión
En el siguiente código tenemos un par de ejemplos de métodos de extensión de la clase String, el primero como función y el segundo como un método que no devuelve nada.
Primero el código de Visual Basic y después el de C#.
Imports System.Runtime.CompilerServices
Module Extensiones
<Extension>
Public Function Prueba(str As String) As String
Return "PRUEBA " & str
End Function
<Extension>
Public Sub Imprimir(str As String)
Console.WriteLine(str)
End Sub
End Module
static class Extensiones
{
//[Extension]
public static string Prueba(this string str)
{
return "PRUEBA " + str;
}
public static void Imprimir(this string str)
{
Console.WriteLine(str);
}
Algunos métodos prácticos para extender String y TextBox
Aquí te dejo el código para extender la clase String con un método que quita las tildes (acentos) a las vocales, con idea de que podamos hacer comparaciones sin que se tenga en cuenta si la vocal está o no acentuada (con la tilde).
En el caso del control TextBox te dejo los métodos de extensión para convertir el contenido en un valor de tipo Integer, Double, Decimal, Date y TimeSpan.
Esto lo empecé a usar en el último programa que he hecho, hasta ahora, cuando quería convertir el contenido de una cadena en un valor numérico, etc., lo que hacía era usar funciones para esas conversiones.
Esas conversiones podría haberlas puesto en la clase String, pero al hacerla en el TextBox me ahorraba tener que indicar la propiedad Text cada vez que quería hacer la conversión 😉
En el código de ejemplo te pongo también la función que convierte en número entero para la clase String, así lo tendrás fácil si quieres extender dicha clase en lugar del TextBox.
El código para Visual Basic
Primero los métodos de extensión y después cómo usarlos.
Imports System
Imports System.Runtime.CompilerServices
Imports System.Windows.Forms
Module Extensiones
''' <summary>
''' Devuelve un valor Integer de la propiedad Text del TextBox indicado.
''' </summary>
''' <param name="txt">El TextBox a extender</param>
<Extension>
Public Function AsInteger(txt As TextBox) As Integer
Dim i As Integer = 0
Integer.TryParse(txt.Text, i)
Return i
End Function
''' <summary>
''' Devuelve un valor Double de la propiedad Text del TextBox indicado.
''' </summary>
<Extension>
Public Function AsDouble(txt As TextBox) As Double
Dim d As Double = 0
Double.TryParse(txt.Text, d)
Return d
End Function
''' <summary>
''' Devuelve un valor Decimal de la propiedad Text del TextBox indicado.
''' </summary>
<Extension>
Public Function AsDecimal(txt As TextBox) As Decimal
Dim d As Decimal = 0
Decimal.TryParse(txt.Text, d)
Return d
End Function
''' <summary>
''' Devuelve un valor TimeSpan de la propiedad Text del TextBox indicado.
''' </summary>
<Extension>
Public Function AsTimeSpan(txt As TextBox) As TimeSpan
Dim c As New TimeSpan(0, 0, 0)
TimeSpan.TryParse(txt.Text, c)
Return c
End Function
''' <summary>
''' Devuelve un valor Date de la propiedad Text del TextBox indicado.
''' Si es un valor nulo o vacío, devuelve el 1 de enero de 1900.
''' </summary>
<Extension>
Public Function AsDate(txt As TextBox) As Date
Dim d As DateTime = New DateTime(1900, 1, 1)
If Not (String.IsNullOrWhiteSpace(txt.Text) OrElse txt.Text.Equals(DBNull.Value)) Then
DateTime.TryParse(txt.Text, d)
If d.Year < 1900 Then
d = New DateTime(1900, 1, 1, 0, 0, 0)
End If
Else
' asignar el 01/01/1900 si es un valor en blanco
d = New DateTime(1900, 1, 1, 0, 0, 0)
End If
Return d.Date
End Function
''' <summary>
''' Quitar las tildes de una cadena.
''' </summary>
''' <param name="str">La cadena a extender</param>
<Extension>
Public Function QuitarTildes(ByVal str As String) As String
Dim tildes1 = "ÁÉÍÓÚáéíóú"
Dim tildes0 = "AEIOUaeiou"
Dim res As New System.Text.StringBuilder
For i = 0 To str.Length - 1
Dim j = tildes1.IndexOf(str(i))
If j > -1 Then
res.Append(tildes0.Substring(j, 1))
Else
res.Append(str(i))
End If
Next
Return res.ToString
End Function
''' <summary>
''' Devuelve un valor Integer de la cadena a la que se aplica este método.
''' </summary>
<Extension>
Public Function AsInteger(str As String) As Integer
Dim i As Integer = 0
Integer.TryParse(str, i)
Return i
End Function
<Extension>
Public Function Prueba(str As String) As String
Return "PRUEBA " & str
End Function
<Extension>
Public Sub Imprimir(str As String)
Console.WriteLine(str)
End Sub
End Module
Imports System
Imports System.Windows.Forms
Module Module1
Sub Main()
Dim s = "Hola"
Console.WriteLine(s.Prueba)
s.Imprimir()
s = "Código de ejemplos prácticos"
Console.WriteLine(s.QuitarTildes())
Dim txt As New TextBox
txt.Text = "125"
Console.WriteLine("txt.Text : {0}", txt.Text)
Console.WriteLine("txt.Text.AsInteger+10 : {0}", txt.Text.AsInteger + 10)
Console.WriteLine("txt.AsInteger+10 : {0}", txt.AsInteger + 10)
txt.Text = "125,38"
Console.WriteLine("txt.Text : {0}", txt.Text)
Console.WriteLine("txt.AsDecimal*2 : {0}", txt.AsDecimal * 2)
Console.WriteLine("txt.AsDouble*2 : {0}", txt.AsDouble * 2)
txt.Text = "10:30"
Console.WriteLine("txt.Text : {0}", txt.Text)
Console.WriteLine("txt.AsTimeSpan : {0}", txt.AsTimeSpan)
txt.Text = "24/08/2020"
Console.WriteLine("txt.Text : {0}", txt.Text)
Console.WriteLine("txt.AsDate : {0}", txt.AsDate)
Console.WriteLine("txt.AsDate.AddDays(2) : {0}", txt.AsDate.AddDays(2))
Console.ReadKey()
End Sub
End Module
El código para C#
Primero los métodos de extensión y después cómo usarlos.
using System;
using System.Windows.Forms;
static class Extensiones
{
//[Extension]
public static string Prueba(this string str)
{
return "PRUEBA " + str;
}
public static void Imprimir(this string str)
{
Console.WriteLine(str);
}
/// <summary>
/// Devuelve un valor Integer de la propiedad Text del TextBox indicado.
/// </summary>
/// <param name="txt">El TextBox a extender</param>
public static int AsInteger(this TextBox txt)
{
int i = 0;
int.TryParse(txt.Text, out i);
return i;
}
/// <summary>
/// Devuelve un valor Double de la propiedad Text del TextBox indicado.
/// </summary>
public static double AsDouble(this TextBox txt)
{
double d = 0;
double.TryParse(txt.Text, out d);
return d;
}
/// <summary>
/// Devuelve un valor Decimal de la propiedad Text del TextBox indicado.
/// </summary>
public static decimal AsDecimal(this TextBox txt)
{
decimal d = 0;
decimal.TryParse(txt.Text, out d);
return d;
}
/// <summary>
/// Devuelve un valor TimeSpan de la propiedad Text del TextBox indicado.
/// </summary>
public static TimeSpan AsTimeSpan(this TextBox txt)
{
TimeSpan c = new TimeSpan(0, 0, 0);
TimeSpan.TryParse(txt.Text, out c);
return c;
}
/// <summary>
/// Devuelve un valor Date de la propiedad Text del TextBox indicado.
/// Si es un valor nulo o vacío, devuelve el 1 de enero de 1900.
/// </summary>
public static DateTime AsDate(this TextBox txt)
{
DateTime d = new DateTime(1900, 1, 1);
if (!(string.IsNullOrWhiteSpace(txt.Text) || txt.Text.Equals(DBNull.Value)))
{
DateTime.TryParse(txt.Text, out d);
if (d.Year < 1900)
d = new DateTime(1900, 1, 1, 0, 0, 0);
}
else
// asignar el 01/01/1900 si es un valor en blanco
d = new DateTime(1900, 1, 1, 0, 0, 0);
return d.Date;
}
/// <summary>
/// Quitar las tildes de una cadena.
/// </summary>
/// <param name="str">La cadena a extender</param>
public static string QuitarTildes(this string str)
{
var tildes1 = "ÁÉÍÓÚáéíóú";
var tildes0 = "AEIOUaeiou";
System.Text.StringBuilder res = new System.Text.StringBuilder();
for (var i = 0; i <= str.Length - 1; i++)
{
var j = tildes1.IndexOf(str[i]);
if (j > -1)
res.Append(tildes0.Substring(j, 1));
else
res.Append(str[i]);
}
return res.ToString();
}
/// <summary>
/// Devuelve un valor Integer de la cadena a la que se aplica este método.
/// </summary>
public static int AsInteger(this string str)
{
int i = 0;
int.TryParse(str, out i);
return i;
}
}
using System;
using System.Windows.Forms;
class Program
{
static void Main(string[] args)
{
var s = "Hola";
Console.WriteLine(s.Prueba());
//Console.WriteLine(s.Prueba2());
s.Imprimir();
s = "Código de ejemplos prácticos";
Console.WriteLine(s.QuitarTildes());
TextBox txt = new TextBox();
txt.Text = "125";
Console.WriteLine("txt.Text : {0}", txt.Text);
Console.WriteLine("txt.Text.AsInteger+10 : {0}", txt.Text.AsInteger() + 10);
Console.WriteLine("txt.AsInteger+10 : {0}", txt.AsInteger() + 10);
txt.Text = "125,38";
Console.WriteLine("txt.Text : {0}", txt.Text);
Console.WriteLine("txt.AsDecimal*2 : {0}", txt.AsDecimal() * 2);
Console.WriteLine("txt.AsDouble*2 : {0}", txt.AsDouble() * 2);
txt.Text = "10:30";
Console.WriteLine("txt.Text : {0}", txt.Text);
Console.WriteLine("txt.AsTimeSpan : {0}", txt.AsTimeSpan());
txt.Text = "24/08/2020";
Console.WriteLine("txt.Text : {0}", txt.Text);
Console.WriteLine("txt.AsDate : {0}", txt.AsDate());
Console.WriteLine("txt.AsDate.AddDays(2) : {0}", txt.AsDate().AddDays(2));
Console.ReadKey();
}
//Error CS1106: Un método de extensión debe definirse en una clase estática no genérica
//public static string Prueba2(this string str)
//{
// return "PRUEBA2 " + str;
//}
}
Y esto es todo… espero que te haya sido de utilidad… ya sabes que esa es la idea 😉
Nos vemos.
Guillermo