Está en la página 1de 30

Proyecto:

Aplicacin:
Manual de C# 2

TEMA 5. EL LENGUAJE C#

5.1 Introduccin
Este tema tratar de explicar los elementos del lenguaje C#, profundizando en los tipos de datos definidos, las
estructuras de programacin, as como en las caractersticas del lenguaje que nos permitir desarrollar programas.
Bsicamente cuestiones relacionadas con la sintaxis y el significado de los elementos del lenguaje.

5.2 Caracteres del lenguaje C#


El lenguaje C# utiliza el juego de caracteres UNICODE como cdigo de representacin de la informacin. Este
cdigo utiliza dos bytes para codificar los caracteres e incluye entre los primeros 256 caracteres los del juego de
caracteres ASCII. De este juego de caracteres los ms utilizados podemos agruparlos en:

Letras: (a-z, A-Z, incluida la , las letras acentuadas y el carcter _).


Dgitos: (0-9).
Espacios en blanco: realmente es una denominacin genrica para un grupo de caracteres cuya finalidad es
separar los elementos de un programa. Lo constituyen el espacio en blanco (SP), el tabulador horizontal
(HT), el retorno de carro (CR) y el avance de lnea (LF).
Caracteres especiales: , . ; : ? ( ) [ ] { } < > = ! / \ ~ + - * % & ^

Hay caracteres que no son imprimibles y no tienen una representacin grfica para su uso. En el cdigo UNICODE,
los 31 primeros caracteres no son imprimibles. Con el objeto de poder representar este tipo de caracteres, se puede
utilizar otra forma de representacin para tales caracteres: mediante las secuencias de escape. Una secuencia de
escape est formada por el carcter \ seguido de una combinacin de dgitos o de una letra.

1. Si se usa una combinacin de dgitos, stos deben expresar en hexadecimal el cdigo ASCII o UNICODE del
carcter a representar. Si se usa el cdigo ASCII, se deben preceder los dgitos con la letra x. Si se usa el
cdigo UNICODE se usa la letra u. As, para representar el carcter avance de lnea, cuyo cdigo es 10,
podramos hacerlo de las formas '\x0A' y \u000A.

2. Las secuencias de escape formadas por el carcter \ seguido de letra es una forma equivalente a la anterior.

El motivo es que es ms fcil recordar una letra que el cdigo asociado a dicho carcter. As por ejemplo la
secuencia de escape del tabulador horizontal es \t. No todos los caracteres permiten esta representacin.

La primera forma de representacin tambin sirve para aquellos caracteres que son imprimibles. As el carcter 'K'
tambin se puede representar de las formas '\x4B' y \u004B.

En la siguiente tabla se tienen las secuencias de escape que usan el formato \ seguido de letra.

Nombre Constante UNICODE Secuencia Escape


Carcter nulo NULL 0 \0
Sonido de alerta BEL 7 \a
Retroceso BS 8 \b
Tabulador horizontal HT 9 \t
Nueva lnea LF 10 \n
Salto de pgina FF 12 \f

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 3

Retorno de Carro CR 13 \r
Fin Archivo EOF 26 no existe
Escape ESC 27 no existe
Comillas " 34 \"
Apstrofo ' 39 \'
Barra Invertida \ 92 \\

Carcter ASCII. Representacin hexadecimal \xdd


Carcter UNICODE. Representacin hexadecimal \udddd

5.3. Tipos
Como ya comentamos, los tipos de C# se clasifican en tipos valor y tipos referencia. Una variable de un tipo valor
almacena directamente un valor, mientras que una variable de un tipo referencia lo que permite almacenar es una
referencia a un objeto, es decir la posicin de memoria donde se encuentra el objeto. Los tipos valor se clasifican en
tipos primitivos, estructuras y tipos enumerados.

Los tipos primitivos se clasifican en enteros, reales y el tipo bool. Los tipos enteros pueden ser con signo:
sbyte, short, int, long y sin signo: byte, ushort, uint, ulong y char. Los tipos reales pueden ser de coma
flotante: float y double o de coma fija: decimal.

Las variables de tipo primitivo que declaremos en nuestros programas deberemos elegirlas segn el tipo de
valores que vayan a almacenar y del rango de stos.

Las estructuras son parecidas a las clases, pero de tipo valor y con ciertas restricciones. Se suelen utilizar
para representar objetos ligeros (que ocupen poca memoria y necesiten procesarse con cierta velocidad).
Las estructuras no pueden derivar de ningn tipo y ningn tipo puede derivar de ellas. Al ser de tipo valor,
las asignaciones de variables de tipo estructura, provocan la copia de los valores que almacena la
estructura, y no la direccin de memoria como ocurre con los tipos referencia.

Para definir estructuras se realiza igual que las clases pero usando la palabra struct en lugar de class. Veamos el
siguiente ejemplo:

using System;
using System.Collections.Generic;
using System.Text;

namespace Estructuras
{
struct Punto
{
public int x, y; // Campos de la estructura
public Punto(int xx, int yy) // Constructor parametrizado
{
x = xx;
y = yy;
}
}
class Program
{
static void Main(string[] args)
{
Punto p1 = new Punto(10, 10);
Punto p2 = p1; // p2 y p1 No referencian al mismo Punto. Son dos objeto Punto
// distintos pero que almacenan los mismos valores en sus campos
p2.x = 100;
Console.WriteLine(p1.x);
}
}
}

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 4

La ejecucin presentar en pantalla 10. Esto se debe a que el valor de x modificado es el de p2, y este objeto p2
almacena en su espacio de memoria sus propios valores. Si Punto hubiese sido definido como una clase, si que
hubiese mostrado por pantalla 100, ya que p2 y p1 referenciaran el mismo espacio de memoria.

Todas las estructuras derivan implcitamente del tipo System.ValueType, que a su vez deriva de la clase
System.Object. En la clase Objects est definido el mtodo Equals() el cual permite determinar si dos referencias
sealan al mismo objeto. Ahora bien, en la clase ValueType se ha redefinido el mtodo Equals(), el heredado de
Objects, de modo que devuelva true si los objetos comparados tienen el mismo valor en todos sus campos y false en
caso contrario. Ahora lo que se comparan son los valores almacenados.

Todos los tipos primitivos vistos anteriormente tienen una estructura de datos asociada, de forma que los nombres de
dichos tipos primitivos son en realidad alias de estructuras. As por ejemplo el tipo double es un alias de la
estructura System.Double, o el tipo char es un alias de System.Char. Por lo tanto, los tipos primitivos son objetos
pero que se almacenan por valor.

Estas estructuras tienen definidas propiedades y mtodos. As por ejemplo, la estructura Int32, encapsula un nmero
entero (dato tipo int). Esta estructura dispone de una serie de campos y mtodos que podemos usar. Los ms
importantes son:

Campo Descripcin
MinValue Valor ms pequeo que se puede almacenar de tipo int
MaxValue Valor ms grande que se puede almacenar de tipo int.

Mtodo Descripcin
Parse(string) Convierte un string a un valor int.
ToString() Convierte un valor int en una cadena (objeto string).

Las otras estructuras disponen de atributos y mtodos anlogos. La estructura Double dispone del atributo NaN, (Not
is A Number), la cual representa una constante que es devuelta cuando el resultado de una operacin no est
definido. El mtodo IsNaN(double) devuelve true si el argumento no es un nmero. Los atributos NegativeInfinity y
PositiveInfinity representan los valores infinito negativo y positivo respectivamente El mtodo IsInfinity(double)
devuelve true si el valor del argumento es infinito.

Los tipos enumerados son tipos definidos por el usuario. Permiten utilizar un grupo de constantes a travs de
nombres asociados. Estos nombres son ms representativos que las constantes a las que representan.

Las constantes que se pueden usar deben ser de tipo byte, char, int o long.

Para definir tipos enumerados se utiliza la sintaxis enum tipo_a_definir seguida de los nombres asociados a las
constantes encerrados entre llaves. Por defecto las constantes asociadas son de tipo int y empiezan por el valor cero.
Un tipo enumerado puede definirse tanto fuera como dentro de una clase. Ejemplo:

using System;
using System.Text;
namespace Enumeracion
{
// Definicin del enumerado dia
enum dia { lunes, martes, miercoles, jueves, viernes, sabado, domingo };

class Program
{
static void Main(string[] args)
{
dia d = dia.lunes; // d es de tipo dia y se le asigna lunes
if (d != dia.domingo)
Console.WriteLine("Hoy no es " + dia.domingo);
if (d == 0)
Console.WriteLine("Horror, es " + d);
d = (dia)4; // 4 se convierte a tipo dia, tomando viernes
Console.WriteLine("Por fin es " + d); // se convierte a "viernes"
}

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 5

}
}

La salida que presenta su ejecucin sera:

Hoy no es domingo
Horror, es lunes
Por fin es viernes

Segn el ejemplo anterior, el primer valor de la enumeracin, lunes, se corresponde con 0, el segundo, martes, con
1, mircoles con 2, etc. Para asignar un valor a una variable de tipo enum se usa la sintaxis
nombre_enumeracion.constante. Tambin se puede asignar a la variable el valor entero correspondiente, pero es
necesario realizar una conversin explcita al tipo de la enumeracin. El ejemplo muestra cmo en la sentencias
WriteLine() se realiza una conversin de forma implcita del tipo de la enumeracin, dia, a tipo string.

Si queremos que las constantes se asocien a otro tipo que no sea int o que los valores enteros asociados sean otros,
podemos hacerlo de la forma:

enum dia : byte { lunes = 1, martes, miercoles, jueves, viernes, sabado = 9, domingo };

En este caso el tipo asociado a las constantes es byte y adems lunes se corresponde con 1, martes con 2, mircoles
con 3, jueves con 4, viernes con 5, sbado con 9 y domingo con 10.

5.4 Literales
Un literal es un valor constante que podr ser de algunos de los tipos primitivos, de tipo string (literal de cadena), o
bien la expresin null (referencia nula). Por lo tanto, un literal puede ser: un entero, un real, un valor booleano, un
carcter, una cadena de caracteres o un valor nulo. Todos ellos son valores constantes.

Los literales enteros se pueden expresar en decimal o en hexadecimal. Se le puede aadir un signo ms (+) o menos
(-). El tipo de un literal entero depender de su base, de su valor y de su sufijo.

Si el literal entero no tiene sufijo, su tipo es el primero de los tipos int, uint, long o ulong en el que su valor pueda
ser representado. Los sufijos pueden ser U, L o UL. Si es U, su tipo es el primero de los tipos uint o ulong en el que
su valor pueda ser representado; si es L, su tipo es el primero de los tipos long o ulong y si es UL su tipo es ulong.
Ejemplo:

1234 Constante entera tipo int


1234L Constante entera tipo long
12345678907 Constante entera tipo long

Los literales enteros expresados en hexadecimal deben ir precedidos por 0x o 0X. Ejemplo:

256 Constante entera decimal tipo int


0x100 Constante entera hexadecimal tipo int (equivalente a 256 en decimal)

Un literal real est formado por una parte entera, seguido por un punto decimal, y una parte fraccionaria. Tambin se
puede usar la notacin cientfica, en cuyo caso se aade al valor una e o E, seguida por un exponente positivo o
negativo. Por ejemplo, las tres constantes siguientes seran equivalentes:

-17.24
-0.1724E2
-1.724e+01
Las constantes reales son siempre de tipo double, salvo que se le aada el sufijo f o F en cuyo caso sern de tipo
float, o bien el sufijo m o M con lo que sera de tipo decimal. Ejemplos:

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 6

23.45e-02F
1234567.00M

Un literal carcter es un slo carcter encerrado entre comillas simples. Se pueden usar secuencias de escape para
representarlos. Ejemplos:

Espacio en blanco
a Letra minscula a
\n Retorno de carro ms avance de lnea (CR+LF)
\0 Carcter nulo (UNICODE \u0000)

El valor de una constante tipo carcter es el valor del cdigo numrico del juego de caracteres usado. As, la
constante A tiene asociado el valor 65 segn el juego de caracteres UNICODE.

Los literales de tipo string, llamados literales de cadena de caracteres o simplemente cadenas de caracteres estn
formados por una secuencia de caracteres, incluidas las secuencias de escape, encerradas entre comillas dobles. Las
cadenas de caracteres son en realidad objetos de tipo string; cada vez que usemos una cadena de caracteres, se crea
un objeto de tipo string con el valor del literal. Ejemplos:

"Esto es una cadena"


"12.34"
"A" // No confundir con A
"" // Cadena vaca.

5.5 Identificadores
Los identificadores son los nombres que se dan a variables, clases, estructuras, interfaces, eventos, mtodos,
espacios de nombre, etc. Las reglas respecto a las posibilidades de eleccin de nombres son las siguientes:

1. Un identificador se forma con una secuencia de letras (minsculas de la a a la z; maysculas de la A a la


Z, incluidas las ees y las vocales acentuadas) y dgitos (del 0 al 9).
2. El carcter subrayado o underscore ( _ ) se considera como una letra ms.
3. Un identificador no puede contener espacios en blanco, ni otros caracteres distintos de los citados, como por
ejemplo (* , ; . : - + , etc.).
4. El primer carcter de un identificador debe ser siempre una letra o un ( _ ), es decir, no puede ser un dgito.
5. Se hace distincin entre letras maysculas y minsculas (Case Sensitive). As, Masa es considerado como un
identificador distinto de masa y de MASA.

Ejemplos de identificadores vlidos son los siguientes:

tiempoSideral, distanciaAngular, caso_A, PI, velocidadDeLaLuz

Por el contrario, los siguientes nombres no son vlidos


1_valor, tiempo-total, euros, %final

En general es aconsejable elegir nombres de mtodos y de variables de forma que permitan conocer a simple vista
qu tipo de funcin o de variable representan, utilizando para ello tantos caracteres como sean necesarios. Esto
simplifica enormemente la tarea de programacin y sobre todo de correccin y mantenimiento de los programas. Es
cierto que los nombres largos son ms laboriosos de teclear, pero en general resulta rentable tomarse esa pequea
molestia. [Tema 0 ConvencinEstilosC#].

5.6 Palabras Clave

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 7

En C#, como en cualquier otro lenguaje, existen una serie de palabras clave (keywords) que el usuario no puede
utilizar como identificadores. Estos identificadores predefinidos tienen un significado especial para el compilador.
Una lista de estas palabras se puede obtener de la bibliografa. Importante, siempre se escriben en minsculas, tal
como aparecen.

5.7 Constantes Simblicas


Las variables pueden cambiar de valor a lo largo de la ejecucin de un programa, o bien en ejecuciones distintas de
un mismo programa. Adems de variables, un programa utiliza tambin constantes, es decir, valores que siempre
son los mismos.

La declaracin de una constante simblica consiste en dar un nombre o identificador y su valor. Para ello su usa el
calificador const. El formato es:

const tipo identificador = constante;

Una vez se haya declarado una constante, no se le puede asignar otro valor. Ejemplos:
const int iva = 16;
const string despedida = "Hasta luego";
despedida = "Adios"; // Error...

El uso ms frecuente de una constante es para poder modificar ms fcilmente un programa. Si por ejemplo en un
programa utilizamos 20 veces la constante iva de valor 16 y la hemos definido como en el ejemplo anterior, y
pasado un tiempo la legislacin cambia fijando el tipo de IVA general al nuevo valor del 21 %, slo es necesario
modificar una lnea, la de la definicin de la constante y volver a compilar. En cambio, si no hemos declarado iva,
sino que hemos utilizado el valor 16 directamente las 20 veces, tendramos que realizar 20 cambios en el cdigo.

5.8 Variables
Ya sabemos que una variable representa un espacio de memoria para almacenar un valor de un determinado tipo.
Dicho valor, a diferencia de una constante puede cambiar durante la ejecucin de un programa. La declaracin de
una variable se realiza con la siguiente sintaxis:

tipo identificador [, identificador]... [ = ValorInicial]

La declaracin de una variable se puede realizar a nivel de clase (atributos o campos de la clase), a nivel de mtodo
(dentro de la definicin del mtodo) o a nivel de un bloque de cdigo. Dependiendo de dnde se declare, su uso
estar limitado a la clase, al mtodo, o al bloque de cdigo que la define. Es lo que se conoce como mbito de una
variable.

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 8

Las variables miembro o campos de una clase pueden ser declaradas en cualquier parte dentro de la clase, siempre
que sea fuera de todo mtodo y estarn disponibles para todo el cdigo de la clase. Las variables declaradas dentro
de un mtodo y los parmetros de ste son locales al mtodo. Las variables declaradas dentro del bloque de una
sentencia compuesta, son locales a dicho bloque.

Una variable local existe y tiene valor desde su punto de declaracin hasta el final del bloque donde est definida.
Las variables locales de un mtodo se definen, es decir, se reserva espacio de memoria, cada vez que se ejecuta un
mtodo y dejan de existir cuando finaliza la ejecucin del mtodo.

Recordar que las variables miembro de una clase son iniciadas por omisin por el compilador, aunque podemos
iniciarlas explcitamente con los valores que indiquemos. Los valores asignados por defecto son 0 para las variables
numricas, los caracteres con \0, los tipos bool con el valor false y las referencias a null. En cambio las variables
locales no son inicializadas por el compilador, siendo esta tarea obligacin del programador.

5.9 Operadores
Un operador es un carcter o grupo de caracteres que acta sobre uno, dos o ms operandos para realizar una
determinada operacin generando un determinado resultado. Ejemplos tpicos de operadores son suma (+),
diferencia (-), producto (*), mayor (>), etc.

Los operadores pueden ser unarios, binarios y ternarios, segn acten sobre uno, dos o tres operandos,
respectivamente. En C# existen muchos operadores de diversos tipos (ste es uno de los puntos fuertes del lenguaje),
que se vern a continuacin.

5.9.1 Operadores Aritmticos


Los operadores aritmticos son operadores binarios y permiten indicar las operaciones de clculo bsicas. En C#
se utilizan los cinco operadores siguientes:

Suma: +
Resta:
Multiplicacin: *
Divisin: /
Resto o mdulo: %

Los operadores pueden aceptar una mezcla de operandos enteros y reales. Generalmente si ambos operandos son
enteros, el resultado es un entero. Por otro lado, si uno de los operandos es real, el resultado ser real (de tipo double
para ser ms exacto).

Si en una divisin ambos operandos son enteros, la divisin se realiza como una divisin entera, es decir, el
resultado se redondea producindose otro entero. Por ejemplo:

9/2 // se evala 4, no 4.5

Si queremos realizar una divisin real cuando ambos operadores son enteros, deberamos realizar una conversin
explcita sobre uno de los operandos para que actuara como real:
int sumaNotas = 65, numAlu = 10;
double notaMedia = sumaNotas/(double)numAlu; // da 6.5

El operador mdulo (%) devuelve el resto de la divisin entera. Es decir 13%3 devolver el valor 1. Es posible que
el valor devuelto por una expresin aritmtica sea demasiado grande como para almacenarlo en una variable de un
tipo dado. Esta situacin de desbordamiento (overflow) provoca un error en tiempo de ejecucin de forma que la

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 9

mquina virtual lanza una excepcin, que si no es capturada y tratada provoca la interrupcin del programa y la
aparicin de un mensaje de error en la consola. Las excepciones son el mecanismo bsico para el tratamiento de
errores. Las veremos.
byte k;
k = 20 * 45; // Desbordamiento: 900 > 255

Recordar que matemticamente la operacin de divisin por cero no est permitida. El resultado es un error en
tiempo de ejecucin provocando el lanzamiento de una excepcin del tipo division by zero, la cual si no es tratada, el
programa termina en ese momento con el consiguiente mensaje de error.

5.9.2 Operadores Relacionales


Una caracterstica imprescindible de cualquier lenguaje de programacin es la de considerar alternativas, esto es, la
de proceder de un modo u otro segn se cumplan o no ciertas condiciones. Los operadores relacionales permiten
estudiar si se cumplen o no esas condiciones. As pues, estos operadores producen un resultado u otro segn se
cumplan o no algunas de las condiciones que se vern a continuacin.

En el lenguaje natural, existen varias palabras o formas de indicar si se cumple o no una determinada condicin. En
informtica se ha hecho bastante general el utilizar las formas (true, false). Si una condicin se cumple, el resultado
es el valor booleano true; en caso contrario, el resultado es false.

Los operadores relacionales de C son los siguientes:

Igual que: ==
Menor que: <
Mayor que: >
Menor o igual que: <=
Mayor o igual que: >=
Distinto que: !=

Todos los operadores relacionales son operadores binarios (tienen dos operandos), y su forma general es la
siguiente:

expresion1 operador-relacional expresion2

El funcionamiento de estos operadores es el siguiente: se evalan expresion1 y expresion2, y se comparan los


valores resultantes. Si la condicin representada por el operador relacional se cumple, el resultado es true; si la
condicin no se cumple, el resultado es false.

A continuacin se incluyen algunos ejemplos de estos operadores aplicados a constantes:


(2 == 1) // Resultado false
(3 <= 3) // Resultado true
(3 < 3) // Resultado false
(1 != 1) // Resultado false

Los caracteres pueden usarse como operandos, ya que lo que se compara son los valores numricos correspondientes
a su cdigo de representacin. Por ejemplo:

'A' < 'G' // el resultado es true ya que se evala la expresin 65 < 71

Para las cadenas de caracteres, objetos de tipo string y por tanto de tipo referencia, los operadores de igualdad (== y
!=) se han definido para comparar los valores que referencian los objetos string, en lugar de comparar si dichas
referencias sealan al mismo lugar de memoria. De esta forma la comparacin es lexicogrfica que es lo que
generalmente se pretende al comprobar la igualdad o la desigualdad entre cadenas.

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 10

Si se quiere comparar si una cadena es lexicogrficamente menor o mayor que otra, no podemos utilizar los
operadores de relacin; es necesario utilizar mtodos de la clase string para tal fin. Aunque hay varios mtodos, uno
de ellos es el siguiente:

public static int Compare (string strA, string strB);

Este mtodo usa como argumentos las dos cadenas a comparar, y retorna un nmero negativo si la primera cadena es
menor que la segunda, un nmero positivo si la primera cadena es mayor que la segunda, y cero si ambas cadenas
son iguales. As, el siguiente ejemplo provoca la salida en pantalla del mensaje: Mayor.
string st1 = "PEPE";
string st2 = "PEPA";
if(String.Compare(st1,st2) > 0)
Console.WriteLine("Mayor");

5.9.3 Operadores Lgicos


Los operadores lgicos son operadores que permiten combinar expresiones lgicas, dando como resultado un valor
booleano de verdadero o falso (true o false). Existen cuatro operadores lgicos:

Operador negacin (NOT): !


Operador conjuncin (AND): &&
Operador disyuncin (OR): ||
Operador OR exclusivo (XOR): ^

El operador negacin es un operador unario, el cual niega el valor lgico del operando sobre el que acta. Si el
operando es true da como resultado false, y si es false se devuelve true.

La forma general de los operadores OR, AND y XOR es:


expresion1 || expresion2
expresion1 && expresion2
expresion1 ^ expresion2

El operador && devuelve true si tanto expresion1 como expresion2 son verdaderas y false en caso contrario; es
decir, si una de las dos expresiones o las dos son falsas el resultado es falso. Por otra parte, el operador || devuelve
true si al menos una de las expresiones es cierta. El operador ^ devuelve true si una de las expresiones es verdadera
y la otra falsa; si las dos expresiones son verdaderas o las dos falsas, el resultado se evala como falso.

Es importante tener en cuenta que el compilador de C# trata de optimizar la ejecucin de estas expresiones, lo cual
puede tener a veces efectos no deseados. Por ejemplo: para que el resultado del operador && sea verdadero, ambas
expresiones tienen que ser verdaderas; si se evala expresion1 y es falsa, ya no hace falta evaluar expresion2, y de
hecho no se evala. Algo parecido pasa con el operador ||: si expresion1 es verdadera, ya no hace falta evaluar
expresion2.

Los operadores && y || se pueden combinar entre s (quizs agrupados entre parntesis), dando a veces un cdigo de
difcil interpretacin. Por ejemplo:
bool r;
r = (2==1) || (-1==-1) // El resultado es true
r = (2==2) && (3==-1) // El resultado es false
r = ((2==2) && (3==3)) || (4==0) // El resultado es true
r = ((6==6) || (8==0)) && ((5==5) && (3==2)) // El resultado es false

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 11

5.9.4 Operadores a Nivel de Bits


C# soporta un completo juego de operadores a nivel de bits, por lo que podemos realizar tareas al igual que se puede
hacer en ensamblador. Las operaciones a nivel de bits nos permiten comprobar, asignar o desplazar los bits reales
que componen un dato de tipo entero. Los operadores son:

Operador Accin
& AND
| OR
^ XOR (OR exclusivo)
Complemento a uno
>> Desplazamiento a la derecha
<< Desplazamiento a la izquierda.

Los operadores AND, OR, XOR y complemento a uno, estn gobernados por la mismas reglas que sus equivalentes
lgicos, excepto en que trabajan bit a bit. El bit uno se considera true y el bit cero false.

Los operandos para los operadores &, | y ^ tienen que ser de un tipo entero o bool, y para los desplazamientos el
primer operando debe ser tipo int, uint, long o ulong y el segundo tipo int.

Los operadores a nivel de bits son frecuentes usados en aplicaciones de controladores de dispositivos. Veamos con
algunos ejemplos los usos ms frecuentes de los operadores a nivel de bits.

El operador & (AND) se suele utilizar para desactivar (poner a cero) los bits de un operando mediante la mscara de
otro operando. Ejemplo: para desactivar los bits 3 y 4 de una variable A, podemos emplear la mscara de un
operando B que tenga los bits 3 y 4 un cero y en los dems bits un uno.

int tira = 0xCC; // 000000000000000000000000 1 1 0 0 1 1 0 0


int mascara = 0x7FFFFFF3; // 011111111111111111111111 1 1 1 1 0 0 1 1
int resultado;
resultado = tira & mascara; // 000000000000000000000000 1 1 0 0 0 0 0 0

Tambin se puede utilizar para conocer el valor de un determinado bit de un operando, mediante la mscara de otro
operando. Ejemplo: para conocer el valor del bit 3 de una variable A, podemos emplear la mscara de un operando
B que tenga un uno en el bit 3 y ceros en el resto de los bits.
int tira = 0xCC; // 000000000000000000000000 1 1 0 0 1 1 0 0
int mascara = 0x4; // 000000000000000000000000 0 0 0 0 0 1 0 0
int resultado;
resultado = tira & mascara; // 000000000000000000000000 0 0 0 0 0 1 0 0

El operador | (OR) se puede utilizar para activar (poner a uno) los bits de un operando, mediante la mscara de otro
operando. Ejemplo: para activar los bits 5 y 7 de una variable A, podemos emplear la mscara de un operando B
que tenga los bits 5 y 7 a uno y cero en los dems bits.
int tira = 0x8C; // 000000000000000000000000 1 0 0 0 1 1 0 0
int mascara = 0x50; // 000000000000000000000000 0 1 0 1 0 0 0 0
int resultado;
resultado = tira | mascara; // 000000000000000000000000 1 1 0 1 1 1 0 0

El operador ^ (XOR) se puede utilizar para cambiar el valor de los bits de un operando, mediante la mscara de otro
operando. Ejemplo: para cambiar los bits 1 y 3 de una variable A, se puede emplear la mscara de un operando B
que tenga en los bits 1 y 3 un uno, y en los dems bits un cero.
int tira = 0xCC; // 000000000000000000000000 1 1 0 0 1 1 0 0
int mascara = 0x5; // 000000000000000000000000 0 0 0 0 0 1 0 1
int resultado;
resultado = tira ^ mascara; // 000000000000000000000000 1 1 0 0 1 0 0 1

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 12

El operador ~ ( NOT o complemento a uno) es unario y cambia los bits de su operando. Ejemplo: para cambiar
todos los bits de una variable A se le aplica el operador ~.
int tira = 0xCC; // 000000000000000000000000 1 1 0 0 1 1 0 0
int resultado;
resultado = ~ tira; // 111111111111111111111111 0 0 1 1 0 0 1 1

Los operadores de desplazamiento, >> y <<, mueven todos los bits de una variable a la derecha o a la izquierda,
segn se especifique. La forma general de una sentencia de desplazamiento a la derecha es:

variable >> nmero de desplazamientos;

A medida que se desplazan los bits hacia un extremo se van rellenando con ceros por el extremo opuesto. Los bits
que salen se pierden, y entran ceros. Sin embargo, un desplazamiento a la derecha de un nmero negativo introduce
unos.

int x; bits de x valor de x


x = 7 0...0 0 0 0 0 0 1 1 1 7
x = x << 1 0...0 0 0 0 0 1 1 1 0 14
x = x << 3 0...0 0 1 1 1 0 0 0 0 112
x = x >> 5 0...0 0 0 0 0 0 0 1 1 3

5.9.5 Operadores Incrementales


Los operadores incrementales (++) y (--) son operadores unarios que incrementan o disminuyen en una unidad el
valor de la variable a la que afectan. Estos operadores pueden ir inmediatamente delante o detrs de la variable. Si
preceden a la variable, sta es incrementada antes de que el valor de dicha variable sea utilizado en la expresin en
la que aparece. Si es la variable la que precede al operador, la variable es incrementada despus de ser utilizada en la
expresin. A continuacin se presenta un ejemplo de estos operadores:
int i = 2;
int j = 2;
int k = 5;
int m, n, p;
m = i++; // m toma 2 e i toma 3
n = ++j; // j toma 3 y n toma 3
p = k++ + 10 // p toma 15 y k toma 6
p = ++k + 10 // k toma 7 y p toma 17

Estos operadores son muy utilizados. Es importante entender muy bien por qu los resultados m y n del ejemplo
anterior son diferentes.

5.9.6 Operadores de Asignacin


Los operadores de asignacin asignan a una variable (es decir, depositan en la zona de memoria correspondiente a
dicha variable) el resultado de una expresin o el valor de otra variable (en realidad, una variable es un caso
particular de una expresin).

El operador de asignacin ms utilizado es (=), que no debe ser confundido con la igualdad matemtica, se utiliza
con el siguiente formato:
variable = expresion;

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 13

El funcionamiento es como sigue: se evala expresin y el resultado se deposita en variable, sustituyendo cualquier
otro valor que hubiera en esa posicin de memoria anteriormente. Una posible utilizacin de este operador es como
sigue:
variable = variable + 1;

Desde el punto de vista matemtico este ejemplo no tiene sentido (Equivale a 0 = 1!), pero s lo tiene considerando
que en realidad el operador de asignacin (=) representa una sustitucin; en efecto, se toma el valor de variable
contenido en la memoria, se le suma una unidad y el valor resultante vuelve a depositarse en memoria en la zona
correspondiente al identificador variable, sustituyendo al valor que haba anteriormente.

El resultado ha sido incrementar el valor de variable en una unidad.

Existen unas variaciones del operador (=). Estos operadores simplifican algunas operaciones recurrentes sobre una
misma variable. Su forma general es:
variable op= expresin;

donde op representa cualquiera de los operadores (+ , -, *, /, %, &, |, ^, <<, >>). La expresin anterior es equivalente
a:
variable = variable op expresin;

A continuacin se presentan algunos ejemplos con estos operadores de asignacin:


distancia += 1; equivale a: distancia = distancia + 1;
rango /= 2.0 equivale a: rango = rango /2.0
x *= 3.0 * y - 1.0 equivale a: x = x * (3.0 * y - 1.0)
n &= 0xF2A3 equivale a: n = n & 0xF2A3
k >>= 3 equivale a: k = k >> 3

La operacin de asignacin es en s misma una expresin cuyo valor es el almacenado en el operando de la


izquierda. As, una operacin de asignacin se puede usar como el operando derecho de otra expresin de
asignacin. Cualquier nmero de asignaciones se pueden concatenar para formar una expresin. Por ejemplo:
int m, n, p;
m = n = p = 25; // Significa m = ( n = ( p = 25));
m =(n = p = 25) + 2; // Significa m = ( n = ( p = 25)) + 2;

5.9.7 Operador Condicional


El operador condicional ? es un operador ternario, es decir, tiene tres operandos. Su forma general es:
Exp1 ? Exp2 : Exp3

Donde Exp1 debe ser una expresin booleana. El operador ? acta de la siguiente forma: Se evala Exp1 como una
condicin lgica. Si el resultado es true, la Exp2 es evaluada y su resultado se toma como resultado de la expresin
total. En caso contrario, se evala la Exp3, siendo ste el resultado final. Ejemplo:
int a = 1;
int b = 2;
int min;
min = (a < b ? a : b); // min recibe 1

Hay que tener en cuenta que slo una de las dos expresiones (Exp2 o Exp3) es evaluada. Esto hay que tenerlo en
cuenta cuando por ejemplo en estas expresiones se producen cambios en los valores de variables. Ejemplo:
min = (a < b ? a++ : b++);

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 14

la variable a es incrementada ya que se evala a++. La variable b mantiene su valor ya que b++ no se evala. Ya
que la operacin condicional es en s misma una expresin, se puede usar como una expresin de otra operacin
condicional, es decir, las expresiones condicionales se pueden anidar una dentro de otras. Por ejemplo:

int a = 1;
int b = 2;
int c = 3;
int min;
min = (a < b ? (a < c ? a : c) : (b < c ? b : c));

5.9.8 Operadores de Informacin de Tipos


De todos los operadores que permiten obtener informacin sobre tipos de datos el ms importante es el operador
typeof, cuya forma de uso es:
typeof(nombreTipo)

El operador devuelve un objeto de la clase System.Type con informacin sobre el tipo de nombreTipo. Esta
informacin se puede consultar a travs de las propiedades de los objetos de la clase Type, incluyendo detalles tales
como cules son sus miembros, cul es su tipo padre o a qu espacio de nombres pertenece.

El operador is permite determinar si una expresin es de un tipo u otro. Su sintaxis es:


expresin is nombreTipo

El significado es el siguiente: se evala expresin. Si el resultado de sta es del tipo o compatible con el tipo cuyo
nombre se indica en nombreTipo se devuelve true; y si no, devuelve false. Este operador se suele utilizar con
mtodos polimrficos. Veamos un ejemplo:
using System;
using System.Collections.Generic;
using System.Text;

namespace OperTipos
{
class MiClase
{ }
class Program
{
static void Main(string[] args)
{
Type t1, t2;
t1 = typeof(byte);
t2 = typeof(MiClase);
Console.WriteLine(t1.BaseType); // Clase base del tipo byte
Console.WriteLine(t2.Namespace); // Espacio de nombres de MiClase
MiClase mc = new MiClase();
string s = "hol";
Console.WriteLine(mc is MiClase); // evidente
//se puede concatenar un string con un char obteniendo un string?
Console.WriteLine(s + 'a' is String); // pues s.
}
}
}

La salida por pantalla es:


System.ValueType
OperTipos
True
True

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 15

5.10 Prioridad de Operadores


El orden en el que los operadores son evaluados dentro de una expresin viene determinado por las reglas de
precedencia. Estas reglas dividen a los operadores en varios niveles de prioridad que se presentarn en una tabla de
mayor a menor prioridad. Tambin se mostrar su asociatividad o comienzo de uso en el caso de tener operadores
con el mismo nivel de prioridad. En el siguiente ejemplo:
a == b + c * d

c * d se evala primero ya que el operador * tiene mayor prioridad que los operadores + y ==. El resultado se suma
a b ya que el operador + tiene mayor prioridad que ==. Por ltimo se evala el operador ==.

Una expresin entre parntesis siempre se evala primero. Los parntesis tienen mayor prioridad y son evaluados
desde los ms internos a los ms externos.

Como regla general decir que el orden de prioridad de mayor a menor es: operadores aritmticos, operadores
relacionales, operadores lgicos y por ltimo los operadores de asignacin. Respecto a las reglas de asociatividad
decir que todos los operadores asocian de izquierda a derecha, excepto los operadores unarios, el operador ternario y
el de asignacin.

La tabla siguiente resume las reglas de prioridad y asociatividad de todos los operadores. Las filas se han colocado
de mayor a menor prioridad. Los operadores escritos sobre una misma lnea tienen la misma prioridad.

5.11 Conversin de Tipos


Las conversiones entre tipos primitivos se realizan cuando en una expresin aparecen operandos de diferente tipo o
bien asignamos a una variable un valor de distinto tipo al definido para la variable. En estos casos se producen
conversiones de tipos.

As, por ejemplo, para poder sumar dos variables hace falta que ambas sean del mismo tipo. Si una es int y otra
float, el valor de la primera se convierte a float (es decir, el valor de la variable del tipo de menor rango se convierte
al tipo de mayor rango), antes de realizar la operacin. A esta conversin automtica e implcita de tipo (el
programador no necesita intervenir, aunque s conocer sus reglas), se le denomina conversin implcita o promocin,
pues la variable de menor rango es promocionada al rango de la otra.

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 16

En el caso de una asignacin, se convierte el valor de la derecha al tipo de la variable de la izquierda siempre que no
haya prdida de informacin; en otro caso el compilador presenta un mensaje de error. Si queremos realizar de todas
formas dicha conversin, aunque se pierda informacin, debemos realizar una conversin explcita o forzada. Esta
conversin, denomina tambin casting, se implementa de la forma:

(tipo) expresin

El resultado anterior es que una vez evaluada expresin, se convierte dicho valor resultante al tipo que hayamos
sealado entre parntesis.

La figura siguiente resume los tipos primitivos principales colocados de izquierda a derecha de menos a ms
precisos. Las flechas indican las conversiones implcitas permitidas.

No se permite realizar conversiones entre tipos numricos y el tipo bool.

Las conversiones en una expresin se realizan operacin a operacin siguiendo el orden de prioridad de los
operadores. Por ejemplo, en el siguiente fragmento de cdigo:

...
double valor;
char car = 'a';
int i = 2;
float f = 1.1F;
double d = 0.0001;
valor = (car / i) - (f * d) + (f / i);

Las conversiones que se realizan son:

(char/int) -> int; (float*double) -> double; (float/int) -> float


int + double + float
double + float
double

En la primera operacin (car / i) el valor del cdigo UNICODE del carcter a (97), se convierte a tipo int ya que la
constante 2 es de tipo int. La divisin de enteros da como resultado otro entero, en este caso el resultado de esta
divisin es 48.

En el ejemplo, la variable valor est declarada como double, por lo que en la asignacin de la expresin no habra
conversin de tipo. Qu hubiera pasado si la variable valor se hubiera declarado de tipo int?. Pues que el resultado
se hubiera tenido que convertir de double a int, proceso en el que se producira prdida de informacin generndose
un error de compilacin. Si de todas formas deseamos realizar la conversin debera hacerse de forma explcita. En
el siguiente ejemplo,

double masa = 4.67;


int k = (int)1.7 + (int)masa;

la variable masa siempre ser de tipo double. Con el casting se logra que en la expresin slo se opere con la parte
entera de la variable. La constante 1.7 (que es de tipo double) intervendr en la expresin slo con su valor entero (1
en este caso). En este ejemplo
char letra = 'A';
letra = (char)(1 + letra);
char minuscula = (char)(letra + ('a' - 'A'));

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 17

la variable minscula almacenar el carcter b.

Las conversiones tambin se pueden realizar entre otros objetos que no sean de tipo primitivo. Normalmente se
realizan entre objetos que pertenecen a una misma jerarqua de clases. Por ejemplo, cualquier objeto de la clase que
sea, siempre se puede convertir de forma implcita a tipo Object, ya que esta clase es la clase base para cualquier
objeto. En general una conversin implcita, la permitida directamente, se puede realizar a un tipo base o padre del
tipo del objeto a convertir. Ejemplo:

string s = "hola";
Object ob = s; // Conversin implcita.

Las conversiones explcitas entre objetos tambin se pueden hacer, siempre que el compilador pueda realizar dicha
conversin, ya que si no es as, se lanzara una excepcin durante la ejecucin del tipo InvalidCast.

Existe otro operador que permite realizar operaciones de conversin de forma muy similar al ya visto. Este operador
es el operador as, que se usa as:

expresion as tipoDestino

La forma de operar es la siguiente: si la expresin es convertible a tipoDestino, se realiza la conversin, siendo sta
el resultado; si la conversin no es posible el resultado es null. El uso del operador as sera equivalente a la siguiente
expresin:

expresion is tipoDestino ? (tipoDestino)expresin : null;

Como vemos si expresin es del tipo o compatible con tipoDestino, se realiza la conversin de forma explcita y se
retorna sta; si no es posible la conversin, se retorna null.

El operador as slo es aplicable a tipos referencia y a aquellos casos en que existan conversiones predefinidas en el
lenguaje. Como veremos en otro tema, esto slo incluye conversiones entre un tipo y tipos padres suyos y entre un
tipo y tipos hijos suyos; es decir, entre tipos pertenecientes a una jerarqua de clases.

En el ejemplo que vimos anteriormente sobre el operador is

. . .
string s = "hol";
Console.WriteLine(s + 'a' is String);

La salida en pantalla era true ya que is evala si la expresin es de tipo string o compatible con el tipo string. Si
aadimos la sentencia siguiente:
Console.WriteLine(s + 'a' as String);

La salida en pantalla sera hola ya que al ser la expresin compatible con el tipo string, se ha retornado el valor del
resultado de dicha conversin.

5.12 Sentencias de Control


En principio, las sentencias de un programa se ejecutan secuencialmente, es decir, una a continuacin de la anterior
empezando por la primera y acabando por la ltima. El lenguaje C# dispone de varias sentencias para modificar este
flujo secuencial de la ejecucin. Las ms utilizadas se agrupan en dos familias: las bifurcaciones o sentencias de
seleccin, que permiten elegir entre dos o ms opciones segn ciertas condiciones, y los bucles o sentencias de
iteracin, que permiten ejecutar repetidamente un conjunto de instrucciones tantas veces como se desee, cambiando
o actualizando ciertos valores.

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 18

5.12.1 Sentencias de Seleccin


Las sentencias de seleccin permiten elegir qu sentencia ser la prxima en ejecutarse.

Sentencia if
Esta sentencia de control permite ejecutar o no una sentencia simple o compuesta segn se cumpla o no una
determinada condicin. Esta sentencia tiene la siguiente forma general:
if (expresin booleana)
sentencia;

Se evala la expresin booleana. Si el resultado es verdadero (true), se ejecuta sentencia; si el resultado es


falso (false), se salta sentencia y se prosigue en la lnea siguiente. Hay que recordar que sentencia puede ser
una sentencia simple o compuesta. Ejemplo:
if (x != 0)
b = a / x;
b++;

La sentencia b = a/x se ejecutar si la condicin (x != 0) es verdadera y no se ejecutar si es falsa. En cualquier


caso se ejecutar la sentencia siguiente b++.

Sentencia if-else
Esta sentencia permite realizar una bifurcacin, ejecutando una parte u otra del programa segn se cumpla o no
una cierta condicin. La forma general es la siguiente:

if (expresin booleana)
sentencia_1;
else
sentencia_2;

Se evala expresin. Si el resultado es verdadero (true), se ejecuta sentencia_1 y si el resultado es falso (false),
se ejecuta sentencia_2. En cualquier caso la ejecucin contina en la siguiente sentencia ejecutable que haya a
continuacin de la sentencia if.

Las sentencias incluidas en la parte if o en la parte else pueden ser tambin sentencias de tipo if o de tipo if-
else. Esto se conoce como anidamiento. Por ejemplo:

if (valor > 0)
if (x > y)
mayor = x;
else
mayor = y;

Como vemos, el anidamiento puede mostrar confusin, ya que en principio podemos dudar en determinar cual
es el if correspondiente a un else. La regla es que cada else se corresponde con el if ms prximo que no est
asociado ya con un else. En el ejemplo el else se corresponde con el segundo if (x >y).

Si la lgica de la solucin impusiera que el else del ejemplo anterior se correspondiera con el primero de los if,
(if (valor>0 )), tenemos dos soluciones. La primera sera forzando a que cada if tenga un else:
if (valor > 0)
if (x > y)
mayor = x;
else
;
else
mayor = y;

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 19

Hemos forzado al if interior con un else colocando una sentencia vaca (;). La otra solucin es crear un bloque
que separe el else del if no deseado. Ahora el else no tiene conocimiento del if(x>y), ya que pertenecen a
bloques distintos. Pero lo mejor siempre consiste en hacer lo requerido de la forma ms sencilla.


Sentencia if-else mltiple.
Esta sentencia permite realizar una ramificacin mltiple, ejecutando una entre varias partes del programa
segn se cumpla una entre varias condiciones. La forma general es la siguiente:
if (expresion_1)
sentencia_1;
else if (expresion_2)
sentencia_2;
else if (...)
...
[else
sentencia_n;]

Se evala expresin_1. Si el resultado es verdadero, se ejecuta sentencia_1. Si el resultado es falso, se salta


sentencia_1 y se evala expresin_2. Si el resultado es verdadero se ejecuta sentencia_2, mientras que si es
falso, se evala expresion_3 y as sucesivamente. Si ninguna de las expresiones o condiciones es verdadera, se
ejecuta sentencia_n que es la opcin por defecto (puede ser la sentencia vaca, y en ese caso puede eliminarse
junto con la palabra else). Todas las sentencias pueden ser simples o compuestas. Ejemplo:

using System;
using System.Collections.Generic;
using System.Text;
namespace prueba
{
class Program
{
static void Main(string[] args)
{
int valor;
Console.Write("Teclee un nmero entero entre 0 y 2: ");
valor = Int32.Parse(Console.ReadLine());
if (valor == 0)
Console.WriteLine("Puls cero");
else if (valor == 1)
Console.WriteLine("Puls uno");
else if (valor == 2)
Console.WriteLine("Puls dos");
else
Console.WriteLine("Fuera de rango");
Console.ReadLine();
}
}
}

Sentencia switch
La sentencia que se va a describir a continuacin desarrolla una funcin similar a la de la sentencia if ... else
con mltiples ramificaciones. Esta sentencia permite ejecutar una de varias acciones, en funcin del valor de
una expresin. Su sintaxis es:
switch (expresion)
{
case expresion_cte_1:
[sentencia_1;]
case expresion_cte_2:
[sentencia_2;]
...
case expresion_cte_n:
[sentencia_n;]
[default:]
[sentencia;]

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 20

donde expresin es una expresin de tipo entero, enumerado o string y las expresiones_constantes es una
constante del mismo tipo que expresin o de un tipo que se pueda convertir implcitamente al tipo de
expresin; las sentencias pueden ser simples o compuestas. En el caso de que se trate de una sentencia
compuesta, no hace falta incluir entre llaves las sentencias simples que la forman.

La sentencia switch evala expresin y compara su valor con las constantes de cada case de la siguiente forma:
si dicho valor coincide con el valor constante expresion_cte_1, se ejecuta sentencia_1, y contina hasta una
sentencia que transfiera el control fuera o dentro del bloque switch; esta sentencia debe estar presente por cada
case as como para default. Generalmente se usa break para transferir el control fuera del bloque de la
sentencia switch. Si el resultado coincide con el valor constante expresion_cte_2, se ejecuta sentencia_2 hasta
encontrar una sentencia que transfiera el control fuera o dentro del bloque switch. Este mecanismo se repite
para todos los case que aparezcan. Si ninguna expresion_cte coincide con el valor de expresin, se ejecuta la
sentencia que est a continuacin de default si esta clusula ha sido especificada.

La sentencia switch muchas veces produce un cdigo ms legible que si hubiramos usado una estructura else-
if equivalente. As el ejemplo anterior se puede reescribir usando una sentencia switch :

switch (valor)
{
case 0:
Console.WriteLine("Puls cero");
break;
case 1:
Console.WriteLine("Puls uno");
break;
case 2:
Console.WriteLine("Puls dos");
break;
default:
Console.WriteLine("Fuera de rango");
break;
}

Se puede tener un switch formando parte de la secuencia de sentencias de otro switch. Incluso si las constantes
case del switch interior y del exterior contienen valores comunes, no aparecen conflictos, como por ejemplo:
switch(x)
{
case 1:
switch(y)
{
case 0:
Console.WriteLine("Error de divisin por cero");
break;
case 1:
dividir(x,y);
break;
}
break;
case 2:
......

Si se quiere ejecutar la misma sentencia para varios valores del resultado de la expresin, se puede hacer
poniendo varios case expresion_cte seguidos. Ejemplo:
switch (valor)
{
case 0:
case 1:
Console.WriteLine("Menor que 2");
break;
case 2:
Console.WriteLine("Igual a 2");
break;
default:
Console.WriteLine("Fuera de rango");
break;

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 21

5.12.2 Sentencias de Iteracin


El lenguaje C# dispone de varias sentencias que permiten repetir una serie de veces la ejecucin de unas lneas de
cdigo. Esta repeticin se realiza, bien un nmero determinado de veces, bien hasta que se cumpla una determinada
condicin. De modo genrico, a estas sentencias se les denomina bucles.

Sentencia while
Esta sentencia permite ejecutar repetidamente, mientras se cumpla una determinada condicin, una sentencia o
bloque de sentencias. La forma general es como sigue:

while (condicin)
sentencia;

Se evala la condicin, si el resultado es falso la sentencia no se ejecuta y se pasa el control a la siguiente


sentencia en el programa. Si el resultado es verdadero se ejecuta sentencia y se vuelve a repetir el proceso
descrito volviendo a evaluarse la condicin. Evidentemente, alguna vez la condicin se evaluar como falsa
para que el bucle acabe, pues si no, continuara indefinidamente. Es decir, mientras la condicin se evale
como verdadera, sentencia se ejecutar. Si la condicin se evala como falsa la primera vez, sentencia no se
llegar a ejecutarse nunca.

Los bucles while normalmente se utilizan cuando no se conoce con exactitud el nmero de iteraciones que se
deben realizar. Una manera de terminar la ejecucin de un bucle while cuando el usuario debe introducir una
secuencia de datos, es usar un valor centinela como ltimo dato. La condicin del bucle compara cada dato con
el valor centinela y termina cuando el usuario teclea el valor centinela. Hay que tener cuidado en elegir
adecuadamente el valor centinela.

El siguiente ejemplo calcula la media de una serie de notas.


using System;
using System.Collections.Generic;
using System.Text;
namespace BucleWhile1
{
class Program
{
static void Main(string[] args)
{
double nota, suma = 0.0;
int cuenta = 0;
Console.Write("Introduzca nota [-1 para salir]: ");
nota = Double.Parse(Console.ReadLine());
while (nota != -1) // el valor centinela es -1
{
if (nota >= 0 && nota <= 10)
{
suma += nota;
cuenta++;
}
else
Console.WriteLine("Valor incorrecto");
Console.Write("Introduzca nota [-1 para salir]: ");
nota = Double.Parse(Console.ReadLine());
}
if (cuenta > 0)
Console.WriteLine("La media es {0:f2}", suma / cuenta);
else
Console.WriteLine("Sin datos...");
Console.ReadLine();
}
}

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 22

Los conmutadores, banderas o flags tambin permiten controlar el nmero de iteraciones de un bucle while. El
conmutador se inicializa a un valor, el cual se mantendr hasta que ocurra un suceso cambindose a otro valor.
El bucle se ejecuta mientras el conmutador no cambie de valor. Por ejemplo, calcular el valor de la funcin f(x)
= log(x) donde x debe ser mayor que cero.
using System;
using System.Collections.Generic;
using System.Text;

namespace BucleWhile2
{
class Program
{
static void Main(string[] args)
{
double l, x = 0;
bool positivo = false; // Conmutador inicializado
while (!positivo) // Mientras no cambie el mismo
{
Console.Write("Valor para x: ");
x = Double.Parse(Console.ReadLine());
positivo = (x > 0); // Cambiar a true si x es positivo
}
l = Math.Log10(x);
Console.WriteLine("Log({0}) = {1:f6}", x, l);
Console.ReadLine();
}
}
}

Sentencia do ... while


Esta sentencia funciona de modo anlogo a while, con la diferencia de que la evaluacin de la condicin se
realiza al final del bucle, despus de haber ejecutado al menos una vez sentencia. La forma general de esta
sentencia es:

do
sentencia;
while(condicin);

Se ejecuta sentencia y posteriormente se evala la condicin. Si es verdadera, se vuelve a ejecutar sentencia


volvindose a evaluar la condicin. El bucle acaba cuando la condicin se evala como falsa. Debe observarse
que hay que poner (;) a continuacin del parntesis que encierra a condicin, entre otros motivos para que esa
lnea se distinga de una sentencia while ordinaria. El ejemplo siguiente obliga a teclear una letra entre la A y la
F.
using System;
using System.Collections.Generic;
using System.Text;

namespace CicloDoWhile
{
class Program
{
static void Main(string[] args)
{
char letra;
int con = 0;
do
{
con++;
Console.Write("Introduzca una letra [A-F]: ");
letra = (char)Console.Read();
Console.ReadLine(); // Elimina \r\n del buffer
// o bien podemos hacer
// letra = Char.Parse(Console.ReadLine());
} while ((letra < 'A') || (letra > 'F'));

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 23

if (con == 1)
Console.WriteLine("Muy bien Carlos, muy bien...a la primera");
else
Console.WriteLine("Vale. A ver si nos fijamos...");
Console.ReadLine();
}
}
}

Los usos ms frecuentes del bucle do-while coinciden con los del bucle while. La diferencia es que con un
bucle do-while nos aseguramos que el bucle se ejecuta al menos una vez, ya que la condicin se evala al final.

Sentencia for
for es quizs el tipo de bucle mas verstil y utilizado del lenguaje C#. Permite ejecutar una sentencia
repetidamente un nmero determinado de veces. Su forma general es la siguiente:

for ([inicializacin]; [condicin]; [actualizacin])


sentencia;

Posiblemente la forma ms sencilla de explicar la sentencia for sea utilizando la construccin while que sera
equivalente. Dicha construccin es la siguiente:
inicializacin;
while (condicin)
{
sentencia;
actualizacin;
}

Antes de iniciarse el bucle se ejecuta inicializacin, que es una o ms sentencias que asignan valores iniciales a
ciertas variables o contadores. A continuacin se evala condicin; si es falsa, la ejecucin prosigue en la
sentencia siguiente a la construccin for; si es verdadera, se ejecutan sentencia y actualizacin, y se vuelve a
evaluar condicin. El proceso prosigue hasta que condicin sea falsa.

Normalmente la parte de actualizacin sirve para actualizar variables o incrementar contadores. Un ejemplo
tpico puede ser la suma de los 10 primeros nmeros naturales:

for (s = 0, i = 1; i <= 10; i++)


s += i;

Primeramente se inicializa la variable s a cero y la variable i a 1; el ciclo se repetir mientras que i sea menor o
igual que 10, y al final de cada ciclo el valor de i se incrementar en una unidad. En total, el bucle se repetir
10 veces.

La ventaja de la construccin for sobre la construccin while equivalente est en que en la cabecera de la
construccin for se tiene toda la informacin sobre como se inicializan, controlan y actualizan las variables del
bucle.

El bucle for implementado en C# es mucho ms potente que su equivalente en otros lenguajes. Realmente,
todas las sentencias que forman parte del bucle, lo que hemos llamado inicializacin, condicin y
actualizacin, pueden ser cualquier sentencia vlida de C#. Adems las tres partes anteriores no son
obligatorias de usar. Veamos unos ejemplos:
for(int x = 0; x != 123;)
x = Int32.Parse(Console.ReadLine()); // Se ejecuta hasta que se teclea 123

El ejemplo siguiente imprime las letras del abecedario en orden inverso

char car;
for (car = 'z'; car >= 'a'; car--)
{
Console.WriteLine(car);

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 24

if (car == 'o')
Console.WriteLine('');
}

En el siguiente ejemplo se presenta en pantalla un contador que desciende hasta 1 y que empieza por el valor
correspondiente al nmero de caracteres de una cadena previamente leda desde teclado.
string s = Console.ReadLine(); // Se lee una cadena
int l = s.Length; // Obtiene la longitud de la cadena
for (; l>0; )
{
Console.WriteLine(l);
l--;
}

Uno de los posibles usos del bucle for, aunque nada recomendable, es la de poder construir bucles infinitos.
Esto se puede conseguir dejando la expresin condicional vaca. Por ejemplo:
for (;;)
{
c = Char.Parse(Console.ReadLine());
if (c == 'A')
break; // Salir del bucle
}

Una sentencia, segn la sintaxis de C#, puede estar vaca. Esto supone que el cuerpo de un bucle pueda estar
vaco.
for (t = 0; t < VALOR; t++); // Crea un bucle de retardo temporal.

En este ejemplo se leen caracteres de teclado hasta que se pulsa 's' o 'n':
char c;
for (c = Char.Parse(Console.ReadLine());
c != 's' && c != 'n';
c = Char.Parse(Console.ReadLine()));

Sentencia foreach
Permite repetir un grupo de sentencias para cada elemento de un array o de una coleccin. Esta sentencia la
usaremos cuando estudiemos dichas estructuras de datos.

5.12.3 Bucles Anidados


Los bucles anidados constan de un bucle externo con uno o ms bucles internos. Cada vez que se realiza una
iteracin del bucle externo, se realizan todas las iteraciones del interno.

El siguiente ejemplo obtiene por pantalla la tabla de multiplicar del 1 al 10. Para ello se usan dos bucles. El bucle
que usa la variable x como variable de control se denomina bucle externo y el bucle con la variable de control y se
llama bucle interno. Para cada valor de x del bucle externo, se ejecuta el bucle interno iterando todos los valores de
y, y se realiza un salto de lnea para separar cada una de las 10 tablas.
using System;
using System.Collections.Generic;
using System.Text;

namespace BucleAnidado1
{
class Program
{
static void Main(string[] args)
{
const int MAX = 10;

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 25

int x, y, p;
for (x = 1; x <= MAX; x++)
{
for (y = 1; y <= MAX; y++)
{
p = x * y;
Console.WriteLine("{0,2} * {1,2} = {2,2}", x, y, p);
}
Console.WriteLine();
}
Console.ReadLine();
}
}
}

El siguiente ejemplo dibuja en pantalla un tringulo issceles usando un carcter como relleno
using System;
using System.Collections.Generic;
using System.Text;
namespace BucleAnidado2
{
class Program
{
static void Main(string[] args)
{
const int NUMLIN = 5;
const char SIMBOLO = '*';
const char BLANCO = ' ';
int fila, con_bla, con_sim;
Console.Clear();
Console.WriteLine();
for (fila = 1; fila <= NUMLIN; fila++)
{
for (con_bla = NUMLIN - fila; con_bla > 0; con_bla--)
Console.Write("\t{0}", BLANCO);
for (con_sim = 1; con_sim < 2 * fila; con_sim++)
Console.Write("\t{0}", SIMBOLO);
Console.WriteLine();
}
Console.ReadLine();
}
}
}

La salida del programa sera:

*
* * *
* * * * *
* * * * * * *
* * * * * * * * *

La siguiente salida se obtiene al ejecutar el cdigo posterior:


54321
4321
321
21
1
using System;
using System.Collections.Generic;
using System.Text;
namespace BucleAnidado3
{
class Program
{
static void Main(string[] args)
{
int fil, col; // Filas y columnas

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 26

fil = 5;
do
{
col = fil;
do
{
Console.Write(col);
col--;
} while (col > 0);
Console.WriteLine();
fil--;
} while (fil > 0);
Console.ReadLine();
}
}
}

5.12.4 Sentencias de Salto: break, continue


Vimos como la sentencia break finaliza la ejecucin de una sentencia switch. Cuando se utiliza dentro de un bucle
while, do-while, for o foreach, realiza la misma accin: finaliza la ejecucin del bucle aunque la condicin sea
verdadera. Si se usa dentro de bucles anidados, solamente finaliza la ejecucin del bucle donde est incluida.

La sentencia continue obliga a ejecutar la siguiente iteracin del bucle donde se halla, aunque no haya terminado de
ejecutar las sentencias que incluye. Al comenzar el siguiente ciclo del bucle, se evala la condicin que controla el
bucle. En el caso que se use dentro de un bucle for, se ejecuta la parte de incremento/decremento del bucle, para
posteriormente evaluar la condicin que controla el bucle. Ejemplo:
using System;

namespace SaltoContinue
{
class Program
{
static void Main(string[] args)
{
int x;
do
{
x = Int32.Parse(Console.ReadLine());
if (x <= 0)
continue;
Console.WriteLine("Tecle el positivo " + x);
} while (x != 100);
}
}
}

5.13 Concepto de Redefinicin de un Operador


Un operador en C# no es ms que un smbolo formado por uno o ms caracteres que permite realizar una
determinada operacin entre uno o ms datos y produce un resultado. Ya hemos visto que C# cuenta con un buen
nmero de operadores que permiten realizar con una sintaxis clara e intuitiva las operaciones comunes a la mayora
de lenguajes (aritmticas, lgicas, etc.) as como otras operaciones ms particulares de C# (operador is, operador as,
etc.).

En C# viene predefinido el comportamiento de sus operadores cuando se aplican a ciertos tipos de datos. Por
ejemplo, si se aplica el operador + entre dos objetos int devuelve su suma, y si se aplica entre dos objetos string
devuelve su concatenacin. Sin embargo, tambin se permite que el programador pueda definir el significado la

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 27

mayora de estos operadores cuando se apliquen a objetos cuyos tipos haya definido l. Esto es lo que se le conoce
como redefinicin de operador.

La posibilidad de redefinir un operador no aporta ninguna nueva funcionalidad al lenguaje y slo se ha incluido en
C# para facilitar la legibilidad del cdigo. Por ejemplo, si tenemos una clase Complejo que representa nmeros
complejos podramos definir un mtodo sumar() para sus objetos de modo que a travs de l se pudiese conseguir la
suma de dos objetos de esta clase como muestra este ejemplo:

Complejo c1 = new Complejo(3,2); // c1 = 3 + 2i


Complejo c2 = new Complejo(5,2); // c2 = 5 + 2i
Complejo c3 = c1.sumar(c2); // c3 = 8 + 4i

Sin embargo, el cdigo sera mucho ms legible e intuitivo si en vez de tenerse que usar el mtodo sumar() se
redefiniese el significado del operador + para que al aplicarlo entre objetos Complejo devolviese su suma. Con ello,
el cdigo anterior quedara as:
Complejo c1 = new Complejo(3,2); // c1 = 3 + 2i
Complejo c2 = new Complejo(5,2); // c2 = 5 + 2i
Complejo c3 = c1 + c2; // c3 = 8 + 4i

sta es precisamente la utilidad de la redefinicin de operadores: hacer ms claro y legible el cdigo, no hacerlo ms
corto. Por tanto, cuando se redefina un operador es importante que se le d un significado intuitivo ya que si no
fuese as, ira contra de la filosofa de la redefinicin de operadores.

5.13.1 Definicin de Redefiniciones de Operadores.


La forma en que se redefine un operador depende del tipo de operador del que se trate, ya que no es lo mismo
redefinir un operador unario que uno binario. Sin embargo, como regla general podemos considerar que se hace
definiendo un mtodo pblico y esttico cuyo nombre sea el smbolo del operador a redefinir y venga precedido de
la palabra reservada operator. Es decir, se sigue una sintaxis de la forma:
public static <tipoDevuelto> operator <smbolo>(<operandos>)
{
<cuerpo>
}

Los modificadores public y static pueden permutarse si se desea, lo que es importante es que siempre aparezcan en
toda redefinicin de operador. Se pueden redefinir tanto operadores unarios como binarios, y en <operandos> se
ha de incluir tantos parmetros como operandos pueda tomar el operador a redefinir, ya que cada uno representar a
uno de sus operandos. Por ltimo, en <cuerpo> se han de escribir las instrucciones a ejecutar cada vez que se
aplique la operacin cuyo operador se identifica con <smbolo> a los operandos indicados en <operandos>.

<tipoDevuelto> no puede ser void, pues por definicin toda operacin tiene un resultado, por lo que todo
operador ha de devolver algo. Adems, los operadores no pueden redefinirse con total libertad ya que ello
dificultara innecesariamente la legibilidad del cdigo, por lo que se han introducido las siguientes restricciones al
redefinirlos:

Al menos uno de los operandos ha de ser del mismo tipo de dato del que sea miembro la redefinicin del
operador.
No puede alterarse sus reglas de precedencia, asociatividad, ubicacin y nmero de operandos, pues si ya de
por s es difcil para muchos recordarlas cuando son fijas, mucho ms lo sera si pudiesen modificarse segn
los tipos de sus operandos.
No pueden definirse nuevos operadores ni combinaciones de los ya existentes con nuevos significados (por
ejemplo ** para representar exponenciacin), pues ello complicara innecesariamente el compilador, el
lenguaje y la legibilidad del cdigo cuando en realidad es algo que puede simularse definiendo mtodos.
No todos los operadores incluidos en el lenguaje pueden redefinirse, pues muchos de ellos (como ., new,
=, etc.) son bsicos para el lenguaje y su redefinicin es inviable, poco til o dificultara innecesariamente

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 28

la legibilidad del cdigo. Adems, no todos los redefinibles se redefinen usando la sintaxis general hasta
ahora vista. Cuando se necesite, se comentarn cules son las peculiaridades de aquellos que requieran una
redefinicin especial.

5.13.2 Redefinicin de Operadores Binarios


Los operadores binarios redefinibles son +, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >= y <= . Toda redefinicin que
se haga de ellos ha de tomar dos parmetros tales que al menos uno de ellos sea del mismo tipo que el tipo de dato
del que es miembro la redefinicin.

Hay que tener en cuenta que aquellos operadores que tengan complementario, siempre han de redefinirse junto con
ste. As, siempre que se redefina el operador > tambin ha de redefinirse en l el operador <, siempre que se
redefina >= ha de redefinirse <=, y siempre que se redefina == ha de redefinirse !=.

Tambin hay que sealar que, como puede deducirse de la lista de operadores binarios redefinibles, no se pueden
redefinir directamente ni el operador de asignacin = ni los operadores compuestos (+=, -=, etc.) Sin embargo, en el
caso de estos ltimos dicha redefinicin ocurre de manera automtica al redefinir su parte no = Es decir, al
redefinir + quedar redefinido consecuentemente +=, al redefinir * lo har *=, etc.

A continuacin se muestra cmo se redefinira el operador + para los objetos Complejo:


class Complejo
{
public float parteReal;
public float parteImaginaria;

public void imprimirComplejo()


{
Console.WriteLine("{0} + {1}i", parteReal, parteImaginaria);
}

public Complejo() { }

public Complejo(float pReal, float pImaginaria)


{
parteReal = pReal;
parteImaginaria = pImaginaria;
}

public static Complejo operator +(Complejo op1, Complejo op2)


{
Complejo resultado = new Complejo();
resultado.parteReal = op1.parteReal + op2.parteReal;
resultado.parteImaginaria = op1.parteImaginaria + op2.parteImaginaria;
return resultado;
}
}

Es fcil ver que lo que en el ejemplo se ha redefinido es el significado del operador + para que cuando se aplique
entre dos objetos de clase Complejo devuelva un nuevo objeto Complejo cuyas partes real e imaginaria sean la suma
de las de sus operandos.

5.13.3 Redefinicin de Operadores Unarios


Los nicos operadores unarios redefinibles son: !, +, -, ~, ++, --, true y false. Toda redefinicin de un operador
unario ha de tomar un nico parmetro que ha de ser del mismo tipo que el tipo de dato al que pertenezca la
redefinicin.

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 29

Los operadores ++ y -- siempre han de redefinirse de manera que el tipo de dato del objeto devuelto sea igual al del
tipo en donde se define el operador. Cuando se usen de forma postfija, lo que har el compilador ser devolver el
objeto original que se les pas como parmetro en lugar del indicado en la sentencia return; y cuando se usen de
forma prefija se devolver el objeto creado y devuelto por return. Por ello es importante no modificar dicho
parmetro si es de un tipo referencia y queremos que estos operadores tengan su significado tradicional. Un ejemplo
de cmo hacerlo es la siguiente redefinicin de ++ para el tipo Complejo.
public static Complejo operator ++ (Complejo op)
{
Complejo resultado = new Complejo(op.ParteReal + 1, op.ParteImaginaria);
return resultado;
}

El siguiente cdigo hace uso de la clase Complejo mostrando cmo se usa la sobrecarga:
class PruebaComplejo
{
static void Main(string[] args)
{
Complejo c1 = new Complejo(1, 2);
Complejo c2 = new Complejo(3, 4);
Complejo c3 = c1 + c2;
c3.imprimirComplejo(); // 4+6i
Complejo c4, c5;
c4 = c1++; // Se retorna el original c1
c1.ImprimirComplejo(); // 2+2i
c4.ImprimirComplejo(); // 1+2i
c5 = ++c2; // Se retorna el c2 modificado
c2.ImprimirComplejo(); // 4+4i
c5.ImprimirComplejo(); // 4+4i
}
}

Respecto a los operadores true y false, estos indican respectivamente, cuando se ha de considerar que un objeto
representa el valor lgico cierto y cuando se ha de considerar que representa el valor lgico falso, por lo que sus
redefiniciones siempre han de devolver un objeto de tipo bool que indique dicha situacin. Adems, si se redefine
uno es obligatorio redefinir tambin el otro, pues siempre es posible usar indistintamente uno u otro para determinar
el valor lgico que un objeto de ese tipo represente.

En realidad los operadores true y false no pueden usarse directamente en el cdigo fuente, sino que redefinirlos para
un tipo de dato es til porque permiten utilizar objetos de ese tipo en expresiones condicionales tal y como si de un
valor lgico se tratase. Por ejemplo, podemos redefinir estos operadores en el tipo Complejo de modo que
consideren cierto a todo complejo distinto de 0 + 0i y falso a 0 + 0i:
public static bool operator true(Complejo op)
{
return (op.ParteReal != 0 || op.ParteImaginaria != 0);
}

public static bool operator false(Complejo op)


{
return (op.ParteReal == 0 && op.ParteImaginaria == 0);
}

Con estas redefiniciones, un cdigo como el que sigue mostrara por pantalla el mensaje Es cierto:
Complejo c1 = new Complejo(1, 0); // c1 = 1 + 0i
if (c1) Console.WriteLine(Es cierto);

Colegio San Jos Juan V. Madrid Jurado


Manual de C# 30

5.13.4 Redefinicin de Operadores de Conversin


Ya vimos que para convertir objetos de un tipo de dato en otro se puede usar un operador de conversin que tiene la
siguiente sintaxis:

(<tipoDestino>) <expresin>

Lo que este operador hace es devolver el objeto resultante de convertir al tipo <tipoDestino> el objeto resultante
de evaluar <expresin>. Para que la conversin pueda aplicarse es preciso que exista alguna definicin de cmo
se ha de convertir a <tipoDestino> los objetos del tipo resultante de evaluar <expresin>.

Las redefiniciones de operadores de conversin pueden ser de dos tipos:



Explcitas: La conversin slo se realiza cuando se usen explcitamente los operadores de conversin antes
comentados.
Implcitas: La conversin se realiza automticamente cada vez que se asigne un objeto de ese tipo de dato a un
objeto del tipo <tipoDestino>. Estas conversiones son ms cmodas que las explcitas pero tambin ms
peligrosas ya que pueden ocurrir sin que el programador se d cuenta. Por ello, slo deberan definirse como
implcitas las conversiones seguras en las que no se puedan producir excepciones ni perderse informacin al
realizarlas.

La sintaxis que se usa para hacer redefinir una operador de conversin es parecida a la usada para cualquier otro
operador slo que no hay que darle nombre, toma un nico parmetro y hay que preceder la palabra reservada
operator con las palabras reservadas explicit o implicit segn se defina la conversin como explcita o implcita. Por
ejemplo, para definir una conversin implcita de Complejo a float podra ser:
public static implicit operator float(Complejo op)
{
return op.ParteReal;
}

Vemos como el tipo del parmetro usado al definir la conversin se corresponde con el tipo de dato del objeto al que
se puede aplicar la conversin (tipo origen), mientras que el tipo del valor devuelto ser el tipo al que se realice la
conversin (tipo destino) Con esta definicin podran escribirse cdigos como el siguiente:
Complejo c1 = new Complejo(5,2); // c1 = 5 + 2i
float f = c1; // f = 5

Ntese que en la conversin de Complejo a float se pierde informacin (la parte imaginaria), por lo que sera mejor
definir la conversin como explcita sustituyendo en su definicin la palabra reservada implicit por explicit. En ese
caso, el cdigo anterior habra de cambiarse por:
Complejo c1 = new Complejo(5,2); // c1 = 5 + 2i
float f = (float) c1; // f = 5

Por otro lado, si lo que hacemos es redefinir la conversin de float a Complejo de forma implcita se hara:
public static implicit operator Complejo(float op)
{
return (new Complejo(op, 0));
}

Entonces se podran crear objetos de tipo Complejo as:


Complejo c2 = 5f; // c2 = 5 + 0i

En este caso nunca se perder informacin y la conversin nunca fallar, por lo que es perfectamente vlido
definirla como implcita. Adems, redefiniendo conversiones implcitas puede conseguirse que los tipos definidos
por el usuario puedan inicializarse directamente a partir de valores literales tal y como si fuesen tipos bsicos del
lenguaje.

Colegio San Jos Juan V. Madrid Jurado

También podría gustarte