You are on page 1of 43

Mtodos y parmetros

Contenido Notas generales Uso de mtodos Uso de parmetros Uso de mtodos sobrecargados 1 2 16 29

Mtodos y parmetros

Notas para el instructor


Este mdulo explica el uso de mtodos, parmetros y mtodos sobrecargados. Tambin explica que es recomendable descomponer la lgica del programa en unidades funcionales, ya que facilita la reutilizacin del cdigo. El mdulo comienza explicando qu son los mtodos, cmo se crean y cmo se pueden hacer llamadas a mtodos. A continuacin se discuten brevemente los modificadores de acceso private y public (que se tratarn con ms detalle en mdulos posteriores). El mdulo concluye con una explicacin de la sobrecarga de mtodos y las reglas sobre signaturas de mtodos. Este mdulo sienta tambin las bases para los temas sobre encapsulacin, que se tratar en un mdulo posterior. Al final de este mdulo, los estudiantes sern capaces de: Crear mtodos estticos que aceptan parmetros y devuelven valores. Pasar parmetros a mtodos utilizando distintos mecanismos. Seguir reglas de mbito para variables y mtodos.

Mtodos y parmetros

Notas generales
Objetivo del tema
Ofrecer una introduccin a los contenidos y objetivos del mdulo.

Explicacin previa

Uso de mtodos Uso de parmetros Uso de mtodos sobrecargados

En este mdulo aprender cmo usar mtodos en C#, cmo se pasan parmetros y cmo se devuelven valores.

Para su informacin

Este mdulo describe la sintaxis bsica para el uso de mtodos en C#, pero no incluye una discusin completa de conceptos orientados a objetos como la encapsulacin y el ocultamiento de informacin. En particular, este mdulo discute los mdulos estticos pero no los mtodos de instancia. Para parmetros y valores devueltos se utilizarn nicamente tipos valor, ya que todava no se han tratado los tipos de referencia.

Uno de los principios bsicos del diseo de aplicaciones es que deben estar divididas en unidades funcionales, ya que las secciones pequeas de cdigo son ms fciles de entender, disear, desarrollar y depurar. La divisin de una aplicacin en unidades funcionales permite tambin la reutilizacin de componentes funcionales en toda la aplicacin. Una aplicacin C# est estructurada en clases que contienen bloques de cdigo con nombre llamados mtodos. Un mtodo es un miembro de una clase que lleva a cabo una accin o calcula un valor. Al final de este mdulo, usted ser capaz de: Crear mtodos estticos que aceptan parmetros y devuelven valores. Pasar parmetros a mtodos de distintas maneras. Declarar y usar mtodos sobrecargados.

Mtodos y parmetros

Uso de mtodos
Objetivo del tema
Ofrecer una introduccin a los temas tratados en esta seccin.

Explicacin previa

Definicin de mtodos Llamadas a mtodos Uso de la instruccin return Uso de variables locales Devolucin de valores

En esta seccin estudiar el uso de mtodos en C#.

En esta seccin estudiar el uso de mtodos en C#. Los mtodos son un mecanismo importante para estructurar el cdigo de un programa. Aprender cmo se crean y cmo se pueden hacer llamadas a mtodos desde una sola clase y desde una clase a otra. Tambin aprender a usar variables locales, as como a asignarlas y destruirlas. Finalmente, aprender a devolver un valor desde un mtodo y a utilizar parmetros para transferir datos a un mtodo o extraerlos de l.

Mtodos y parmetros

Definicin de mtodos
Objetivo del tema
Mostrar la sintaxis para la definicin de mtodos simples.

Explicacin previa

Main es un mtodo

Esta transparencia muestra cmo definir un mtodo simple.

Para definir mtodos propios se usa la misma sintaxis

using using System; System; class class ExampleClass ExampleClass { { static static void void ExampleMethod( ExampleMethod( ) ) { { Console.WriteLine("ExampleMethod"); Console.WriteLine("ExampleMethod"); } } static static void void Main( Main( ) ) { { // // ... ... } } } }

Recomendacin al profesor

No entre por el momento en explicaciones detalladas sobre el significado de static, void o la lista de parmetros vaca. Lo ms importante que hay que recordar es que un mtodo pertenece a una clase, que tiene un nombre y que contiene un bloque de cdigo.

Un mtodo es una serie de instrucciones C# que han sido agrupadas bajo un nombre determinado. La mayor parte de los lenguajes de programacin modernos incluyen un concepto similar; se puede considerar que un mtodo es equivalente a una funcin, una subrutina, un procedimiento o un subprograma.

Ejemplos de mtodos
El cdigo mostrado en la transparencia contiene tres mtodos: El mtodo Main El mtodo WriteLine El mtodo ExampleMethod El mtodo Main es el punto de entrada de la aplicacin, mientras que WriteLine forma parte de Microsoft .NET Framework y se puede llamar desde un programa. El mtodo WriteLine es un mtodo esttico de la clase System.Console. El mtodo ExampleMethod pertenece a ExampleMethod y contiene una llamada al mtodo WriteLine. Todos los mtodos en C# pertenecen a una clase, al contrario de lo que ocurre en otros lenguajes de programacin como C, C++ y Microsoft Visual Basic, que permiten subrutinas y funciones globales.

Mtodos y parmetros

Creacin de mtodos
Cuando se crea un mtodo hay que especificar lo siguiente: Nombre Un mtodo no puede tener el mismo nombre que una variable, una constante o cualquier otro elemento que no sea un cdigo y haya sido declarado en la clase. El nombre del mtodo puede ser cualquier identificador permitido de C# y distingue entre maysculas y minsculas. Lista de parmetros A continuacin del nombre del mtodo viene una lista de parmetros para el mtodo. Esta lista aparece entre parntesis que deben estar presentes aunque no hay ningn parmetro, como se ve en los ejemplos de la transparencia. Cuerpo del mtodo Despus de los parntesis viene el cuerpo del mtodo, que debe estar entre llaves ({ y }) aunque no contenga ms que una instruccin.

Sintaxis para la definicin de mtodos


Para crear un mtodo se utiliza la siguiente sintaxis:
static void MethodName( ) { cuerpo del mtodo }

Recomendacin al profesor

El siguiente ejemplo muestra cmo crear un mtodo llamado ExampleMethod en la clase ExampleClass:
using System; class ExampleClass { static void ExampleMethod( ) { Console.WriteLine("Example method"); } static void Main( ) { Console.WriteLine("Main method"); } }

Por el momento, no dedique demasiado tiempo a hablar de las palabras clave static y void. La palabra clave void se tratar ms adelante en esta seccin, mientras que static se discutir en mdulos posteriores dedicados a conceptos orientados a objetos.

Nota C# distingue entre maysculas y minsculas en los nombres de mtodos, lo que permite declarar y usar mtodos cuyos nombres slo se diferencian en letras maysculas o minsculas. Por ejemplo, es posible declarar mtodos llamados print y PRINT en la misma clase. Sin embargo, el runtime de lenguaje comn requiere que los nombres de mtodos dentro de una clase se diferencien tambin en otros aspectos para garantizar la compatibilidad con otros lenguajes en los que los nombres de los mtodos no distinguen entre maysculas y minsculas. Esto es importante si se desea que una aplicacin interacte con otras aplicaciones escritas en lenguajes que no sean C#.

Mtodos y parmetros

Llamadas a mtodos
Objetivo del tema
Explicar cmo hacer una llamada a un mtodo simple.

Una vez definido un mtodo, se puede:


Explicacin previa

Una vez definido un mtodo, hay que saber cmo llamarlo.

Llamar a un mtodo desde dentro de la misma clase Se usa el nombre del mtodo seguido de una lista de parmetros entre parntesis Llamar a un mtodo que est en una clase diferente Hay que indicar al compilador cul es la clase que contiene el mtodo que se desea llamar El mtodo llamado se debe declarar con la palabra clave public Usar llamadas anidadas Unos mtodos pueden hacer llamadas a otros, que a su vez pueden llamar a otros mtodos, y as sucesivamente

Despus de definir un mtodo, es posible hacer llamadas a ese mtodo desde dentro de la misma clase y desde otras clases.

Llamadas a mtodos
Recomendacin al profesor
La sintaxis resultar familiar para los desarrolladores en C y C++. A los desarrolladores en Visual Basic puede indicarles que en C# no existe la instruccin Call y que hay que usar parntesis en todas las llamadas a mtodos.

Para hacer una llamada a un mtodo hay que emplear el nombre del mtodo seguido de una lista de parmetros entre parntesis. Los parntesis son obligatorios aunque el mtodo llamado no contenga ningn parmetro, como se ve en el siguiente ejemplo.
MethodName( );

Nota para los desarrolladores en Visual Basic La instruccin Call no existe. Los parntesis son obligatorios en todas las llamadas a mtodos.

Mtodos y parmetros

El programa del siguiente ejemplo comienza al principio del mtodo Main de ExampleClass. La primera instruccin muestra Comienza el programa. La segunda instruccin en Main es la llamada a ExampleClass. El flujo de control pasa a la primera instruccin en ExampleClass y aparece Hola, mundo. Al final del mtodo, el control pasa a la instruccin inmediatamente despus de la llamada al mtodo, que es la instruccin que muestra Termina el programa.
using System; class ExampleClass { static void ExampleClass( ) { Console.WriteLine("Hola, mundo"); } static void Main( ) { Console.WriteLine("Comienza el programa."); ExampleMethod( ); Console.WriteLine("Termina el programa."); } }

Llamadas a mtodos desde otras clases


Recomendacin al profesor Para que los mtodos de una clase puedan hacer llamadas a mtodos en otra clase hay que: Especificar la clase que contiene el mtodo que se desea llamar. Para especificar la clase que contiene el mtodo se utiliza la siguiente sintaxis:
ClassName.MethodName( );

Los contenidos de este tema estn simplificados. En un mdulo posterior se explicarn con detalle las palabras clave public, private, internal y protected. Lo nico que tiene que explicar por el momento es que los mtodos llamados desde una clase diferente tienen que estar declarados como public.

Declarar el mtodo llamado con la palabra clave public. El siguiente ejemplo muestra cmo hacer una llamada al mtodo TestMethod, que est definido en la clase A, desde Main en la clase B:
using System; class A { public static void TestMethod( ) { Console.WriteLine("Esto es TestMethod en clase A"); } } class B { static void Main( ) { A.TestMethod ( ); } }

Mtodos y parmetros

Si en el ejemplo anterior se eliminara el nombre de la clase, el compilador buscara un mtodo llamado TestMethod en la clase B. Puesto que en esa clase no hay ningn mtodo con ese nombre, el compilador mostrar el siguiente error: El nombre TestMethod no existe en la clase o espacio de nombres B. Un mtodo que no se declare como pblico es privado por defecto en la clase. Por ejemplo, si en la definicin de TestMethod se omite la palabra clave public, el compilador mostrar el siguiente error: A.TestMethod() no es accesible debido a su nivel de proteccin. Tambin se puede emplear la palabra clave private para indicar que slo es posible hacer llamadas al mtodo desde dentro de la clase. Estas dos lneas de cdigo tienen exactamente el mismo efecto, ya que los mtodos son privados por defecto:
private static void MyMethod( ); static void MyMethod( );

Las palabras clave public y private especifican la accesibilidad del mtodo. Estas palabras clave controlan si es posible hacer llamadas a un mtodo desde fuera de la clase en la que est definido.

Llamadas anidadas a mtodos


Tambin es posible hacer llamadas a mtodos desde dentro de mtodos. El siguiente ejemplo muestra cmo anidar llamadas a mtodos:
using System; class NestExample { static void Method1( ) { Console.WriteLine("Method1"); } static void Method2( ) { Method1( ); Console.WriteLine("Method2"); Method1( ); } static void Main( ) { Method2( ); Method1( ); } }

Mtodos y parmetros

La salida de este programa es la siguiente:


Method1 Method2 Method1 Method1

La anidacin permite hacer llamadas a un nmero ilimitado de mtodos. No hay ningn lmite predefinido para el nivel de anidacin. Sin embargo, el entorno de tiempo de ejecucin puede imponer lmites, normalmente debido a la cantidad de RAM disponible para ejecutar el proceso. Cada llamada a un mtodo necesita memoria para almacenar direcciones de retorno y otra informacin. Como regla general, si se agota la memoria para llamadas anidadas a mtodos se debe probablemente a problemas en el diseo de clases.

Mtodos y parmetros

Uso de la instruccin return


Objetivo del tema
Presentar la instruccin return y explicar cmo usarla al final de un mtodo.

Explicacin previa

Return inmediato Return con una instruccin condicional


static static void void ExampleMethod( ExampleMethod( ) ) { { int int numBeans; numBeans; //... //... Console.WriteLine("Hello"); Console.WriteLine("Hello"); if if (numBeans (numBeans < < 10) 10) return; return; Console.WriteLine("World"); Console.WriteLine("World");

Normalmente, la ejecucin de un mtodo se devuelve al llamador cuando se llega a la ltima instruccin del mtodo, excepto si se utiliza la instruccin return.

} }

Recomendacin al profesor

Esta resultar familiar para los programadores en C y C++. Para los programadores en Visual Basic, la instruccin return por s misma es equivalente a Exit Sub, Exit Function o Exit Property en Visual Basic.

La instruccin return se puede emplear para hacer que un mtodo se devuelva inmediatamente al llamador. Sin una instruccin return, lo normal es que la ejecucin se devuelva al llamador cuando se alcance la ltima instruccin del mtodo.

Return inmediato
Por defecto, un mtodo es devuelto a su llamador cuando se llega al final de la ltima instruccin del bloque de cdigo. La instruccin return se utiliza cuando se quiere que un mtodo sea devuelto inmediatamente al llamador. El mtodo del siguiente ejemplo muestra Hola, y es inmediatamente devuelto a su llamador:
static void ExampleMethod( ) { Console.WriteLine("Hola"); return; Console.WriteLine("mundo"); }

Este uso de la instruccin return no resulta muy til, ya que la llamada final a Console.WriteLine no se ejecuta nunca. Si los avisos del compilador de C# estn activados a nivel 2 o superior, el compilador mostrar el siguiente mensaje: Detectado cdigo inaccesible.

Mtodos y parmetros

10

Return con una instruccin condicional


Es mucho ms habitual, y mucho ms til, utilizar la instruccin return como parte de una instruccin condicional como if o switch. Esto permite que un mtodo sea devuelto al llamador si se cumple cierta condicin. El mtodo del siguiente ejemplo ser devuelto si la variable numBeans es menor que 10; en caso contrario, la ejecucin continuar dentro de este mdulo.
static void ExampleMethod( ) { int numBeans; //... Console.WriteLine("Hola"); if (numBeans < 10) return; Console.WriteLine("mundo"); }

Consejo En general se considera una buena prctica de programacin que un mtodo tenga un punto de entrada y otro de salida. El diseo de C# garantiza que la ejecucin de todos los mtodos comienza por la primera instruccin. Un mtodo sin ninguna instruccin return tiene un punto de salida al final del bloque de cdigo. Un mtodo con varias instrucciones return tiene mltiples puntos de salida, lo que en algunos casos puede hacer que el mtodo sea difcil de entender y mantener.

Return con un valor


Recomendacin al profesor
Los valores devueltos se discutirn ms adelante en este mdulo. Este prrafo se ha incluido aqu para anticiparse a las preguntas de los estudiantes sobre el tema.

Si un mtodo est definido con un tipo de datos en lugar de void, return se usa para asignar un valor a la funcin. Este punto se discutir ms adelante en este mdulo.

Mtodos y parmetros

11

Uso de variables locales


Objetivo del tema
Describir las variables locales y explicar cmo se crean y destruyen.

Explicacin previa

Variables locales

Cada mtodo tiene su propio conjunto de variables locales.

Se crean cuando comienza el mtodo Son privadas para el mtodo Se destruyen a la salida Para compartir se utilizan variables de clase El compilador no avisa si hay conflictos entre nombres locales y de clase

Variables compartidas

Conflictos de mbito

Cada mtodo tiene su propio conjunto de variables locales, que slo se pueden utilizar dentro del mtodo en el que estn declaradas. No es posible acceder a las variables locales desde ninguna otra parte de la aplicacin.

Variables locales
Se pueden incluir variables locales en el cuerpo de un mtodo, como se ve en el siguiente ejemplo:
static void MethodWithLocals( ) { int x = 1; // Variable con valor inicial ulong y; string z; ... }

Las variables locales pueden llevar asignado un valor inicial (como la variable x en el cdigo del ejemplo anterior). La variable no estar inicializada si no se le asigna un valor o si no tiene una expresin inicial para determinar un valor.

Mtodos y parmetros

12

Recomendacin al profesor

Las variables que se declaran en un mtodo son completamente independientes de las variables declaradas en otros mtodos, aunque sus nombres sean iguales. Cada vez que se hace una llamada a un mtodo se asigna memoria para variables locales, que se libera cuando termina el mtodo. Por lo tanto, los valores almacenados en estas variables no se conservan desde una llamada a un mtodo y la siguiente.

Esta aplicacin sobre asignacin y liberacin de memoria se refiere nicamente a tipos de valor. La administracin de memoria para tipos de referencia es ms compleja y se tratar en un mdulo posterior.

Mtodos y parmetros

13

Variables compartidas
El siguiente cdigo intenta contar el nmero de veces que ha sido llamado un mtodo: Recomendacin al profesor
class CallCounter_Bad { static void Init( ) { int nCount = 0; } static void CountCalls( ) { int nCount; ++nCount; Console.WriteLine("Mtodo llamado {0} veces", nCount); } static void Main( ) { Init( ); CountCalls( ); CountCalls( ); } }

Los desarrolladores experimentados en Visual Basic tal vez comenten que, en Visual Basic, poner static antes del nombre de un mtodo hace que todas las variables locales de ese mtodo tengan clase de almacenamiento esttico. Recuerde este hecho, aunque normalmente no ser necesario mencionarlo.

Este programa no se puede compilar debido a dos problemas importantes. La variable nCount en Inic no es la misma que la variable nCount en CountCalls. Independientemente del nmero de veces que se llame al mtodo CountCalls, el valor nCount se pierde cada vez que termina CountCalls. Para su informacin La forma correcta de escribir este cdigo es utilizando una variable de clase, como se muestra en el siguiente ejemplo:
class CallCounter_Good { static int nCount; static void Init( ) { nCount = 0; } static void CountCalls( ) { ++ nCount; Console.Write("Mtodo llamado " + nCuenta + " veces."); } static void Main( ) { Init( ); CountCalls( ); CountCalls( ); } }

ste es el comportamiento habitual de las variables locales en C, C++ y Visual Basic, por lo que no deberan surgir demasiados problemas.

En este ejemplo, nCount se declara como clase en vez de mtodo. Por lo tanto, nCount se comparte entre todos los mtodos de la clase.

Mtodos y parmetros

14

Conflictos de mbito
En C# se puede declarar una variable local con el mismo nombre que una variable de clase, aunque eso puede producir resultados inesperados. En el siguiente ejemplo, NumItems est declarada como una variable de clase ScopeDemo, y tambin como una variable local en Method1. Las dos variables son completamente distintas. En Method1, NumObjetos se refiere a la variable local, mientras que en Method2 se refiere a la variable de clase.
class ScopeDemo { static int numItems = 0; static void Method1( ) { int numItems = 42; ... } static void Method2( ) { numItems = 61; } }

Consejo El compilador de C# no indica si hay variables locales y variables de clase que tienen los mismos nombres, por lo que conviene adoptar una convencin de nomenclatura para distinguirlas unas variables de otras.

Mtodos y parmetros

15

Devolucin de valores
Explicar cmo utilizar la instruccin return para devolver valores.

Objetivo del tema

Explicacin previa

El mtodo se debe declarar con un tipo que no sea void Se aade una instruccin return con una expresin

La instruccin return se puede utilizar para devolver un valor desde un mtodo.

Fija el valor de retorno Se devuelve al llamador

Los mtodos que no son void deben devolver un valor


int int x; x; x x= = DosMasDos( DosMasDos( ); ); Console.WriteLine(x); Console.WriteLine(x);

static static int int DosMasDos( DosMasDos( ) ){ { int int a,b; a,b; a a= = 2; 2; b b= = 2; 2; return return a a+ + b; b; } }

Ya hemos aprendido a usar la instruccin return para hacer que un mtodo finalice inmediatamente. Tambin se puede utilizar la instruccin return para devolver un valor desde un mtodo. Para devolver un valor hay que: 1. Declarar el mtodo con el tipo del valor que se desea devolver. 2. Aadir al mtodo una instruccin return. 3. Incluir el valor que se desea devolver al llamador.

Declaracin de mtodos con un tipo que no sea void


Para declarar un mtodo de forma que devuelva un valor al llamador hay que cambiar la palabra clave void por el tipo del valor que se desea devolver.

Mtodos y parmetros

16

Uso de instrucciones return


Recomendacin al profesor La palabra clave return seguida de una expresin hace que el mtodo finalice inmediatamente y devuelve la expresin como valor de retorno del mtodo. El siguiente ejemplo muestra cmo declarar un mtodo llamado DosMasDos que devuelve el valor 4 a Main cuando hace una llamada a DosMasDos:
class ExampleReturningValue { static int DosMasDos( ) { int a,b; a = 2; b = 2; return a + b; } static void Main( ) { int x; x = DosMasDos( ); Console.WriteLine(x); } }

La instruccin return devuelve un valor al llamador inmediatamente. Lo mismo ocurre en C y C++. En Visual Basic, las funciones miembro devuelven un valor por asignacin al nombre de la funcin sin causar un return inmediato.

El valor devuelto es un int, ya que int es el tipo de retorno del mtodo. Cuando se hace una llamada al mtodo, ste devuelve el valor 4. En este ejemplo, el valor se almacena en la variable local x de Main.

Los mtodos que no son void deben devolver valores


Si se declara un mtodo con un tipo distinto de void, es obligatorio aadir al menos una instruccin return. El compilador intenta comprobar que cada uno de estos mtodos devuelve siempre un valor al mtodo de llamada. Si detecta que un mtodo que no es void no incluye ninguna instruccin return, el compilador mostrar el siguiente mensaje de error: No todas las rutas de cdigo devuelven un valor. Este mensaje tambin aparecer si el compilador detecta que es posible ejecutar un mtodo que no es void sin devolver un valor. Consejo La instruccin return slo se puede utilizar para devolver un valor desde cada llamada a un mtodo. Si se desea devolver ms de un valor desde una llamada a un mtodo se pueden utilizar los parmetros out o ref, que se discutirn ms adelante en este mdulo. Tambin es posible devolver una referencia a una tabla o clase o estructura, que puede contener varios valores. La norma general, segn la cual hay que evitar el uso de varias instrucciones return en un solo mtodo, es vlida tambin para mtodos que no son void.

Mtodos y parmetros

17

Uso de parmetros
Objetivo del tema
Ofrecer una introduccin a los temas tratados en esta seccin.

Explicacin previa

Declaracin y llamadas a parmetros Mecanismos de paso de parmetros Paso por valor Paso por referencia Parmetros de salida Uso de listas de parmetros de longitud variable Normas para el paso de parmetros Uso de mtodos recursivos

En esta seccin aprender a utilizar parmetros en mtodos.

En esta seccin aprender a declarar parmetros y a hacer llamadas a mtodos con parmetros. Estudiar tambin como se pasan parmetros. Finalmente, aprender el uso de llamadas a mtodos recursivos en C#. Recomendacin al profesor En esta seccin aprender a: Declarar y hacer llamadas a parmetros. Pasar parmetros utilizando los siguientes mecanismo: Paso por valor Paso por referencia Parmetros de salida Usar llamadas a mtodos recursivos.

Dependiendo de su formacin, es posible que los estudiantes tengan distintas ideas sobre el paso de parmetros. C no permite directamente el paso de parmetros por referencia (en su lugar se pasan punteros). C++ incluye un mecanismo de paso por referencia, adems de punteros similares a los de C. En Visual Basic, los parmetros se pasan por referencia de forma predeterminada, salvo que se desactive esta opcin con la palabra clave ByVal.

Mtodos y parmetros

18

Declaracin y llamadas a parmetros


Mostrar la sintaxis bsica para la declaracin y el uso de parmetros.

Objetivo del tema

Explicacin previa

Declaracin de parmetros

En la declaracin del mtodo, los parmetros se colocan entre los parntesis que siguen al nombre del mtodo.

Se ponen entre parntesis despus del nombre del mtodo Se definen el tipo y el nombre de cada parmetro Un valor para cada parmetro

Llamadas a mtodos con parmetros


static static void void MethodWithParameters(int MethodWithParameters(int n, n, string string y) y) { ... } { ... } MethodWithParameters(2, MethodWithParameters(2, "Hola, "Hola, mundo"); mundo");

Los parmetros permiten pasar informacin hacia dentro y fuera de un mtodo. La definicin de un mtodo puede incluir una lista de parmetros entre parntesis a continuacin del nombre del mtodo. Las listas de parmetros de todos los ejemplos que hemos visto hasta ahora en este mdulo estaban vacas.

Declaracin de parmetros
Cada parmetro tiene un tipo y un nombre. Se pueden declarar parmetros poniendo sus declaraciones entre los parntesis que siguen al nombre del mtodo. La sintaxis que se utiliza es similar a la empleada para declarar variables locales, salvo que las declaraciones de parmetros se separan con una coma en lugar de un punto y coma. El siguiente ejemplo muestra cmo declarar un mtodo con parmetros:
static void MethodWithParameters(int n, string y) { // ... }

Este ejemplo declara el mtodo MethodWithParameters con dos parmetros: n e y. El primer parmetro es de tipo int, mientras que el segundo es de tipo string. Los parmetros aparecen en la lista separados por comas.

Mtodos y parmetros

19

Llamadas a mtodos con parmetros


El cdigo de llamada debe indicar los valores de los parmetros en la llamada al mtodo. El siguiente cdigo muestra dos ejemplos de llamadas a un mtodo con parmetros. En ambos casos, los valores de los parmetros son encontrados y colocados en los parmetros n e y al principio de la ejecucin de MethodWithParameters.
MethodWithParameters(2, "Hola, mundo"); int p = 7; string s = "Mensaje de prueba"; MethodWithParameters(p, s);

Mtodos y parmetros

20

Mecanismos de paso de parmetros


Objetivo del tema
Presentar tres formas de pasar parmetros.

Explicacin previa

Los parmetros se pueden pasar de tres maneras distintas.

Tres maneras de pasar parmetros

entrada Paso por por valor valor entrada Paso entrada entrada Paso Paso por por referencia referencia salida salida salida salida
Parmetros Parmetros de de salida salida

Para su informacin

Los parmetros se pueden pasar de tres maneras distintas: Por valor Los parmetros valor se llaman a veces parmetros de entrada, ya que los datos se pueden transferir a un mtodo pero no fuera de l. Por referencia Los parmetros referencia se llaman a veces parmetros de entrada/salida, ya que los datos se pueden transferir dentro y fuera de un mtodo. Por salida Los parmetros de salida se llaman a veces parmetros out, ya que los datos se pueden transferir fuera de un mtodo pero no dentro de l.

En C y C++ se usa por defecto el mecanismo de paso por valor. C no incluye ningn mecanismo de paso por referencia. C++ utiliza el modificador & para indicar paso por referencia. Visual Basic utiliza por defecto paso por referencia.

Mtodos y parmetros

21

Paso por valor


Objetivo del tema
Explicar el mecanismo de paso por valor.

Mecanismo predeterminado para el paso de parmetros:


Explicacin previa

Se copia el valor del parmetro Se puede cambiar la variable dentro del mtodo No afecta al valor fuera del mtodo El parmetro debe ser de un tipo igual o compatible

El paso por valor es el mecanismo predeterminado.

static static void void SumaUno(int SumaUno(int x) x) { { x++; x++; // // Incrementar Incrementar x x } } static static void void Main( Main( ) ) { { int int k k= = 6; 6; SumaUno(k); SumaUno(k); } }

Console.WriteLine(k); Console.WriteLine(k); // // Muestra Muestra el el valor valor 6, 6, no no 7 7

La mayor parte de los parmetros se utilizan en las aplicaciones para pasar informacin a un mtodo, no fuera de l. Por eso el paso por valor es el mecanismo predeterminado para pasar parmetros en C#.

Definicin de parmetros valor


La definicin ms sencilla de un parmetro es un nombre de tipo seguido de un nombre de variable, y se conoce como parmetro valor. Cuando se hace una llamada a un mtodo, para cada parmetro valor se crea una nueva ubicacin de almacenamiento donde se copian los valores de las expresiones correspondientes. La expresin de cada parmetro valor debe ser del mismo tipo que la declaracin del parmetro valor, o bien de un tipo que pueda ser convertido implcitamente a ese tipo. Dentro del mtodo se puede escribir cdigo que cambie el valor del parmetro. Esto no afectar a ninguna variable fuera de la llamada al mtodo. En el siguiente ejemplo, la variable x en AddOne (SumaUno) es completamente independiente de la variable k en Main. Se puede cambiar la variable x en AddOne, pero esto no afectar al valor de k.

Mtodos y parmetros
static void AddOne(int x) { x++; } static void Main( ) { int k = 6; AddOne (k); Console.WriteLine(k); // Muestra el valor 6, no 7 }

22

Mtodos y parmetros

23

Paso por referencia


Objetivo del tema
Explicar el mecanismo de paso por referencia.

Explicacin previa

Un parmetro referencia es una referencia a una posicin de memoria.

Qu son los parmetros referencia?


Una referencia a una posicin de memoria Se usa la palabra clave ref en la declaracin y las llamadas al mtodo Los tipos y valores de variables deben coincidir Los cambios hechos en el mtodo afectan al llamador Hay que asignar un valor al parmetro antes de la llamada al mtodo

Uso de parmetros referencia


Qu son los parmetros referencia?


Un parmetro referencia es una referencia a una posicin de memoria. A diferencia de un parmetro valor, un parmetro referencia no crea una nueva ubicacin de almacenamiento. Por el contrario, un parmetro referencia representa la misma posicin de memoria que la variable indicada en la llamada al mtodo. Recomendacin al profesor

Declaracin de parmetros referencia


Un parmetro referencia se puede declarar poniendo la palabra clave ref antes del nombre del tipo, como se ve en el siguiente ejemplo:
static void ShowReference(ref int nId, ref long nCount) { // ... }

Puede explicar a los programadores en C y C++ que el operador ref es similar al operador de direccin (&) en C y C++, aunque no son iguales. Las direcciones de C y C++ permiten modificar posiciones de memoria arbitrarias. C# es ms seguro.

Uso de distintos tipos de parmetros


La palabra clave ref afecta nicamente al parmetro al que antecede, no a toda la lista de parmetros. En el siguiente mtodo, nId se pasa por referencia pero longVar se pasa por valor:
static void OneRefOneVal(ref int nId, long longVar) { // ... }

Mtodos y parmetros

24

Coincidencia de tipos y valores de parmetros


En la llamada a un mtodo, los parmetros referencia se indican utilizando la palabra clave ref seguida de una variable. El valor indicado en la llamada al mtodo debe ser exactamente igual al tipo en la definicin del mtodo, y adems debe ser una variable, no una constante ni una expresin calculada.
int x; long q; ShowReference(ref x, ref q);

Si se omite la palabra clave ref o si se emplea una constante o una expresin calculada, el compilador rechazar la llamada y mostrar un mensaje de error parecido al siguiente: Imposible convertir de int a ref int.

Cambio de valores de parmetros referencia


Si se cambia el valor de un parmetro referencia cambiar tambin la variable indicada por el llamador, ya que ambas son referencias a la misma posicin de memoria. El siguiente ejemplo ilustra cmo el cambio del parmetro referencia afecta tambin a la variable:
static void AddOne(ref int x) { x++; } static void Main( ) { int k = 6; AddOne(ref k); Console.WriteLine(k); // Muestra el valor 7 }

Este cdigo funciona porque, cuando se hace la llamada a AddOne, su parmetro x apunta a la misma posicin de memoria que la variable k en Main. Por lo tanto, al incrementar x se incrementar tambin k.

Mtodos y parmetros

25

Asignacin de parmetros antes de la llamada al mtodo


Un parmetro ref tiene que estar definitivamente asignado al punto de llamada; es decir, el compilador debe asegurarse de que se asigna un valor antes de hacer la llamada. El siguiente ejemplo muestra cmo se pueden inicializar parmetros referencia antes de la llamada al mtodo:
static void AddOne(ref int x) { x++; } static void Main( ) { int k = 6; AddOne(ref k); Console.WriteLine(k); // 7 }

El siguiente ejemplo muestra lo que ocurre si no se inicializa un parmetro referencia k antes de la llamada al mtodo AddOne:
int k; AddOne(ref k); Console.WriteLine(k);

El compilador de C# rechazar este cdigo y mostrar el siguiente mensaje de error: Uso de variable local k no asignada.

Mtodos y parmetros

26

Parmetros de salida
Explicar la palabra clave out y su relacin con el paso por referencia.

Objetivo del tema

Qu son los parmetros de salida?


Explicacin previa

Los parmetros de salida son similares a los parmetros referencia, pero transfieren datos fuera del mtodo en lugar de al mtodo.

Pasan valores hacia fuera, pero no hacia dentro Como ref, pero no se pasan valores al mtodo Se usa la palabra clave out en la declaracin y las llamadas al mtodo

Uso de parmetros de salida


static static void void OutDemo(out OutDemo(out int int p) p) { { // // ... ... } } int int n; n; OutDemo(out OutDemo(out n); n);

Qu son los parmetros de salida?


Los parmetros de salida son similares a los parmetros referencia, pero transfieren datos fuera del mtodo en lugar de al mtodo. Al igual que u parmetro referencia, un parmetro de salida es una referencia a una ubicacin de almacenamiento indicada por el llamador. Sin embargo, no es necesario asignar un valor a la variable indicada para el parmetro out antes de hacer la llamada, y el mtodo asume que el parmetro no ha sido inicializado. Los parmetros de salida son tiles cuando se quiere devolver valores de un mtodo por medio de un parmetro sin tener que asignar a ste un valor inicial.

Uso de parmetros de salida


Para declarar un parmetro de salida se utiliza la palabra clave out antes del tipo y el nombre, como se ve en el siguiente ejemplo:
static void DemoOut(out int p) { // ... }

Como ocurre con la palabra clave ref, out afecta nicamente a un parmetro y cada parmetro out debe estar separado de los dems. En la llamada a un mtodo con un parmetro out hay que poner la palabra clave out antes de la variable que se desea pasar, como en este ejemplo:

Mtodos y parmetros
int n; DemoOut(out n);

27

En el cuerpo del mtodo al que se hace la llamada no hay ninguna indicacin al contenido del parmetro de salida, por lo que ste se trata como si fuera una variable local sin asignar. El valor del parmetro out se tiene que asignar dentro del mtodo.

Mtodos y parmetros

28

Uso de listas de parmetros de longitud variable


Objetivo del tema
Presentar la palabra clave params.

Explicacin previa

C# incluye un mecanismo para pasar listas de parmetros de longitud variable.

Se usa la palabra clave params Se declara como tabla al final de la lista de parmetros Siempre paso por valor

static static long long AddList(params AddList(params long[ long[ ] ] v) v) { { long long total, total, i; i; for (i for (i = = 0, 0, total total = = 0; 0; i i< < v.Length; v.Length; i++) i++) total total += += v[i]; v[i]; return return total; total; } } static static void void Main( Main( ) ) { { long long x x= = AddList(63,21,84); AddList(63,21,84); } }

Recomendacin al profesor

C# incluye un mecanismo para pasar listas de parmetros de longitud variable.

No es necesario que discuta este tema con mucho detalle. Recuerde adems que en este curso todava no se han tratado las matrices.

Declaracin de parmetros de longitud variable


En ocasiones resulta til tener un mtodo que pueda aceptar un nmero variable de parmetros. En C# se puede emplear la palabra clave params para indicar una lista de parmetros de longitud variable. Cuando se declara un parmetro de longitud variable hay que: Declarar slo un parmetro params por mtodo. Poner el parmetro al final de la lista de parmetros. Declarar el parmetro como de tipo tabla unidimensional. Este ejemplo muestra cmo declarar una lista de parmetros de longitud variable:

Mtodos y parmetros
static long AddList (params long[ ] v) { long total; long i; for (i = 0, total = 0; i < v.Length; i++) total += v[i]; return total; }

29

Para su informacin

Visual Basic tiene una funcin parecida llamada ParamArray(). C y C++ tienen () y las macros va_*, que manejan listas de parmetros variables, como en printf.

Como un parmetro params es siempre una tabla, todos los valores deben ser del mismo tipo.

Mtodos y parmetros

30

Paso de valores
Hay dos maneras de pasar valores al parmetro params cuando se hace una llamada a un mtodo con un parmetro de longitud variable: Como una lista de elementos separados por comas (la lista puede estar vaca) Como una tabla Ambas tcnicas se muestran en el siguiente cdigo. El compilador trata las dos tcnicas de la misma forma.
static void Main( ) { long x; x = AddList (63, 21, 84); // Lista x = AddList (new long[ ]{ 63, 21, 84 }); // Tabla }

Independientemente del mtodo empleado para hacer la llamada al mtodo, el parmetro params se trata siempre como una tabla. Se puede usar la propiedad Length de la tabla para determinar el nmero de parmetros pasados a cada llamada. Para su informacin Los datos se copian en el parmetro params y, aunque es posible modificar los valores dentro del mtodo, los valores fuera del mtodo no cambian.

Para conservar los cambios realizados en el mtodo se usa una tabla object.

Mtodos y parmetros

31

Normas para el paso de parmetros


Objetivo del tema
Discutir los distintos mecanismos para el paso de parmetros.

Explicacin previa

Mecanismos

Aqu se ofrecen algunas normas para el paso de parmetros.

El paso por valor es el ms habitual El valor de retorno del mtodo es til para un solo valor ref y/o out son tiles para ms de un valor de retorno ref slo se usa si los datos se pasan en ambos sentidos El paso por valor suele ser el ms eficaz

Eficiencia

La abundancia de opciones disponibles para pasar parmetros puede hacer que la eleccin no resulte obvia. Dos de los factores que hay que considerar a la hora de elegir la forma de pasar parmetros son el mecanismo y su eficiencia.

Mecanismos
Los parmetros valor ofrecen cierta proteccin frente a modificaciones no deseadas, ya que los cambios realizados dentro del mtodo no tienen efecto fuera de l. Esto sugiere que los parmetros valor son la mejor opcin, salvo que sea preciso pasar informacin fuera de un mtodo. Recomendacin al profesor Para pasar datos fuera de un mtodo se puede utilizar la instruccin return, parmetros referencia o parmetros de salida. La instruccin return es fcil de usar, pero slo puede devolver un resultado. Si se necesita devolver varios valores hay que usar parmetros referencia y de salida. Utilice ref si desea transferir datos en las dos direcciones, y out si slo necesita transferir datos fuera del mtodo.

Esto es una ligera simplificacin. Un mtodo puede devolver varios valores utilizando tipos de referencia (por ejemplo, una tabla).

Eficiencia
En general, los tipos simples como int y long se pasan ms eficazmente por valor. Estos aspectos de eficiencia no forman parte del lenguaje, por lo que no hay que tomrselos al pie de la letra. Aunque la eficiencia puede ser un punto a tener en cuenta en aplicaciones grandes y que consumen muchos recursos, normalmente es preferible preocuparse de la correccin, la estabilidad y la potencia del programa antes que de la eficiencia. El empleo de buenas prcticas de programacin tiene prioridad sobre la eficiencia.

Mtodos y parmetros

32

Uso de mtodos recursivos


Objetivo del tema
Explicar que C# permite el uso recursivo de mtodos.

Explicacin previa

Como la mayor parte de los lenguajes de programacin, C# permite el uso recursivo de mtodos.

Un mtodo puede hacer una llamada a s mismo


Directamente Indirectamente

til para resolver ciertos problemas

Recomendacin al profesor

No todos los estudiantes estarn familiarizados con la recursin. En caso de problemas, explique que por el momento no es necesario comprender la recursin en detalle. Lo nico que tienen que saber es que pueden utilizarla cuando sea necesario.

Un mtodo puede hacer una llamada a s mismo. Esta tcnica se conoce como recursin y ofrece una solucin para ciertos tipos de problemas. Los mtodos recursivos suelen ser tiles para manipular estructuras de datos ms complejas, como listas y rboles. Los mtodos en C# pueden ser mutuamente recursivos. Por ejemplo, puede darse una situacin en la que un mtodo A llame a un mtodo B, y el mtodo B llame al mtodo A.

Ejemplo de mtodo recursivo


La serie de Fibonacci aparece con cierta frecuencia en matemticas y biologa (por ejemplo, el ndice de reproduccin y la poblacin de conejos). El trmino n de esta serie tiene el valor 1 si n es 1 2, y en los dems casos es igual a la suma de los dos nmeros que le preceden en la serie; es decir, el valor del trmino n para n mayor de 2 se obtiene a partir de dos valores anteriores de la serie. El hecho de que la definicin del mtodo incluya al propio mtodo sugiere que puede ser recursivo. El cdigo para el mtodo Fibonacci podra ser siguiente:
static ulong Fibonacci(ulong n) { if (n <= 2) return 1; else return Fibonacci(n-1) + Fibonacci(n-2); }

Recomendacin al profesor

El cdigo del ejemplo usa ulongs para poder utilizar valores grandes.

Como puede verse, dentro del mtodo se hacen dos llamadas al mismo mtodo.

Mtodos y parmetros

33

Un mtodo recursivo debe tener una condicin de fin para que devuelva un valor sin hacer ms llamadas. En el caso del mtodo Fibonacci, la condicin de fin es n <= 2.

Mtodos y parmetros

34

Uso de mtodos sobrecargados


Objetivo del tema
Ofrecer una introduccin a los temas tratados en esta seccin.

Explicacin previa

Declaracin de mtodos sobrecargados Signaturas de mtodos Uso de mtodos sobrecargados

En esta seccin aprender a usar mtodos sobrecargados.

Los mtodos no pueden tener el mismo nombre que otros elementos en una clase. Sin embargo, dos o ms mtodos en una clase s pueden compartir el mismo nombre. A esto se le da el nombre de sobrecarga. En esta seccin aprender a: Declarar mtodos sobrecargados. Utilizar signaturas en C# para distinguir mtodos que tienen el mismo nombre. Saber cundo usar mtodos sobrecargados.

Mtodos y parmetros

35

Declaracin de mtodos sobrecargados


Objetivo del tema
Explicar cmo sobrecargar nombres de mtodos.

Explicacin previa

Mtodos que comparten un nombre en una clase


Es posible dar el mismo nombre a ms de un mtodo en una clase.

Se distinguen examinando la lista de parmetros

class class OverloadingExample OverloadingExample { { static static int int Suma(int Suma(int a, a, int int b) b) { { return return a a+ + b; b; } } static static int int Suma(int Suma(int a, a, int int b, b, int int c) c) { { return return a a+ +b b+ + c; c; } } static static void void Main( Main( ) ) { { Console.WriteLine(Suma(1,2) Console.WriteLine(Suma(1,2) + + Suma(1,2,3)); Suma(1,2,3)); } } } }

Para su informacin

C++ admite la sobrecarga, pero C no. Visual Basic .NET es la primera versin de Visual Basic que permite mtodos sobrecargados.

Los mtodos sobrecargados son mtodos que tienen el mismo nombre dentro de una clase. El compilador de C# distingue mtodos sobrecargados comparando las listas de parmetros.

Ejemplos de mtodos sobrecargados


El siguiente cdigo muestra cmo se pueden utilizar distintos mtodos con el mismo nombre en una clase:
class OverloadingExample { static int Add(int a, int b) { return a + b; } static int Add(int a, int b, int c) { return a + b + c; } static void Main( ) { Console.WriteLine(Add(1,2) + Add(1,2,3)); } }

Mtodos y parmetros

36

Recomendacin al profesor

Las signaturas se discutirn con ms detalle en el siguiente tema.

El compilador de C# encuentra en la clase dos mtodos llamados Add, y dos llamadas a mtodos llamados Add en Main. Aunque los nombres de los mtodos son iguales, el compilador puede distinguir entre los dos mtodos Add comparando las listas de parmetros. El primer mtodo Add acepta dos parmetros, ambos de tipo int. Por su parte, el segundo mtodo Add lleva tres parmetros que tambin son de tipo int. Como las listas de parmetros son diferentes, el compilador permite definir ambos mtodos dentro de la misma clase. La primera instruccin en Main contiene una llamada a Add con dos parmetros int, por lo que el compilador la interpreta como una llamada al primer mtodo Add. La segunda llamada a Add lleva tres parmetros int y el compilador la interpreta como una llamada al segundo mtodo Add. No est permitido compartir nombres entre mtodos y variables, constantes o enumeraciones en la misma clase. El siguiente cdigo no se compilar porque se ha utilizado el nombre k para un mtodo y una variable:
class BadMethodNames { static int k; static void k( ) { // ... } }

Mtodos y parmetros

37

Signaturas de mtodos
Objetivo del tema
Explicar la funcin de las signaturas de mtodos.

Explicacin previa

El compilador de C# puede distinguir entre mtodos en una clase examinando la signatura de cada mtodo.

Las signaturas de mtodos deben ser nicas dentro de una clase Definicin de signatura

Forman Forman la la definicin definicin de la signatura de la signatura


Nombre Nombredel delmtodo mtodo Tipo Tipode deparmetro parmetro Modificador Modificador

No No afectan afectan a a la la signatura signatura


Nombre Nombrede de parmetro parmetro Tipo Tipode deretorno retornode de

mtodo mtodo

El compilador de C# utiliza signaturas para distinguir entre mtodos en una clase. Cada mtodo dentro de una clase debe tener una signatura diferente de la de todos los dems mtodos declarados en esa clase.

Definicin de signatura
La signatura de un mtodo consta del nombre del mtodo, el nmero de parmetros del mtodo y el tipo y modificador (como out o ref) de cada parmetro. Para su informacin Los tres mtodos siguientes tienen distintas signaturas, por lo que pueden estar declarados en la misma clase.
static int LastErrorCode( ) { } static int LastErrorCode(int n) { } static int LastErrorCode(int n, int p) { }

No est permitido definir mtodos sobrecargados que se diferencien nicamente en ref y out.

Mtodos y parmetros

38

Elementos que no afectan a la signatura


La signatura de un mtodo no incluye el tipo retorno. Los dos mtodos siguientes tienen la misma signatura, por lo que no pueden estar declarados en la misma clase.
static int LastErrorCode(int n) { } static string LastErrorCode(int n) { }

La signatura de un mtodo no incluye los nombres de los parmetros. Los dos mtodos siguientes tienen la misma signatura, aunque los nombres de los parmetros sean diferentes.
static int LastErrorCode(int n) { } static int LastErrorCode(int x) { }

Mtodos y parmetros

39

Uso de mtodos sobrecargados


Objetivo del tema
Explicar cundo usar mtodos sobrecargados.

Explicacin previa

Este tema describe algunas situaciones en las que es conveniente sobrecargar mtodos.

Conviene usar mtodos sobrecargados si:


Hay mtodos similares que requieren parmetros diferentes Se quiere aadir funcionalidad al cdigo existente Son difciles de depurar Son difciles de mantener

No hay que abusar, ya que:


Los mtodos sobrecargados son tiles si se tienen dos mtodos similares que requieren distinto nmero o tipo de parmetros.

Mtodos similares que requieren parmetros diferentes


Imaginemos que una clase contiene un mtodo que enva un mensaje de saludo al usuario. A veces se sabe el nombre del usuario, pero no siempre. Se pueden definir dos mtodos diferentes llamados Greet y GreetUser, como muestra el siguiente cdigo:
class GreetDemo { static void Greet( ) { Console.WriteLine("Hola"); } static void GreetUser(string Name) { Console.WriteLine("Hola " + Name); } static void Main( ) { Greet( ); GreetUser("Alex"); } }

Mtodos y parmetros

40

El programa funciona, pero en la clase hay dos mtodos que realizan una tarea prcticamente idntica aunque tengan nombres diferentes. Esta clase se puede reescribir con sobrecarga de mtodos como se muestra a continuacin:
class GreetDemo { static void Greet( ) { Console.WriteLine("Hola"); } static void Greet(string Name) { Console.WriteLine("Hola " + Name); } static void Main( ) { Greet( ); Greet("Alex"); } }

Mtodos y parmetros

41

Adicin de funcionalidad al cdigo existente


La sobrecarga de mtodos tambin es til si se desea aadir nuevas funciones a una aplicacin sin tener que hacer demasiados cambios al cdigo existente. Por ejemplo, se podra ampliar el cdigo anterior aadiendo otro mtodo que salude a un usuario de forma diferente segn la hora del da, como se muestra a continuacin:
class GreetDemo { enum TimeOfDay { Manana, Tarde, Noche } static void Greet( ) { Console.WriteLine("Hola"); } static void Greet(string Name) { Console.WriteLine("Hola " + Name); } static void Greet(string Name, TimeOfDay td) { string Message = ""; switch(td) { case TimeOfDay.Manana: Message="Buenos das"; break; case HoraDelDia.Tarde: Message="Buenas tardes"; break; case HoraDelDia.Noche: Message="Buenas noches"; break; } Console.WriteLine(Mensaje + " " + Name); } static void Main( ) { Greet( ); Greet("Alex"); Greet("Sandra", HoraDelDia.Manana); } }

Cundo utilizar sobrecarga


El uso excesivo de la sobrecarga de mtodos puede hacer que las clases resulten difciles de depurar y mantener. En general, slo se debe sobrecargar mtodos que tengan funciones muy estrechamente relacionadas pero que difieran en la cantidad o el tipo de datos que necesitan.

You might also like