Veremos ahora las cinco partes, pero conforme estudiemos a las funciones sabremos cómo son utilizadas. Las funciones pueden regresar información y esta información puede ser cadena, entero, flotante o cualquier otro tipo. En la sección de tipo tenemos que indicar precisamente la clase de información que regresa. Si la función no regresa ningún valor entonces tenemos que indicar a su tipo como void. Todas las funciones deben identificarse y lo hacemos por medio de su nombre. Las funciones que coloquemos adentro de las clases deben de tener un nombre único. El nombre también es utilizado para invocar o ejecutar a la función.
Las funciones pueden necesitar de datos o información para poder trabajar. Nosotros le damos esta información por medio de sus parámetros. Los parámetros no son otra cosa que una lista de variables que reciben estos datos. Si la función no necesita usar a los parámetros, entonces simplemente podemos dejar los paréntesis vacíos. Nunca debemos olvidar colocar los paréntesis aunque no haya parámetros. El código de la función se sitúa adentro de un bloque de código. En esta sección podemos colocar cualquier código válido de C#, es decir, declaración de variables, ciclos, estructuras selectivas e incluso invocaciones a funciones. Las funciones al ser declaradas pueden llevar un modificador antes del tipo. Los modificadores cambian la forma como trabaja la función. Nosotros estaremos utilizando un modificador conocido como static. Este modificador nos permite usar a la función sin tener que declarar un objeto de la clase a la que pertenece.
Tenemos cuatro tipos básicos de funciones:
- Funciones que ejecutan código
- Funciones que regresan un valor
- Funciones que reciben valores
- Funciones que reciben parámetros y regresan un valor
Funciones que ejecutan código
El primer tipo de funciones que vamos a conocer son las que ejecutan código. Estas funciones no reciben datos y no regresan ningún dato. Solamente llevan a cabo alguna operación. Aunque en este momento no parecen muy útiles, sí lo son. Para poder utilizar la función, debemos declararla. La declaración se debe hacer adentro del bloque de código correspondiente a una clase. Para los ejemplos analizados en este libro, estamos usando la clase denominada Program. Nuestra función Main() se encuentra también adentro de esta clase. En este momento tomaremos una estrategia de programación, que aún no pertenece a la programación estructurada, en el futuro veremos las técnicas orientadas a objetos. En esta técnica usamos a la función Main() como administradora de la lógica y la mayor parte del proceso se llevará a cabo en las funciones. Crearemos una aplicación y le colocaremos cada uno de los tipos de funciones que vamos a aprender, dejando a Main() como nuestra administradora del programa. El programa va a ser conceptualmente sencillo, ya que lo que nos interesa es comprender el funcionamiento de las funciones. El programa simplemente se encargará de preguntarle al usuario el tipo de operación aritmética que queremos llevar a cabo y luego la realizará con los datos dados que le proporcionemos. Este programa ya fue resuelto anteriormente, pero en este caso será implementado agregando el uso de las funciones. En el diagrama de flujo indicamos a la función por medio de un rectángulo que tiene dos franjas a los lados. Cuando lo veamos, sabemos que tenemos que ir a la función y ejecutar su código. Veamos cómo quedaría el diagrama de flujo de la aplicación.
Funciones que regresan un valor
Nuestro siguiente tipo de función puede regresar un valor. Esto significa que cuando la función es invocada va a llevar a cabo la ejecución de su código. El código va a calcular un valor de alguna manera y este valor calculado por la función será regresado a quien haya invocado a la función. La invocación puede haber sido hecha por la función Main() o algún otra función. Como la función va a regresar un valor, necesitamos indicar su tipo. El tipo va a depender del valor devuelto. Si el valor es un entero, entonces el tipo de la función es int. Si el valor es un flotante, la función tendrá tipo float y así sucesivamente. La función puede regresar cualquiera de los tipos definidos en el lenguaje y también tipos definidos por el programador y objetos de diferentes clases. La función va a utilizar un comando especial para regresar el valor, este comando se conoce como return y se usa de la siguiente manera:
return variable;
En cuanto la ejecución del programa encuentra un return, la función es finalizada aun si no ha llegado a su fin. Al mismo tiempo que finaliza la función el valor colocado después del return es regresado a quien hizo la invocación. El valor puede ser colocado con una variable o explícitamente con un valor en particular. No hay que olvidar colocar el punto y coma al finalizar la sentencia. La finalización de la función se lleva a cabo aunque tengamos código escrito después del return. Como la función regresa un valor, del lado del invocador necesitamos tener alguien que pueda recibir el valor regresado. Generalmente usaremos una variable, pero en algunos casos puede ser una expresión que será evaluada con el valor regresado por la función. Supongamos que nuestra función regresa un valor entero. Entonces podemos tener un código como el siguiente.
int n;
n=función();
De esta forma el valor regresado por la función queda guardado en la variable n y podemos hacer uso de él. El código lo entendemos de la siguiente forma. Tenemos una variable entera n. Luego tenemos una asignación para n. Si recordamos, la asignación siempre se lleva a cabo de derecha a izquierda. Se evalúa la expresión y la función se ejecuta y calcula un valor, el cual es regresado por medio de return. Este valor se considera como la evaluación de la expresión y es asignado a n. A partir de este momento podemos usar el valor según lo necesitemos.
Funciones que reciben valores
Hasta el momento las funciones que hemos utilizado piden directamente al usuario los valores que necesitan para trabajar. Sin embargo, las funciones también pueden recibir valores en el momento que son invocadas. De esta forma trabajarán con los valores pasados por el programa en lugar de pedirlos al usuario. Estos valores son conocidos como parámetros. Los parámetros pueden ser de cualquier tipo, ya sea de los tipos nativos de C# como entero, flotante, cadena o de tipos definidos por el programador como clases y estructuras.
Los parámetros deben llevar su tipo y su nombre. El nombre nos permite acceder a los datos que contiene y de hecho van a trabajar como si fueran variables locales a la función. Adentro de la función los usamos como variables normales. Los parámetros se definen en la declaración de la función. Adentro de los paréntesis de la función los listamos. La forma de listarlos es colocando primero en tipo seguido del nombre. Si tenemos más de un parámetro para la función, entonces debemos separarlos por medio de comas.
La invocación de la función es muy sencilla, simplemente debemos colocar el nombre de la función y, entre los paréntesis, los datos que vamos a enviar como parámetros. Los datos pueden ser situados por medio de variables o un valor colocado explícitamente. Podemos hacer ahora la función que se encargará de la multiplicación. Esta función recibirá los operandos desde Main() por medio de los parámetros, realizará el cálculo y lo mostrará al usuario. Como la función Main() manda la información, entonces será responsabilidad de ella pedirlos a los usuarios.
Funciones que reciben parámetros y regresan un valor
Ya hemos visto tres tipos diferentes de funciones, y seguramente ya hemos comprendido cómo funcionan y podemos fácilmente imaginar lo que hará este tipo de función. Esta función va a recibir de quien la invoque información. La información es pasada por medio de parámetros. La función lleva a cabo alguna acción o cálculo y obtiene un valor que va a ser regresado. El valor regresado es recibido en el lugar donde se invocó a la función y se puede trabajar con él. Los parámetros serán usados como variables y los declaramos adentro de los paréntesis de la función. Tenemos que indicar el tipo que va a recibir seguido de su nombre, si tenemos más de un parámetro, entonces debemos de separarlos por comas. Como la función regresa un valor, es necesario indicar su tipo en la declaración. La variable que va a recibir el valor retornado deberá tener de preferencia el mismo tipo que la función o cuando menos un tipo que sea compatible o posible de convertir. Como siempre haremos uso de return para poder regresar el valor calculado. De hecho este tipo de función utiliza todas las partes de las que consiste una función. En este momento debemos programar la función que lleva a cabo la división. La función recibirá dos valores flotantes, verificará que no llevemos a cabo la división entre cero, realiza el cálculo y regresa el valor.
Ejemplos:
1.- Programa que muestra la suma de 5+10 usando la Función que devuelve un valor.
Código:
Compilación:
2.-Programa que muestra la suma de dos números ingresados usando la función que ejecuta código.
Código:
Compilación:
3.- Multiplicación de dos valores ingresados usando la función que reciben valores.
Código:
Compilación:
ARREGLOS
En C# llamamos arreglo a una colección de objetos, dicha colección tiene longitud definida y esta no puede cambiar con el flujo del programa, esto podrá sonar limitante, pero al trabajar con arreglos se obtiene un mejor desempeño que con cualquier otra colección. Usando el lenguaje podemos crear, recorrer y manipular arreglos de cualquier tipo de objeto.
Unidimensionales
Comenzando por lo más básico, los arreglos unidimensionales son colecciones lineales, que nos pueden ayudar a representar una secuencia numérica, letras del alfabeto o un cromosoma dentro de un programa de algoritmos genéticos, entre muchas otras otras.
Instanciación
Para crear un arreglo haremos uso de la palabra reservada new y los corchetes cuadrados [ ], también es necesario conocer el tamaño que necesitaremos, puesto que como ya lo mencioné, no es posible cambiar el tamaño una vez creado:
char [] vocales = new char[5];
int [] conteo = new int[10];
object [] misObjetos = new object[3];
Si creamos arreglos de esa manera, cada posición tendrá el valor por default del tipo de dato del arreglo… bueno, mejor usamos nuestro ejemplo:
El arreglo de vocales contendrá 5 \0, que es el valor por default de un char.
El arreglo conteo contendrá 10 0, que es el valor por default de un entero.
El arreglo misObjetos contendrá 3 null, que es el valor por default de un object.
Además de la instanciación tradicional, también podemos emplear la instanciación de colecciones, la cual nos permite inicializar un arreglo asignándole valores inmediatamente:
char [] vocales = new char[5] { 'a', 'e', 'i', 'o', 'u' };
int [] conteo = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
object [] misObjetos = { "3", 1, 99.99 };
Como podemos ver, tenemos varias opciones para inicializar arreglos unidimensionales:
- new char[5] { ..., nos permite indicar el tamaño y el tipo explícitamente y posteriormente indicar los valores, si cambiáramos el 5 por un 7sin aumentar la cantidad de valores obtendríamos un error de compilación.
- new int[] { 1, 2, ..., nos permite indicar solamente el tipo de dato de los elementos, la cantidad es inferida por el compilador, en este caso podemos incrementar o reducir la cantidad de elementos al momento de inicializar sin ningún problema.
- { "3", 1, 99.99 }, al inicializar de esta manera estamos dejandole al compilador la tarea de inferir tanto el tipo de dato del arreglo como la cantidad de elementos que contiene. Dicho sea de paso, el declarar un arreglo así puede resultar un poco confuso de leer.
Acceso a los elementos
Una vez instanciado, podemos acceder a los elementos del arreglo usando nuevamente los corchetes cuadrados [ ] y el índice del elemento al que queremos acceder. Nota importante los arreglos están indizados en 0 es decir, el primer elemento de un arreglo está en el índice 0.
Retomemos los arreglos del ejemplo pasado. Para acceder a la a dentro del arreglo vocales debemos acceder a la posición 0:
Console.WriteLine(vocales[0]); // a
O, digamos que queremos reemplazar la i por una t:
vocales[2] = 't';
Console.WriteLine(vocales[2]); // t
Propiedades y métodos
A pesar de que los arreglos implementan la interfaz IList, con todo y sus propiedades, la única rescatable para los arreglos unidimensionales es la propiedad Length (o LongLength si metemos más de 2^32-1 elementos en el arreglo), que nos devuelve la longitud del arreglo:
Console.WriteLine(vocales.Length); // 5
Console.WriteLine(conteo.Length); // 10
Console.WriteLine(misObjetos.Length); // 3
Posdata
Sin importar su contenido, los arreglos siempre son tipos por referencia, por lo que es posible tener las siguientes líneas de código:
int [] arreglo = null;
double [] nulo = null;
Ejemplos:
1.- Programa que guarda los sueldos de 5 operarios en un arreglo.
Código:
Compilación:
2.- Programa que muestre el curso que obtuvo el mayor promedio general. Cada curso cuenta con 5 alumnos.
Código:
Compilación:
3.- Ingreso de las alturas de 5 personas, y Contar cuántas personas son más altas que el promedio Normal y cuántas más bajas.
Código: