Manuales .

NET : Manual C#
Índice Temático Básico » Intermedio » Avanzado
y y y y

y y y

y y y y y y

y y y y y

¿Qué es C#? Lenguaje Orientado a Objetos Objeto Herencia o Clase  Funciones Miembro  Campos Estáticos o Clase Base o Clase Derivada o Clase Abstracta o Clase Sealed o Overloading/Sobrecarga o Herencia Simple o Polimorfismo y Funciones Virtuales o Encapsulación y Visibilidad o Abstracción Plataforma .NET .NET Common Language Runtime - CLR o Características del CLR .NET Runtime Environment o Ambiente/Entorno de Ejecución o Ensamblaje o Interoperabilidad de Lenguaje o Atributos Biblioteca de Clases de la Plataforma .NET Requerimientos de Software Lenguaje Intermedio y Metadatos JIT Sistema de Tipo Unificado El Sistema Virtual de Objetos - VOS o VOS Type System o Metadata y Reflection o Seguridad o Deployment o Interoperabilidad con código no administrado o Common Language Specification - CLS o Virtual Execution System - VES Tipos de Datos o Constantes y Campos Solo Lectura Ejemplo Hello World! Ejemplo Args Ejemplo Input/Output Ejemplo String Format

y y y y

y

y y y y

y y

y y y

y y y

Función Main o Múltiples Funciones Main Preprocesamiento Comentarios Value Types o Tipos simples  Integral  Bool  Char  Floating Point  Decimal o Tipos Estructura o Tipos Enumeración Tipos Referencia o Tipo Objeto o Tipo Clase o Interfaces o Delegados o Tipo string o Arreglos  Arreglos Multidimensionales  Arreglo de Arreglos  Arreglos de Objetos  Conversión de Arreglos o Clase Array o Interface IComparable o Interface IComparer  IComparer Como Propiedad Expresiones Regulares Operador as Secuencias de Escape Boxing o Conversiones Boxing o Conversiones Unboxing Constructores y Destructores o Constructor Estático Métodos o Parámetros  Valores en Parámetros in  Valores en Parámetros ref  Valores en Parámetros out  Ejemplo de Parámetros In, Ref y Out Redefinición de Métodos (Overriding) Ocultamiento de Métodos (Hiding) Propiedades o Accessors o Propiedades Estáticas Índices Eventos Modificadores

y

Modificadores de Clase Modificadores Miembro Modificadores de Acceso  public  protected  private  internal Sentencias de Control o Sentencias de Selección  Sentencia if  Sentencia switch o Sentencias de Iteración (repetición)  Sentencia for  Sentencia foreach  Sentencia while  Sentencia do o Sentencias de Salto
o o o     break continue goto return

y

Asignación Definitiva Precedencia de Operadores
o o o typeof is

y

Conversiones

Básico » Intermedio » Avanzado
y

y

y

Manejo de Excepciones o Jerarquía de Excepciones o Trabajar con Excepciones o Chequeo de Overflow o Chequeo programático de Overflow o Sentencias para el Manejo de Excepciones  try - catch  try - finally  try - catch - finally o Lanzamiento de Excepciones o Relanzamiento de Excepciones o Creación de Clases Exception Componentes o Creación de Componentes  Compilación de Componentes o Creación de una Aplicación Cliente  Compilación de Clientes Namespaces o Envolver Clases en Namespace o Utilizar Namespace en Aplicaciones Cliente o Agregar Múltiples Clases a Un Namespace o Namespace y Ensambles

NET y corre en el Lenguaje Común en Tiempo de Ejecución (CLR.NET C# deriva de C y C++.NET en Componentes . simplifica y moderniza a C++ en las áreas de clases.NET Invocación de Servicios Código No Seguro Debugging Seguridad o Seguridad de acceso al código  Permisos Estándar  Permisos Identidad o Seguridad basada en roles Función ToString() Función Equals() Básico » Intermedio » Avanzado y y y y y y y y Clase Hashtable o Interface IHashCodeProvider Función ICloneable Formato Numérico o Formato Personalizado String o Formato Estándar String Parseo Numérico Input/Output Lectura y Escritura de Archivos Serialización Threading (Hilos) ¿Qué es C#? C# o C Sharp es un lenguaje de programación que está incluido en la Plataforma . C# intenta ser el lenguaje base para escribir aplicaciones . mucho de lo que soporta la Plataforma . simple y enteramente orientado a objetos.y y y y y y y y y y Compilación Condicional o Uso del Preprocesador  Definición de símbolos  Exclusión de código basado en símbolos  Lanzamiento de errores y advertencias o Atributo conditional Comentarios de Documentación en XML o Elementos XML Componentes . namespaces. sobrecarga de métodos y manejo .NET o Componentes . Common Language Runtime).COM o Uso de Componentes COM en Componentes .NET está escrito en C#. El primer lenguaje en importancia para el CLR es C#.NET Privados o Componentes .NET Compartidos Interoperabilidad COM o Uso de Componentes . es moderno.

NET provee un colector de basura que es responsable de administrar la memoria en los programas C#. esta característica para acceder a APIs nativas es llamada Platform Invocation Services (PInvoke) Por default el código es safe mode. La Plataforma . Por default trabaja con código administrado. el cual define el estádar de interoperabilidad entre lenguajes que se adhieran a este estándar. El Modelo completo de clases está construido en la cima del . Soporta los conceptos como encapsulación.NET event model. Solamente se permite una base clase. Se elimino la complejidad de C++ para hacerlo más fácil de utilizar y menos propenso a errores. No existen funciones globales. No maneja apuntadores. solamente el runtime . El modelo de objetos es parte de la infraestructura y ya no forma parte del lenguaje de progrmación. C# depende del runtime que provee la Plataforma . Lenguaje Orientado a Objetos . No soporta herencia múltiple. para emular la función de los apuntadores se utiliza delegates el cual provee las bases para el .NET Virtual Object System (VOS). El soporte de versiones lo provee el CLR. No es posible hacer el cast de un entero a un tipo de referencia (objeto).NET Common Language Specification. El manejo de errores está basado en excepciones. Los métodos que se definen en las clases son por default no virtuales (no pueden ser sobre escritos al derivar clases) Soporta los modificadores de acceso private . el runtime administra la ejecución de código. Los parámetros que son pasados son type-safe. herencia y polimorfismo de la programación orientada a objetos. estructuras y almacenamiento de arreglos estáticos. esta declaración permite utilizar apuntadores. No es posible utilizar variables no inicializadas. protected . Soporta OLE Permite la interoperabilidad con APIs al estilo C y DLLs. La Plataforma .NET. pero es posible declarar clases o sólo métodos unsafe.de excepciones. como un miembro de la instancia (accesible via una instancia de clase) o un miembro estático (via el tipo). las cuales no pueden contener implementación. public y agrega un cuarto modificador internal .NET permite la herencia múltiple en la forma de interfaces. si se requiere herencia múltiple es posible implementar intefaces. Permite acceder a diferentes APIs a través de .NET provee un acceso transparente a COM. variables o constantes. Todo deber ser encapsulado dentro de la clase. Algunas características de C# son: y y y y y y y y y y y y y y y y y y y y y y C# provee el beneficio de un ambiente elegante y unificado.

por ejemplo: "un empleado es una persona". para que un lenguaje sea llamado Orientado a Objetos debe soportar tres conceptos: objetos. La herencia es un ejemplo del diseño orientado a objetos conocido como una relación "is-a" (es-un). la herencia es una característica fundamental de un sistema orientado a objetos. Polimorfismo Objeto Un Objeto es una instancia de un tipo de clase. . A través de la herencia es posible crear o derivar una nueva clase basada en una clase existente. Un Objeto es una colección de información relacionada y funcional. la instanciación usa el operador new. Un objeto se compone de: y y Datos que describen el objeto y Operaciones que pueden ser realizadas por el objeto Herencia La Herencia es la habilidad para heredar datos y funcionalidad de un objeto padre. Herencia 3. después la instanciación es posible comunicarnos con el objeto a través de sus miembros. Aunque los lenguajes orientados a objetos se construyen sobre los conceptos de : 1. si los objetos no tienen la estructura apropiada la herencia no podría funcionar correctamente.Según Bjarne Stroustrup autor del lenguaje de programación C++. Encapsulación 2. Una clase derivada es la nueva clase que esta siendo creada y la clase base es una de las cuales la nueva clase es derivada. clases y herencia. La instanciación es el acto de crear una instancia de un objeto. la instancia es un objeto. Al utilizar la herencia la clase base necesita ser diseñada teniendo en mente la herencia. La nueva clase derivada hereda todos los miembros de la clase base por consiguiente permite reusar el trabajo previo. En C# se puede asumir que la clase derivada podría heredar todos los miembros de la clase base.

Una clase utiliza ninguno. uno o más constructores para ayudar a definir la instancia de una clase. Campos Estáticos Un Miembro Estático definine miembros de un objeto que no son asociados con una instancia de clase específica. los componentes principales de una clase son: métodos. Un Campo Estático es el tipo más simple de un miembro estático. eventos y propiedades.name . Una Clase define las operaciones que un objeto puede realizar y define un valor que mantiene el estado del objeto. En el lenguaje común en tiempo de ejecución . eventos y campos. una instancia es la creación de un objeto del tipo clase que se está declarando. Una interfaz de clase es un contrato entre esta y los programadores que usan la clase. Una instancia de una clase es un objeto. . cuando un programador tiene una referencia a la clase derivada. es decir. Una clase utiliza modificadores para especificar la accesibilidad de la clase y sus componentes. Existe una palabra reservada llamada this que sirve para hacer referencia a la clase actual en el ámbito en el cual es utilizada. pero es una buena práctica no olvidar liberar los recursos. Funciones Miembro Una Función Miembro puede ser un constructor. para declarar un campo estático se utiliza el modificador static . upcasting. Cuando se hace referencia a una variable de instancia que tiene el mismo nombre de un parámetro se debe utilizar this. los componentes de una clase son llamados miembros por lo que existen diferentes tipos de miembros. Al crear y manipular objetos no es necesario administrar la memoria que estos ocupan ya que existe un mecanismo que se encarga de esto llamado garbage collector (recolector de basura).NET todos los objetos heredan de la última clase base llamada object y existe sólo una herencia simple de objetos. Una referencia se refiere a una instancia. se accede a la funcionalidad de un objeto invocando sus métodos y accediendo a sus propiedades.Una clase derivada no debería requerir más ni prometer menos que su clase base sobre cualquiera de sus interfaces heredadas. Clase Una Clase es una plantilla para un objeto. el programador siempre puede tratar a esa clase como si fuera la clase base. Un objeto puede derivar sólo de una clase base. una pieza de código que es invocada en una instancia del objeto.

Console. public int iEdad. abstract public class Persona{//Indic a que la clase es abstracta //Propiedades public string sNombre.//Método que la clase derivada debe implementar } //Herencia Simple public class Empleado : Persona{ .Un campo estático puede accederse a través del nombre de la clase. además que la clase padre también se define como abstract . Clase Abstracta Una Clase Abstracta define las funciones que una clase derivada debe implementar. Clase Derivada Una Clase derivada es un objeto hijo.iContador).WriteLine(MiContador. this. } } El ejemplo determina cuantas instancias del objeto han sido creadas. } //Métodos abstract public string Tipo(). Console. Una Clase Abstracta define un contrato en donde las clases derivadas deben definir las funciones que la clase padre marca utilizando la palabra reservada abstract . using System. int iEdad){ this.iContador). Clase Base Una Clase base es un objeto padre de donde se basa un nuevo trabajo. MiContador ContadorB = new MiContador().WriteLine(MiContador. //Constructor public Persona(string sNombre. public MiContador(){ iContador++.sNombre = sNombre. en vez de la instancia de la clase (objeto): using System. class MiContador{ //Campo Estático public static int iContador = 0.iEdad = iEdad. } } class App{ public static void Main(){ MiContador ContadorA = new MiContador().

int iEdad):base(sNombre. Empleado[] aProgramadores = new Empleado[2].Tipo()). } } } Clase Sealed Una Clase sealed se utiliza para prevenir que una clase sea utilizada como una clase base. aProgramadores[1] = new Empleado("Eric S. Console.iEdad). } } class App{ //Aplicación public static void Main(){ Console. i < aProgramadores.cs(4.14): (Location of symbol related to previous error) El error es porque ClaseDerivada no puede utilizar ClaseBase como una clase base porque ClaseBase es sealed . for(int i = 0 . aProgramadores[0] = new Empleado("Bill Gates".Tipo : " + aProgramadores[i].Arreglo de Objetos ---").iEdad : " + aProgramadores[i]. } } Al compilar el código se muestra el siguiente mensaje: sealed.WriteLine(" --. es decir. Raymond". Overloading/Sobrecarga . iEdad){} override public string Tipo(){ return "Empleado".public Empleado(string sNombre.Length.WriteLine("aProgramadores[" + i + "]. 50).WriteLine("aProgramadores["+i+"]. 60). sealed class ClaseBase{ ClaseBase(){} } class ClaseDerivada : ClaseBase{ } class Sellada{ public static void Main(){ ClaseDerivada CD = new ClaseDerivada(). Console.sNombre). no permite derivaciones.WriteLine("aProgramadores[" + i + "].7): error CS0509: 'ClaseDerivada' : cannot inherit from sealed class 'ClaseBase' sealed.sNombre : " + aProgramadores[i].cs(1. su principal uso es para prevenir la derivación no planeada. i++){ Console.

dSueldo = dSueldo.sNombre = sNombre. por lo que es necesario escribir constructores y si funcionalmente no existe alguna modificación se invoca el constructor de la clase que hereda utilizando la sintaxis base. } //Métodos public string Tipo(){ return "Persona".dSueldo.La Sobrecarga (Overloading) hace posible utilizar dos o más clases con el mismo nombre. } } . } public void AsignarSueldo(double dSueld o){ this. La sobrecarga es común especialmente para los constructores para definir diferentes maneras de crear una instancia nueva. int iEdad){ this. aunque pueden existir miembros a los cuales no se pueda tener acceso por ser private . Herencia Simple La Herencia Simple permite derivar una clase en una clase nueva. Cuando una función sobrecargada es invocada el compilador selecciona la función apropiada que coincide con los parámetros. public class Persona{ //Propiedades public string sNombre.dSueldo.iEdad = iEdad. //Constructor public Persona(string sNombre. pero con parámetros diferentes. hereda todos los miembros datos de la clase. } } //Herencia Simple public class Empleado : Persona{ public Empleado(string sNombre.dSueldo = dSueldo * dSueldo. this. public new void AsignarSueldo(double dSueldo){ this. que contiene la definición de la clase de la cual deriva. } public double ObtenerSueldo(){ return this. using System. Si se omite el constructor de la clase base y es invocado el compilador podría invocar el constructor de la clase base sin parámetros. int iEdad):base(sNombre. iEdad){} public new string Tipo(){ return "Empleado". } double dSueldo. Los constructores no pueden ser heredados. public int iEdad. es decir. } public new double ObtenerSueldo(){ return this. private double dSueldo.

Tipo()).WriteLine("Mexicano.class App{ //Aplicación public static void Main(){ Persona Mexicano = new Persona("Gerado Ángeles Nava". } } Polimorfismo y Funciones Virtuales El polimorfismo es la funcionalidad que permite a código antiguo invocar código nuevo. Console. 33).WriteLine("Mexicano.iEdad). Programador.iEdad).WriteLine("Mexicano.WriteLine("Programador.Tipo : " + Mexicano. las cuales permiten al programador usar polimorfismo para hacer su código simple. //Constructor public Persona(string sNombre.iEdad : " + Mexicano. Mexicano.". esto se logra sobreescribiendo o redefiniendo el código. } //Métodos .ObtenerSueldo()). 53).AsignarSueldo(dSueldo). double dSueldo = 123.456.iSueldo : " + Mexicano. using System. this. e invocar en base al tipo la función apropiada.WriteLine("Programador. Console.Herencia Simple ---"). para lo cual se utilizan funciones virtuales y la palabra clave override .sNombre = sNombre. int iEdad){ this. public class Persona{ //Propiedades public string sNombre.WriteLine(" --.iEdad : " + Programador. Console. Virtual significa que cuando una invocación a funciones miembro. Console.sNombre).WriteLine("Programador. Console. Console.Tipo()). Las funciones abstractas son automaticamente funciones virtuales.iSueldo : " + Programador.iEdad = iEdad.WriteLine("Programador.ObtenerSueldo()). Console.Tipo : " + Programador. el compilador debería buscar por el tipo real del objeto y no por el tipo de la referencia. Console.sNombre).sNombre : " + Mexicano. Console.sNombre : " + Programador. public int iEdad.WriteLine("Mexicano. Empleado Programador = new Empleado("Carlos Salinas G.AsignarSueldo(dSueldo). también permite extender el sistema sin modificar el código existente.

33).Length. 60).Tipo()). Empleado[] aProgramadores = new Empleado[2]. aProgramadores[1] = new Empleado("Eric S.WriteLine("aProgramadores[" + i + "].WriteLine("aProgramadores[" + i + "].Tipo : " + Mexicano. Console. iEdad){} override public string Tipo(){ return "Empleado".WriteLine("Mexicano.iEdad).Tipo()).iEdad : " + aProgramadores[i]. Console. la versión de la función que es parte de la clase object podría ser invocada.sNombre). el objeto base object tiene una función virtual llamada ToString() que convierte un objeto a string. 50).WriteLine("Mexicano. Si se invoca la función ToString() en un objeto que que no la tiene como versión propia. for(int i = 0. i < aProgramadores. .sNombre).WriteLine(" --. } } } Cuando una función es declarada con la palabra reservada override significa que es la misma función que fue declarada en la clase base. } } class App{ //Aplicación public static void M ain(){ Persona Mexicano = new Persona("Gerado Ángeles Nava".WriteLine("Mexicano. Console.iEdad). int iEdad):base(sNombre. Cuando existe una función virtual el programador puede pasar una referencia a la clase abstracta aunque la clase derivada y el compilador podrían escribir código para invocar la versión apropiada de la función en tiempo de ejecución.iEdad : " + Mexicano. si la palabra reservada override se omite el compilador podría asumir que la función no está relacionada a la función de la clase base y no despacha la función virtual (el compilador podría sugerir omitir override o agregar new) . aProgramadores[0] = new Empleado("Bill Gates".Tipo : " + aProgramadores[i].sNombre : " + aProgramadores[i]. Console.WriteLine("aProgramadores["+i+"]. Por ejemplo. Console.Arreglo de Objetos ---"). } } //Herencia Simple public class Empleado : Persona{ public Empleado(string sNombre. Raymond". i+ +){ Console. Console.virtual public string Tipo(){ return "Persona".sNombre : " + Mexicano.

los cambios realizados en el objeto quizá arruinen el código del usuario. es diseñarla de manera tal que las modificaciones son minimas. también será un sistema fácil de entender y mantener. Los cambios realizados en partes públicas de un objeto deben permanecer compatibles con la versión previa. si el usuario hace lode detalles dependientes. La encapsulación provee los límites entre una interfaz externa y los detalles de su implementación interna. Al diseñar objetos el programador decide que objetos son visibles al usuario y que es privado dentro del objeto.NET La solución Microsoft . Abstracción Una Abstracción se refiere a como un problema dado es representado en el espacio de programa. lo cual reduce la oportunidad de que el usuario cambie o dependa de los detalles en el código. . también es necesario determinar cuales de los miembros de la clase deberían ser accesibles publicamente. Las partes públicas pueden ser cambiadas sin arruinar el código del usuario. los campos públicos pueden ser accesados a través de cualquier instancia de la clase. habilidad de un objeto para ocultar sus datos internos o parte interna de sus usuarios y provee una interface que hace las partes importantes del objeto accesible programaticamente. los detalles que no son visibles al usuario son señalados para ser encapsulados en la clase. Los beneficios de una buena abstracción.NET o acceso programático para ciertos servicios tales como almacenamiento de archivos. La interfaz de clase es la implementación de la abstracción.NET comprende cuatro componentes fundamentales: 1. si se conoce bien el problema a resolver facilita determinar que métodos necesitara el usuario. Plataforma . Como desarrollador de clases es necesario pensar en terminos de hacer el mejor diseño de abstracción para los clientes de clase y permitirles enfocarse a la tarea que deben realizar y no escudriñar o indagar en los detalles de como funciona la clase.NET el cual es un servicio de verificación de identidad. Razones para encapsular y ocultar: y y y El usuario no puede cambiar lo que es privado en el objeto. Los campos privados pueden sólo ser accesados desde la clase. calendario y pasaporte .Encapsulación y Visibilidad Encapsulación (también llamada information hiding). Servicios de Bloques de Construcción .

La Infraestructura . tanto o si el código objeto es almacenado y ejecutado localmente. Proveer un ambiente de ejecución de código que garantice la ejecución de código seguro.NET algunas veces llamada la Biblioteca de Clases Base (CBL).NET a su disposición.NET la cual incluye características tales como interfaz natural.NET. Hacer que la experiencia del desarrollador sea consistente a través de una amplia variedad de aplicaciones.NET consiste de un Lenguaje Común en Tiempo de Ejecución (CLR) y la Biblioteca de Clases de la Plataforma . La Plataforma . 3.NET la cual comprende la plataforma .NET incluyen soporte para cualquiera de los archivos de entrada/salida y base de datos de entrada/salida para XML y SOAP. El Lenguaje Común en Tiempo de Ejecución (CLR) el cual es el fundamento de la Plataforma .NET.NET. Construir toda la comunicación sobre estándares industriales para asegurar que el código basado en la Plataforma .NET . Proveer un ambiente de ejecución de código que minimice la distribución de software y conflictos de versiones.NET y Microsoft Windows . escalables y distribuidas.NET La Infraestructura .NET el cual podría correr sobre nuevos dispositivos Internet.NET está diseñada para cumplir los siguientes objetivos: y y y y y y Proveer un ambiente consistente de programación orientada a objetos. separados de otros procesos en la máquina) en la cual funcionan las aplicaciones .NET se refiere a todas las tecnologías que constituyen el nuevo ambiente para crear y ejecutar aplicaciones robustas. tal como aplicaciones basadas en Windows y aplicaciones basadas en Web.NET tienen la biblioteca de clases de la Plataforma . incluyendo el código creado por un desconocido o un tercero semiconfiable.NET que permite desarrollar estas aplicaciones es la plataforma .NET es una plataforma nueva que simplifica la aplicación del desarrollo en ambientes altamente distribuidos de Internet. El CLR es como una máquina virtual (el código que corre dentro del CLR en ejecución en un ambiente encapsulado y controlado. La Experiencia de Usuario . La parte de . La biblioteca de clases de la Plataforma . Dispositivos de Software .2. o si es ejecutado localmente pero distribuido en Internet o si es ejecutado remotamente. 4. Proveer un ambiente de ejecución de código que elimine los problemas de desempeño de ambientes de scripts o interpretes. los Servidores Corporativos .NET. La Plataforma .NET pueda integrarse con cualquier otro código.NET consiste de dos componentes principales: 1. La Plataforma . Microsoft Studio . La Plataforma . todos los lenguajes . agentes de información y etiquetas inteligentes es decir una tecnología que automatiza hiperligas para información relacionada a palabras y frases en documentos creados por el usuario.

Los componentes creados en C# son totalmente auto-describibles y pueden ser utilizados sin un proceso de registro.CLR El . también implementa tipos estrictos de seguridad y otras formas de verificación de código que aseguren la seguridad y robustez. mientras que el código que no será manipulado por el runtime es conocido como un código no administrado. .NET tales como Web Forms y servicios web XML.NET Common Language Runtime . Características del CLR EL CLR no sólo soporta el compilador de C#. el código que generan estos compiladores para ser soportado por CLR es llamado managed code. Seguridad type safety. El concepto de administración de código es principio fundamental del runtime. . Modelo Simplificado para la interacción de componentes. también el de Visual Basic y C++. los cuales proveen un sistema de tipo unificado en el cual todo puede ser tratado como un objeto. El runtime es una agente que administra el código en tiempo de ejecución al proveer de serviciones principales como la administración de memoria. por ello que reciba el nombre de lenguaje céntrico de componentes (component-centric). La plataforma .NET Common Language Runtime (Lenguage común en tiempo de ejecución . Todos los objetos son escritos como componentes y los componentes son el centro de acción. es una colección orientada a objetos de tipos reusables que pueden utilizarse para desarrollar aplicaciones en el rango de aplicaciones tradicionales desde la línea de comandos o interfaces de usuario gráficas (GUI) hasta aplicaciones basadas en las últimas inovaciones que provee ASP. C# ayuda en la creación de componentes mediante el runtime y framework . administración de hilos.NET. Algunos de los beneficios que las aplicaciones obtienen del CLR son: y y y y y y Integración de lenguajes a través del Common Language Specification Administración automatica de memoria. La Biblioteca de Clases de la Plataforma .NET) es un ambiente basado en componentes y C# esta diseñado para facilitar la creación de componentes.NET puede almacenar componentes no administrados que son cargados por el CLR en sus procesos e inicializados por la ejecución de código administrado de esta manera se crea un ambiente de software que puede explotar tanto caracterísitcas de código administrado como las del código no administrado. El código que manipulará el runtime es conocido como código administrado. a través del recolector de basura. Soporte de versiones.2.NET. Manejo de excepciones de lenguajes.

es decir. La seguridad y administración de componentes depende de un número de factores que se incluyen en su origen como Internet red corporativa. sistema de archivos o red. acceso a registros o funciones sensitivas. ejecución de hilos. esta infraestructura permite utilizar codigo administrado para escribir la lógica del negocio. no importa el lenguaje que un programador utilice. El runtime también acelera la productividad del desarrollador. El runtime forza el acceso a código seguro.El CLR provee los beneficios anteriores. el cual asegura que toda la administración de código se describe así misma. computadora local. La administración del ambiente del runtime elimina cuestiones de software comunes. aún si comienzan a utilizarse en el misma aplicación activa. La variedad de compiladores Microsoft y de terceros genera código administrado que conforma el CTS. Los metadatos describen los tipos en el código y son empaquetados en el código ejecutable. es decir. através del CLR que provee muchos servicios estándar. quizá o quizá no están disponibles para desempeñar operaciones de acceso a archivos. El runtime también forza la robustez del código implementando una infraestrucutra estricta de verificación de código llamado Common Type System (CTS). el código administrado nunca es interpretado. ejecución de código.NET Runtime Environment . cualquier compilador que utilice el runtime puede hacer lo mismo. El runtime soporta aplicaciones del lado del servidor como Microsoft® SQL ServerŒ e Internet Information Services (IIS). La interoperabilidad entre código administrado y no administrado permiten a los desarrolladores continuar utilizando componentes COM y DLLs. verificación de código seguro. El administrador de memoria elimina las posibilidades de fragmentación de memoria e incrementa la referencia de localidad de memoria para impulsar el incremento del desempeño. biblioteca de clases. no es posible acceder a datos personales. Estas características son intrínsecas a la administración de código que corre sobre el CLR. una característica llamada just-in-time (JIT) permite compilar todo el código administrado para correr en el lenguaje nativo de la máquina del sistema o de cualquiera que se este ejecutando. El CLR administra la memoria. el compilador debe emitir los metadatos en el managed code. mientras que se forza estrictamente la fidelidad de tipo y seguridad de tipo. liberando por ejemplo recursos que ya no son utilizados. y componentes escritos por otros programadores. El runtime está diseñado para incrementar el desempeño. puede utilizar las ventajas del runtime. compilación y otros servicios. . que la administración de código puede consumir otros tipos e instancias administradas.

El entorno contiene las Bibliotecas de Clase Base (Base Class Libraries .NET. el entorno o ambiente en gran parte es un lenguaje agnóstico permitiendo la elección de lenguaje. Las clases base son clases para tratar datos y XML. y Seguridad. para crear interfaces de usuario Clases Network Fuera de la clase base en tiempo de ejecución.BCL) las cuales proveen las funciones tradicionales fundadas en bibliotecas en tiempo de ejecución. El runtime . soporta de herramientas potentes y ayuda con la distribución.NET y los servicios pueden ser escritos en cualquier lenguaje . clases colección y otras clases generales. lo cual significa que el runtime administra la memoria por el programador a través del recolector de basura. existen muchos otros componentes que controlan la interfaz de usuario (UI) y realizan otras operaciones sofisticadas. tales como consultas. el entorno del runtime . Una aplicación puede hacer invocaciones en cualquier nivel y utilizar clases desde cualquier nivel. En el runtime . arreglos. Las clases base proveen tipos de datos básicos.NET todos los errores son reportados via excepciones.NET es un entorno administrado o controlado.NET está diseñado para ser un entorno seguro.El Lenguaje Común en Tiempo de Ejecución provee los servicios de ejecución básica. pilas y tablas hash. empaquetado y soporte: y Modelo de Programación Simple. la funcionalidad del BCL incluye: o o o o o Clases colección. En la parte superior de la arquitectura las clases exponen servicios web y tratramiento de la intefaz de usuario.NET Framework: Servicios Web Interfaz de Usuario Datos y XML Clases Base Lenguaje Común en Tiempo de Ejecución Ambiente/Entorno de Ejecución El ambiente o entorno provee un modelo de programación simple. Organización . Clases de acceso a bases de datos Clases IO (input-output) Clases WinForms. todos los servicios son ofrecidos a través de un modelo común que puede ser accedido desde cualquier lenguaje . . esto hace el código fácil de reusar para el programador y los proveedores de bibliotecas. seguro.

metadatos y otros archivos requeridos para que un paquete se ejecute en un paquete completo. no importaria en que clase sea escrita una clase. Los ensambles se contienen a sí mismo. es decir. existe suficiente información en el ensamble para ser auto-descrito.NET.NET: VB. permitiendo que el código sea utilizado y escrito desde cualquier lenguaje.NET. VC++.NET es ser un lenguaje agnóstico. no sólo las clases pueden ser escritas en algún lenguaje . El runtime . Cada ensamble contiene un manifiesto que enumera todos los archivos que están contenidos en el ensamble. porque los paquetes son distribuidos en un formato genérico. es convertido a una forma intermedia conocida como IL. esto es posible especificando un requerimiento de seguridad para una pieza de código específica. y y Soporte de herramientas potentes.NET. cuando el código es compilado por uno de los compiladores . Ensamblaje En el runtime . Microsoft suministra cuatro lenguajes . .NET puede ser utilizada como una clase base escrita en C# y esa clase podría ser utilizada desde una clase VC++ o JScript.NET ayuda simplificando la distribución y en algunos casos no existe el paso tradicional de instalación. un paquete puede correr en cualquier entorno que soporte . Interoperabilidad de Lenguaje Una de las metas del runtime . Distribución.El runtime .NET el mecanismo de empaquetado es el ensamble (assembly). El ensamble contiene todos los IL. el modelo de ejecución común hace la depuración de lenguajes simple y directa.NET como VB. el entorno separa los componentes de una aplicación por lo que una aplicación sólo corre con los componentes que son enviados. en tiempo de ejecución el entorno verifica que la ejecución del código sea de tipo segura (type-safe). el ensamble puede ser contenido en un solo archivo o puede ser dividido entre varios archivos. C# y JScript.NET como C#. El sistema de seguridad interactua con el verificador para asegurar que el código realice sólo lo que tiene permitido hacer. una clase que fué escrita en VB.NET y ser invocadas desde otro lenguaje . controla que tipos y recursos son expuestos fuera del ensamble y relaciona las referencias de esos tipos y recursos a los archivos que contienen los tipos y recursos. La depuración en gran medida es enriquecida por el runtime .NET es un entorno verificado. El manifiesto también lista otros ensambles que dependen de un ensamble. Utilizando varios archivos podría hacer posible un escenario donde las secciones del ensamble sean descargadas sólo como se necesiten. empaquetado y soporte. Cuando se define un ensamble.

CLS) la cual describe que características pueden ser visibles en la interfaz pública de la clase.NET. Atributos El runtime . Los atributos son extensibles y permite a los programadores definir atributos y utilizarlos. como clases. la clase debe adherir la Especificación Común de Lenguaje (Common Language Specification .0")] Los atributos son anotaciones que se colocan en elementos de código fuente. miembros. Para que una clase sea utilizada desde un lenguaje . por ejemplo la sobrecarga de operadores. El atributo información es almacenado con los metadatos del elemento y pueden ser facilmente recuperados en tiempo de ejecución a través de un proceso conocido como reflection.Para hacer lo anterior posible existen algunos obstaculos como las propias características del lenguaje. ya que un lenguaje no podría soportar ciertas cosas que otro si las soporte. los cuales son en cierto sentido un lugar para colocar información descriptiva en los metadatos junto con un objeto y entonces recuper después los datos. Los atributos se especifican encerrandolos entre corchetes: [Version("14/09/2005". Procure que el atributo para el elemento sea específico. llevar información organizacional al diseñador. utilizando los identificadores siguientes: Identificador assembly module type Descripción ensamble módulo clase o estructura . parámetros. porque no todos los lenguajes pueden utilizarlos. Comentario="1. por ejemplo el CLS prohibe exponer tipos de datos sin signo. etc. C# utiliza un Atributo Condicional para controlar cuando las funciones miembro son invocadas. proveer información acerca de un objeto. Por convención los atributos se agregan al final del nombre de una clase.Attribute .1. Todos los atributos derivan de System.0. Los atributos puede ser utilizados para: cambiar el comportamiento del runtime. con la finalidad de conocer cuales son clases atributo y cuales son clases normales.NET soporta atributos personalizables. Los atributos proveen un mecanismo general para hacer esto y son utilizados en exceso en todo el tiempo de ejecución para almacenar información que modifica como el runtime utiliza las clases.

method property event field param return método porpiedad evento campo parámetro valor de regreso Los atributos que son aplicados a ensambles o módulos deben colocarse después de cualquier cláusula using y antes de cualquier código. Lenguaje Intermedio y Metadatos Microsoft desarrollo un lenguaje parecido al lenguaje ensamblador llamado Microsoft Intermediate Language (MSIL). Es posible utilizar la Plataforma . El managed code generado por el compilador C# no es código nativo porque es un código de Lenguaje Intermedio (IL). MSIL en sí es un lenguaje completo con el cual es posible escribir aplicaciones.NET. La ventaja final del código IL es que el CPU es independiente. los compiladores toman el código fuente como entrada y producen MSIL como salida. lo cual significa que se necesita un compilador en la máquina destino para cambiar el código IL en el código nativo. Para compilar aplicaciones . conectividad a bases de datos y acceso a archivos. Este código IL se convierte en la entrada para la administración del proceso de ejecución del CLR. . del cual solo se utilizará el CLR y el compilador de C#.NET es una colección de tipos reutilizables integradas en el CLR. Biblioteca de Clases de la Plataforma .NET Servicios Web XML Servicios Windows Requerimientos de Software Todo lo que se necesita para desarrollar en C# es el Kit de desarrollo (SDK).NET La Biblioteca de Clases de la Plataforma . colecciones de datos.NET permiten llevar a cabo tareas de programación comunes como manipulación de strings.NET para desarrollar los siguientes tipos de aplicaciones y servicios: y y y y y Aplicaciones de consola Windows Forms Aplicaciones ASP. Los tipos de la Plataforma .

El código fuente es compilado usando el compilador de C# (csc. pero no es lo único que se provee para el runtime. por ejemplo la definición de cada tipo.dll) justo como lo hace con cualquier PE válido. El IL y los metadatos son colocados en los archivos que extienden el formato PE (Portable Executable) utilizado para archivos . El compilador C# produce como salida el código MSIL y un manifiesto en una parte de sólo lectura del EXE que tiene un encabezado estándar PE (Win32Portable Executable).NET. 4. aunque el código IL es empaquetado en un formato de archivo PE válido. El sistema operativo carga y entonces salta al punto dentro del PE el cual es puesto ahí por el compilador C#.El IL es generado por el compilador. . 3.exe y . el compilador también genera metadatos acerca del código. La función _CorExeMain comienza la ejecución del código MSIL que fue colocado en el PE. 6. Cuando el compilador produce o crea la salida también importa una función llamada _CorExeMain del runtime . el punto de entrada es un pequeña parte que salta a la función _CorExeMain en mscoree. los cuales dicen más al runtime del código. JITers El managed code generado por C# es el código IL.dll. Cuando se compila una aplicación C# o cualquier aplicación escrita en un CLS. etc. la aplicación es compilada dentro del MSIL. Los metadatos son bibliotecas de tipo. 5. El proceso es el siguiente: 1. Dado que el código MSIL no puede ser ejecutado directamente (porque no está un un formato de máquina ejecutable) el CLR compila el MSIL usando un compilador just-in-time (JIT o JITter) dentro de instrucciones CPU nativas tal como procesa el MSIL. cuando se carga el archivo PE el runtime coloca y extrae los metadatos y el IL de estos.exe) dentro de un EXE. Los metadatos son empaquetados directamente con el código ejecutable y no en localidades separadas.dll. el sistema operativo carga el PE como una DLL dependiente tal como la única que exporta la función _CorExeMa in (mscoree. El sistema operativo obviamente no puede ejecutar el código MSIL. entrada de datos al registry. Código fuente escrito en C# 2. además se compila dentro de las instrucciones nativas de CPU cuando la aplicación es ejecutada por vez primera por el CLR. 7. no es posible ejecutarlo sin convertirlo a un managed code nativo. Cuando la aplicación es ejecutada.

2. El CLR incluye tres diferentes JITers que pueden ser usados para convertir MSIL en código nativo. La principal diferencia con un JIIter regular es la incorporación de algunas invocaciones code pitching. . el cual realiza el análisis del flujo de datos. La compilación se hace en tiempo de instalación. El JITter es invocado en tiempo de ejecución. La ventaja de la generación de código en tiempo de instalación. así cuando el método es invocado por vez primera. el stub pasa el control al JIT.Cuando un tipo es cargado. Al ser compilado el ensamble entero no hay preocupación referente al desempeño intermitente cada vez que un método en el código es ejecutado por primera vez. opera como un compilador tradicional. administra el código nativo como salida. es un compilador optimizado. EconoJIT. esta especialmente diseñado para sistemas que tienen recursos limitados como memoria. Es posible determinar que tipo de JIT esta siendo utilizado y cuanta memoria utiliza a través de una pequeña utilidad llamada JIT Compiler Manager (jitman. La generación de código en tiempo de instalación compilará un ensamble completo dentro de un código binario de CPU-especifico. aunque está basado sobre el compilador JIT principal. dependiendo de las circunstancias: 1. siendo el beneficio el reclamo de memoria. 3. El JIT compila el IL a código nativo y cambia el stub para que apunte al código nativo que está en cache. así las subsecuentes invocaciones podrían ejecutar el código nativo. Al usar esta utilidad depende del tamaño del sistema y del ambiente de distribución. se ejecuta cuando un componente NGWS es intalado y compila el código IL a managed code nativo. que permiten al EconoJIT descartar el código generado o compilado si el sistema comienza a ejecutarse fuera de memoria. tal como lo hace el compilador C++. es que permite compilar el ensamble completo justo una vez antes de ser ejecutado. Un ensamble el código empaquetado que es enviado al compilador. realiza una conversión muy veloz del IL a managed code nativo También es un JITter en tiempo de ejecución.exe). La desventaja es que si el código es pitched (lanzado) es invocado otra vez por lo que debe ser compilado de nuevo. JIT. compilador por default utilizado por el CLR. cuando el usuario final es menos probable para notificar que el ensamble esta siendo compiladoJIT. PreJIT (Generación de código Install-time). el laoder crea y agrega un stub (pieza pequeña) a cada método del tipo. que reside en el directorio bin del directorio de instalación del NGWS SDK.

como los tipos declarados y los métodos implementados. describe y hace referencia a los tipos definidos por el VOS.in. . Common Language Specification . agregando nuevos tipos que parezcan y actuen como tipos de sistemas built. provee un sistema de tipos que intenta soportar la implementación completa de una rango amplio de lenguajes de programación. Metadata El compilador CLS toma el código fuente como entrada y produce código MSIL para el runtime para compilar a través de los JITters y ejecutar. Los metadatos son la colección de elementos programáticos que constituyen el EXE. es responsable de la carga y ejecución de los programas que fueron escritos por el CLR. Además se mapea el código fuente a secuencias de instrucciones MSIL. Para un valor el tipo describe la representación de almacenamiento y las operaciones que puede realizar.VES. Virtual Execution System . utilizan y administran tipos son modeladas en el Sistema Virtual de Objetos (Virtual Object System . define el subconjunto de tipos del VOS. 2. también deja a los lenguajes escribir extensiones de sistema tipo.Sistema de Tipo Unificado El runtime de . VOS Type System. Los objetos son más poderosos porque el tipo es almacenado explicitamente en su representación. Metadata.CLS.NET hace más que dar al desarrollador un simple sistema de tipo unificado que es usado a través de todos los lenguajes. el compilador CLS tiene otra tarea importante: envolver metadatos dentro del EXE resultante. cada objeto tiene una identidad que lo distingue de los demás objetos. Si una biblioteca de clases es soportada por las reglas del CLS. VOS Type System El VOS define tipos que describen valores y especifican un contrato en donde todos los valores de tipo deben soportar. El VOS establece una plataforma que permite la integración de lenguajes y type safety.VOS Las reglas que se siguen cuando se declaran.VOS). 3. La base de la arquitectura del runtime es la plataforma que puede describir en cuatro áreas: 1. El Sistema Virtual de Objetos . 4. Los Metadatos son datos que describen datos. Existen dos entidades: valores y objetos. garantiza que la biblioteca de clases pueda ser utilizada por los demás lenguajes que implementen el CLS.

emitiendo la información binaria de los metadatos en un archivo PE. Para forzar la seguridad.NET conocer en tiempo de ejecución que tipos podrían ser almacenados y que métodos podrían ser invocados. el cual analiza la aplicación de metadatos fuente y entonces presenta información acerca de la aplicación en la jerarquía del árbol. Para sacar las instancias de las clases en memoria. Seguridad . El encargado de generar los metadatos es el compilador C#. El significado por el cual estos metadatos son consultados es llamado reflection. al pasar el código a IL. con esta información el runtime .NET Framework IL Disassembler).NET es capaz de resolver como crear objetos. La información incluye lo siguiente: y y y El nombre del objeto Los nombres de todos los campos del objeto y sus tipos Los nombres de todas las funciones miembro. La razón para usar metadatos es simple ya que permiten al runtime . La reflection está disponible para usuarios finales para determinar como son los objetos.NET registran toda la información que es requerida para usar el objeto. incluyendo tipos parámetro y nombres Los metadatos también permiten a otras herramientas acceder a la información detallada acerca del código Existe un proceso llamado reflection donde el código en tiempo de ejecución puede consultar los metadatos para encontrar que objetos están disponibles y que funciones y campos están presentes en la clase. La principal ventaja de la combinación de los metadatos con el código ejecutable es que la información acerca de los tipos es persistente. Esto permite al runtime configurar apropiadamente el ambiente para mayor eficiencia al ejecutar la aplicación. invocar funciones miembro o acceder a los datos de un objeto y el compilador puede utilizar la información para encontrar que objetos están disponibles y como es utilizado un objeto. Los metadatos por cada objeto . Una herramienta que toma ventaja de reflection es el ILDASM (Microsoft . búsqueda de atributos o ejecutar métodos en los que los nombres no son conocidos hasta el tiempo de ejecución. Para traducir IL a código nativo.Estos metadatos son similares a los tipos de bibliotecas generadas con componentes COM (Component Object Model). Los metadatos son utilizados para varias tareas: y y y y y Para representar la información que el CLR utiliza para localizar y cargar clases. Para resolver la invocación de métodos.

. así que el cliente administrado trabaja con clases . Los assemblies son paquetes simples de comportamiento semanticamente relacionados que son construidos como un archivo individual o entidades de archivos múltiples.NET es el concepto de (ensambles).CLS Es un conjunto de reglas que un lenguaje debe adherir para crear aplicaciones .NET Código no administrado usando servicios . el código administrado es justo el código que esta ejecutandose bajo el auspicio de la CLR y por consiguiente comienza a ser controlado por el CLR.NET que se ejecutan en el CLR. cuando la aplicación necesita una interfaz para una DLL en C y la empresa que escribe la DLL no adopta . Deployment La llave para el Deployment de aplicaciones .NET. y y y Código administrado invocando funciones DLL no administradas. La especificación de como deploy una aplicación podría variar ya que se puede tratar de un desarrollo web o aplicación tradicional de escritorio.La faceta más importante de cualquier ambiente de desarrollo de aplicaciones distribuidas es como manejar la seguridad. El runtime . es posible lograr esto creando un wrapper . instale los archivos necesarios pero el CLR no elimina las versiones previas de el archivo porque todavía son requeridas por la primer aplicación.NET para el componente COM. la seguridad relacionada a factores tales como reglas de accesibilidad y requerimientos de consistencia son verificados. Si una aplicación de instalación intenta sobre escribir un archivo necesario para otra aplicación. sistema de tipo unificado y metadatos. Cualquier aplicación que es instalada es automáticamente asociada con los archivos que son parte de ese ensamble.NET mantiene el rastreo delos archivos y de las versiones de los archivos asociados con una aplicación. cuando se desea acceder a .NET será necesario invocar esa DLL desde una aplicación .NET.NET. Common Language Specification . La seguridad comienza tan pronto como una clase es caragada por el CLR porque la clase loader es parte del esquema de seguridad . el runtime . Interoperabilidad con código no administrado El código no administrado no tiene las ventajas que tiene el código administrado.NET es lo bastante inteligente para permitir que la aplicación de instalación.NET desde código no administrado. Código administrado usando componentes COM. Un concepto importante relacionado a la CLR es el código administrado. como recolección de basura.

IL). La class loader forza la seguridad. atributos personalizables. Servicios de debugging. Tipos de Datos C# soporta el conjunto de tipos de datos usual. etc. El CLS se refiere a la interoperabilidad entre lenguajes. propiedades. eventos. para ello es necesario conocer los tipos primitivos. un mapa del lenguaje fuente de la construcción de direcciones en el flujo de instrucciones y un mapa de las direcciones de las localidades en el apilado de frames. enumeraciones.El CLS define un subconjunto de tipos del VOS. existe una correspondencia tipo de lenguaje común en tiempo de ejecución . Carga de Metadatos. delegados. crea stubs que son necesarios para la compilación JIT. el VES proprorciona este servicio al código administrado. Recolector de Basura y Manejo de Excepciones (Garbage Collection). arreglos. Tipo byte sbyte Bytes Tipo runtime 1 1 Byte SByte Descripción Unsigned byte Signed byte . Conversión de IL a Código Nativo via JIT. por lo que es necesario seguir los tipos y características del CLS. si una biblioteca de clases sigue las reglas del CLS esta garantizando ser utilizada por clientes de otro lenguaje de programación que también se adhieren a la CLS. por lo que el compilador C# es capaz de generar el lenguaje intermedio. campos. se encarga de checar la seguridad de tipos y la integridad de los métodos. Carga del Código Administrado (Loading Managed Code).NET. Todos los tipos runtime pueden encontrarse en el namespace System del lenguaje común en tiempo de ejecución . miembros tipo. para que el runtime entienda el apilado individual de frames un código administrado tiene que ser proporcionado por el JITer o por el compilador. que la propia especicicación define. Los componentes de la VES son: y y y y y y y Lenguaje Intermedio (Intermediate Language . diseñado para ser facilmente traducido a una amplia gama de lenguajes. Virtual Execution System . el código del lenguaje intermedio no esta diseñado como un interprete tradicional bytecode o árbol de código. resuelve nombres. estos servicios dependeran de la información producida por el compilador del lenguaje fuente y se emiten dos mapas. excepciones. tipos. Administración de Hilos. identificadores. el codigo administrado premite rastrear el apilado en el runtime.NET subyacente. para cada tipo de dato que C# soporta. la conversión del lenguaje intermedio es realmente una compilación.VES El Sistema Virtual de Ejecución implementa la VOS y se crea implementando un motor de ejecución (Execution Engine EE). interfaces. obtiene clases de la memoria. métodos.

Los value types son asignados en estructuras de pilas o en línea. Las referencias y tipos de valores son derivados de la última clase base objet .short ushort int uint long ulong float double decimal string char bool 2 2 4 4 8 8 4 8 8 Int16 UInt16 Int32 UInt32 Int64 UInt64 Single double Decimal String Char Boolean Signed short Unsigned short Signed integer Unsigned int Signed big integer Unsigned big integer Floating point number Double-precision floating point number Fixed-precision number Unicode string Unicode character Boolean value Los tipos de datos son separados en value types y reference types. a este proceso se le conoce como boxing y el proceso de reversa se le conoce como unboxing La palabra reservada class es empleada para declarar un tipo referencia (heap allocated). . y la palabra reservada struct es empleada para declarar un tipo valor. de esta manera en caso de que un tipo de valor necesite actuar como un object una envoltura hace que el tipo de valor parezca una referencia asignandolo al aglomerado. esto trabajaria así: int i = 2005. una estructura es utilizada para objetos ligeros que necesitan actuar como tipos built-in. las clases son utilizadas en cualquier otro caso. Los reference types son asignados al aglomerado.com. y los tipos de valores son copiados a estos. string s = "Septiembre". Por ejemplo un tipo int es un valor tipo y un tipo string es un tipo referencias. La envoltura es marcada por lo que el sistema conoce que contiene por ejemplo int. i s 2005 o---------------> Septiembre Constantes y Campos Solo Lectura En C# los valores pueden ser definidos como constantes y para que un valor sea constante su valor debe ser algo que pueda ser escrito como una constante. public const string sDominio = "informatique.mx".

exe generado tendrá el nombre del archivo fuente) para ejecutar el programa sólo es necesario escribir el nombre del archivo ejecutable.exe . Aplicando el modificador readonly un valor puede ser establecido en el constructor o en una inicialización pero no puede ser modificado después. puede buscar el ejecutable en la ruta: C:WINDOWSMicrosoft.1. Ejemplo Hello World! El código C# puede ser escrito en cualquier editor. en vez de ello es posible utilizar el modificador readonly el cual está diseñado para aquellas situaciones en donde las constantes tienen restricción.4322 Copyright (C) Microsoft Corporation 2001 -2002.6001.NET Compiler version 7.cs Para compilar el código C# es necesario tener instalado la Plataforma . El código C# debe almacenarse en un archivo con extensión . All rights reserved.1.NETFrameworkv1.Console. también puede escribirse con Visual Studio 7.NET que incluye el compilador C#.NET Framework version 1. El archivo es compilado y ligado a helloworld.WriteLine("Hello World"). Para compilar su archivo .cs es necesario abrir la consola (DOS) y escribir el comando cs seguido del nombre de su archivo por ejemplo: cd helloworld.cs El siguiente es el ejemplo típico de los lenguajes de programación: class HelloWorld{ public static void Main(){ System. Si existe algún error el compilador lo notificará. } } .exe nombreArchivoFuente.4322 csc.cs La salida exitosa de la compilación podría ser así: Microsoft (R) Visual C# .4 for Microsoft (R) . Algo interesante es que es posible especificar el nombre del archivo ejecutable a través de un switch : csc /out:nuevoNombre.exe Asegurese de tener esta ruta en el path para poder ejecutar el compilador desde cualquier ubicación. (el archivo .La restricción de tipos constantes es que son conocibles en tiempo de compilación.10.

WriteLine("Argumento {0} : itera. for(int itera = 0. Existen más namespaces en la Plataforma .WriteLine(). el cual recibe los argumentos con los que el componente fue invocado: Ejemplo de Args con for : using System.El método Main debe estar contenido en la clase y escrito con la primer letra en mayúscula.NET using System. . por lo que en vez de escribir: using System. el cual contiene entre otras la clase Console la cual es utilizada para comunicarse con la línea de comandos. } } {1}". } } } y using System.Length). Ejemplo de Args con foreach : using System. itera++) Console. El tipo de este método puede ser void o int. Es posible importar el namespace en las aplicaciones indicandolo al inicio del código con la palabra reservada using que es una directiva para el namespace System. Ejemplo Args Examinemos el siguiente ejemplo. permite al usuario omitir el namespace al utilizar el tipo al que es referenciado en este caso System . define el namespace System . args[itera]). args. También este método puede especificar argumentos: public static void Main(string[] args) System es el ámbito del namespace en el cual el objeto Console está contenido. Solamente se escribe: . itera < args.WriteLine(input). class App{ public static void Main(string[] args){ foreach(string input in args){ Console.WriteLine("Argumentos : {0}".Length.Console. class Args{ public static void Main(string[] args){ Console.

Length args.WriteLine("Argumentos : {0}". La primer parte de lo que se encierra entre paréntesis es un string donde es necesario destacar que{0}. Length es un método de la clase args el cual obtiene el número de elementos que contiene este arreglo.. com . invoca el método WriteLine de la clase Console para escribir en la línea de comando lo que se indica entre los paréntesis.Length .Console y y class Args . en este caso corresponde al iterador y {1} corresponde a args[itera] . . itera. La clase Args contiene una función o método Main() . este método puede o no ser declarado con argumentos. pn Por ejemplo: args http : www . Al ser un método de arranque debe ser declarado con el modificador static porque no está asociado con una instancia de un objeto. y y y El ciclo for comienza una iteración desde 0 hasta el número de elementos que contiene el arreglo args. se declara una clase llamada Args.Length . mx Salida : . args[itera]) que como mencionamos anteriormente {0} hace referencia al orden en que las variables serán escritas. informatique . using no puede ser utilizado con un nombre de clase por lo que no es permitido escribir using System.Length). en este caso asociada con args. Para compilar el componente utilice csc Args. en este caso es fundamental declarlos porque deseamos precisamente leer y escribir estos argumentos proporcionados al invocar el componente.WriteLine(). por cada elemento contenido en el arreglo escribe en la línea de comandos lo que se indica en ("Argumento {0} : {1}".Console. El método indica que recibe un arreglo de tipo string llamado args y Console. public static void Main(string[] args) . es una notación que indica entre llaves un índice que hace referencia a una variable asociada a este. lo cual indica obtener el elemento en cuestión del arreglo args.cs Para ejecutar el componente sin parámetros escriba en la línea de comando: csc Args Salida : Argumentos : 0 y Para ejecutar el componente con parámetros escriba en la línea de comando: csc Args p1 p2 p3 p4 p5 p6 .. el cual sirve como punto de partida de la ejecución del componente. args. Al no existir las funciones globales en C#.

ReadLine(). strNombre .Write("Dirección: ").ReadLine(). String strEdad = Console. String strTel = Console.Write("Teléfono: "). strTel. intEdad. Argumento 4 : informatique Argumento 5 : . String strDir = Console. utilizando la sintaxis número es reemplazado por la variable correspondiente: using System.ReadLine(). Argumento 6 : com Argumento 7 : . String strFecNac = Console. } } . String strNombre = Console.Write("Nombre: ").Argumentos : 8 Argumento 0 : http Argumento 1 : : Argumento 2 : www Argumento 3 : . Console. Console.WriteLine("Datos: {0} {1} {2} {3}". Console.WriteLine("FecNac = " + strFecNac). class inOut{ public static void Main(){ Console. de esta forma sólo es necesario escribir el nombre del objeto seguido del nombre del método.Write("Fecha de Nacimiento: "). strDir). Console. class strFormat{ public static void Main(){ Console.ReadLine().ReadLi ne(). } } Note que importar la directiva System hace posible omitir escribir el namespace. Ejemplo String Format {número} donde Es posible dar formato a la salida de datos a un tipo string. Argumento 8 : mx Ejemplo Input/Output Es posible leer datos de la consola utilizando el método ReadLine y es posible mostrarlos utilizando el método Write o WriteLine del objeto Console : using System.Write("Edad: "). Console.

class App{ public static int Main(){ Console. } } También es posible que la función Main reciba parámetros de la línea de comandos.Función Main Es posible incluir una función estática en la clase para poder probarla. que indica que regresa un valor de tipo entero: using System. class ClaseA{ public static void Main(){ Console. class App{ public static void Main(){ Console.WriteLine(input). class App{ public static void Main(string[] args){ foreach(string input in args){ Console. } } } Múltiples Funciones Main Es posible que existan en una aplicación varias clases que contengan la función Main() y por ello al compilar se indicará un error. para ello es necesario especificar un arreglo de strings como parámetro: using System.WriteLine("Hello world!"). } } El ejemplo anterior define a la función Main como void lo cual indica que no regresa un valor. return(1). Para evitar el error o indicar que función Main() de que clase deseamos que se ejecute. pero es posible indicar que si regrese un valor escribiendo el tipo de la función como int por ejemplo. .WriteLine("Main de la clase A"). es necesario utilizar el siguiente switch al compilar: /main:nombreClase Por ejemplo using System. en C# esta función estática puede ser escrita como Main() e indica el inicio de la ejecución de un programa: using System.WriteLine("Hello world!").

WriteLine("Main de la clase C"). Un identificador es el nombre que es usado para algún elemento de un programa como una variable o función y deben tener una letra o guión bajo como primer caracter. C# soporta las siguientes directivas de preprocesamiento: Tamaño #define #undef #if Valor Define un identificador. Es posible utilizar los siguientes operadores en expresiones preprocesador: y y ! == . } } class ClaseC{ public static void Main(){ Console.cs /main:ClaseB Salida: Main de la clase B Preprocesamiento Lo más importante en este punto es que en C# no existe el preprocesador. cuando los archivos fuente C# son compilados el orden de la compilación de archivos individuales no es importante y es equivalente a un archivo de gran tamaño.WriteLine("Main de la clase B"). } } Al compilar utilice : csc multiplesmain. el motivo por el cual no existe es para simplificar la estructura de compilación además de que no hay necesidad de escribir un archivo de encabezados por separado y mantener en sincronia la implementación. si la directiva anterior no se cumplio y si la expresión es verdadera el código de la sección es compilado Si la directiva anterior no se cumplio el código de la sección es compilado Marca el final de la sección #elif #else #endif Los identificadores deben preceder a cualquier código real.} } class ClaseB{ public static void Main(){ Console. los identificadores también pueden ser definidos via la línea de comando Elimina la definición de un identificador El código de la sección es compilado si la expresión es verdadera Constructor Else-if.

Comentarios Es posible comentar el código. expresiones constantes consisten de Tipos Simples evaluados solamente en tiempo de compilación no en tiempo de ejecución y los Tipos Simples pueden ser inicializados con literales. Tipos Estructura 3. todo lo que sigue a // es ignorado. que se utiliza para comentar una línea. es decir. Value Types Una variable contiene un valor de cierto tipo. que se utiliza para comentar segmentos de código.NET. C# agrupa los value types en: 1. 2.y y y != && || Es posible utilizar paréntesis para agrupar expresiones.767 .768 a 32. Tipos Enumeración Tipos Simples Los Tipos Simples de C# comparten características como las de alias con los tipos de sistema de . Tipos Simples 2. //. C# forza a inicializar las variables antes de utilizarlas en una operación. Los Tipos Simples de C# se agrupan en: y Integral Representa valores enteros y existen nueve tipos integral en C#: Tipo Tamaño 8 bit 8 bit -128 a 127 0 a 255 Valor sbyte byte short Entero con signo Entero sin signo Entero con signo 16 bit -32. Cuando se asigna un valor a un value type el valor actual es copiado a diferencia de los reference types lo que se copia es la referencia actual no el valor. para ello existen dos modalidades: 1. /* */ .

por ejemplo: char cSexo = 'M' .483.036. esto significa por ejemplo que tratar de convertir una variable char a un tipo de dato integral no es posible en C#.648 a 2.223.147.808 a 9.073.295 64 bit -9. y Floating Point Representan dos tipos de datos.744.223. No existen conversiones implicitas de char a otro tipo de datos disponible.483.372. no hay una conversión entre el tipo integral a bool que force esta conversión.036. por lo que se tendrá que hacer un cast explicito: char cCaracter = (char)65. char cUnicode = 'u0068'.647 32 bit 0 a 4. y Char Representa un caracter Unicode de 16 bit de tamaño.535 32 bit -2.615 y Bool Representa valores booleanos verdadero y falso.294. por lo que es posible asignar a una variable un valor booleano o el resultado de una expresión: bool bContinuar = (a > b).551.147.967.854.709.372.854. int nNumero = (int)'A'.ushort int uint long ulong Entero sin signo Entero con signo Entero sin signo Entero con signo Entero sin signo 16 bit 0 a 65. También es posible asignar un valor hexadecimal utilizando la secuencia de escape x o un valor Unicode con la secuencia de escape u: char cHexadecimal = 'x0068'. flotantes (float) y dobles (double): .807 64 bit 0 a 18. En C# el valor verdadero no es posible representarlo con algún valor diferente de cero.775.775.446.

0x10 -28 a 7. se podría generar un overflow o perder precisión. Cuando se define una variable y se le asigna un valor se utiliza el sufijo m para denotar que es un valor decimal: decimal decDecimal = 1. .Tipo float 1. No hay conversiones implicitas entre decimales y dobles. Tipos Estructura Un tipo struct puede declarar constructores. operadores y tipos anidados. Not-a-Number Nota: Si una expresión un valor es de tipo Floating Point todos los otros valores son convertidos a tipos Floating Point antes de realizar el cálculo.9x1028 con una precisión de 28 a 29 dígitos. y Decimal Representa un tipo de alta precisión de 128 bit el cual es posible utilizarlo para calculos financieros y monetarios. Las estructuras actuan de manera similar a una clase y con mayores restricciones. índices.0x10 Al realizar operaciones con Floating Point pueden producirse los siguientes valores: o o o Cero positivo y negativo Infinito positivo y negativo NaN. La principal idea de utilizar struct es para crear objetos ligeros como Point . de esta manera se conserva memoria porque no hay referencias adicionales que son creadas como se necesiten por objetos clase. por ejemplo no pueden heredar de cualquier otro tipo. propiedades.7x10308 con una precisión de 15-16 dígitos -324 double 5. por lo que es necesario una conversión explícita con un cast. métodos. campos.. etc.4x10 con una precisión de 7 dígitos a 1. ni tampoco otra clase puede heredar de una estructura. La diferencia entre struct y class en C# es que struct es un value type y class es una reference type. Los valores posibles comprenden los rangos 1. constantes. Las estructuras deberían ser utilizadas sólo para tipos que son realmente una pieza de datos.5x10 -45 38 Valor a 3.0m Si se omite la letra m la variable podría ser tratada como double por el compilador antes de ser asignado. FileInfo .

public static void Main() { Type eDias = typeof(enumDias).WriteLine("Los días de la semana.miIP.Julio. Miércoles.Mayo. foreach ( string s in Enum. miIP. Type eMeses = typeof(enumMeses).b1 = 192.b3. miIP. Año = 1971}. Mes = 9.Septiembre.Abril. así como es posible especificar el tipo de dato de los valores contenidos especificandolo después del nombre de la enumeración aunque están restringidos a los tipos: long. public class Enumeracion { enum enumDias { Sabado.GetNames(eDias) ) .b2.b4.b1. Console. .Diciembre}. miIP.b4). } } Tipos Enumeración Es posible establecer un conjunto de constantes relacionadas.Write("{0}.Agosto. por default los elementos de una enumeración son de tipo int donde el primer elemento tiene el valor 0 y cada elemento subsecuente se incrementa en 1. miIP.miIP.b4 = 101.". Console. short y byte.{1}. enum enumMeses {Enero. miIP. Viernes }. Jueves.b3 = 1.{1}".Write("{0}. struct IP{ public byte b1. constanteN } Ejemplo: using System. constante3.Febrero.b2).using System. Domingo. Type eFecha = typeof(enumMeses).b3. Lunes. Console. } class ip{ public static void Main(){ IP miIP. Es posible establecer el valor del primer elemento simplemente asignando a este el valor deseado.Junio._ Octubre. Martes.Marzo. miIP.b2 = 168. Sintaxis: enum NombreEnumeraciones{ constante1. constante2. int. . y su valor correspondiente en la enumeración es:"). enum enumFecha {Dia = 21.Noviembre.

es decir. al ser la clase base de todos los tipos es posible asignarle valores de cualquier tipo.WriteLine(). y su valor correspondiente e n la enumeración es:"). sbyte .WriteLine( "{0.GetNames(eMeses) ) Console. Enum. foreach ( string s in Enum.Console. Enum. -11}= {1}". s. Los reference types que C# utiliza son: y y y y y y Tipo Objeto Tipo Clase Interfaces Delegados Tipo string Arreglos Tipo Objeto El Tipo Objeto es la Clase Base de todos los tipos.Format( eDias. "d")). que está disponible como un objeto. El Tipo Objeto es utilizado cuando el value type esta boxed. Miércoles. Console.WriteLine( "{0. el tipo base por default es int. Tipos Referencia Es contraste a value types los reference types no almacenan el dato actual que representan.WriteLine("Los meses del año. -11}= {1}". ushort . Los tipos base válidos para las enumeraciones son: byte. int. Martes. short . s). Jueves.Parse(eDias. uint. Si el tipo base no es especificado. s. } } Tipos Base Los Tipos Base para las enumeraciones se especifican listando el tipo base después del nombre de la enumeración: enum eDias : int{ Lunes. s).Parse(eMeses. Enum. Enum. long y ulong.Format(eMeses. Console. . porque almacenan una referencia al dato actual. Viernes }. "d")).

cuando se define una Clase es posible derivar de múltiples interfaces. propiedades e índices en una interface.").AccionUno(). operadores. una referencia a la interface puede ser obtenida por un cast de la interface. Para crear una interface se emplea la palabra reservada interface : using System.. } class Implementa : Iuno{ public void AccionUno(){ Console.WriteLine("Acción uno. Los datos miembro son constantes. propiedades. funciones miembro y tipos anidados. } } Es posible definir métodos. sólo un objeto que deriva de la interface. por lo que no es posible instanciar una interface. I. Una clase puede implementar más de una interface. interface Iuno{ void AccionUno(). se parecen a una clase abstracta que tiene todos sus miembros abstractos.. campos y eventos. } } class App{ public static void Main(){ Implementa I = new Implementa().Tipo Clase El Tipo Clase contiene datos miembro. InterfaceB{} Existe una técnica llamada Implementación de la Interface Explícita y se utiliza para resolver colisiones con nombres de métodos iguales entre interfaces: using System. interface Iuno{ void AccionUno(). índices. Sólo existe la firma pero no tiene implementado todo el código. constructores y destructores. mientras que al definir una interface sólo es posible derivar de sólo una clase. Las funciones miembro incluyen métodos. } . class NombreClase : InterfaceA. Las interfaces están estrechamente relacionadas a clases abstractas. } interface Idos{ void AccionUn o(). Interfaces Una interface declara un tipo referencia que tiene sólo miembros abstractos. Cuando un objeto implementa una interface.

AccionUno().WriteLine("Colisión resuelta con el nombre del método Iuno"). por ejemplo si deseamos que una clase Ordenamiento soporte diferentes métodos de ordenación. Es posible encapsular métodos estáticos e instancias en una instancia delegado. Un delegado especifica la forma de una función en vez de especificar toda una interface. Idos dos = (Idos) I.class Implementa : Iuno. Las interfaces se crean en tiempo de compilación y los delegados son creados en tiempo de ejecución. Un delegado es una implementación de function pointers orientada a objetos y son utilizados en muchas situaciones donde un componente necesita volver a invocar el componente que lo esta usando. básicamente un delegado es un type-safe y secure version. así como también es posible crear interfaces basadas de otras interfaces. . uno. Un delegado encapsula un método con cierta firma. Los delegados al ser de naturaleza dinámica se utilizan cuando el usuario desea cambiar el comportamiento. Delegados Los delegados son similares a las interfaces.AccionUno(){ Console. } } Es posible ocultar al usuario de la clase la implementación de una interfaz. } } class App{ public static void Main(){ Implementa I = new Implementa().WriteLine("Colisión resuelta con el nombre del método Idos"). El principal uso de los delegados es con los eventos no con las clases.AccionUno(){ Console. Idos{ void Iuno.AccionUno(). dos. } void Idos. la ordenación podría ser controlada en base a un delegado que defina la función de comparación. especifican un contratado entre un caller y un implementer (implementador). La especificación del delegado determina la forma de la función y crea una instancia del delegado. Iuno uno = (Iuno) I. se usa la función que coincide con la forma.

informatique.Nota los delegados siempre son creados aún si no son usados. string es un alias para la clase predefinida System.Length.String en el CLR. La clase String soporta los sisguientes métodos de comparación y búsqueda: Método Descripción . Tipo string El Tipo string se utiliza para manipular datos string. for(int iElemento = 0.com. Todos los strings en C# son instancias del tipo System.mx".String y su uso es muy sencillo: string sWebSite = "http://www. iElemento < sWebSite. que los caracteres contenidos en el string no puede ser modificados por los usuarios del string. iElemento++){ Console. La clase string deriva directamente de object y no es posible derivarla. pero los delegados podrían ser creados al vuelo si se reemplazan las funciones estáticas por propiedades.mx". Es posible hacer un barrido de los caracteres que componen el string utilizando la propiedad Length que poseen los arreglos y porque es posible acceder a estos tratando al string como un arreglo: using System. es decir. class App{ public static void Main(){ string sWebSite = "http://www. } } } Es posible concatenar strings utilizando el operador +. simplemente acceda a su índice: sWebSite[11].com. todas las operaciones que son realizadas por la clase String regresan una versión modificada del string en vez de modificar la instancia en la cual se invoco el método.WriteLine("Elemento " + iElemento + " : " + sWebSite[iElemento]). Para acceder a un caracter. entonces unicamente se crea el delegado solo si se utiliza la propiedad.Length + " caracteres").WriteLine("sWebSite contiene : " + sWebSite. La clase String es un ejemplo de tipo inmutable. Console.informatique. Si requiere comparar strings por igualdad utilice el operador de comparación == Aunque string es un reference type la comparación se realiza comparando los valores no las referencias.

si se pasan objetos la función ToString es invocada Copia un número específico de caracteres de una ubicación del string dentro del arreglo Regresa un nuevo string con un substring insertado en la ubicación específica Une un arreglo de strings junto con un separador entre cada elemento del arreglo Alinea a la izquierda un string Alinea a la derecha un string Elimina caracteres de un string Reemplaza todas las instancias de un caracter con caracteres diferentes Crea un arreglo de strings dividiendo un string en cualquier ocurrencia de uno o más caracteres Extrae un substring de un string regresa una versión de un string en minúsculas regresa una versión de un string en mayúsculas Elimina espacios en blanco de un string Elimina un string de caracteres al final de un string Elimina un string de caracteres al inicio de un string object.Compare() CompareOrdinal() CompareTo() EndsWith() StartsWith() IndexOf() LastIndexOf() Concat() CopyTo() Insert() Join() PadLeft() PadRight() Remove() Replace() Split() Substring() ToLower() ToUpper() Trim() TrimEnd() TrimStart() Compara dos strings. Regresa la posición de la primer ocurrencia de un substring Regresa la posición de la última ocurrencia de un substring Concatena dos o más strings u objetos.Format() puede ser utilizada para crear un string basado en los valores de otro string. Compara dos regiones de strings utilizando una comparación ordinal Compara la instancia actual con otra instancia. convierte un objeto a una representación string. La clase StringBuilder soporta las siguientes propiedades y métodos: Propiedad Capacity Descripción Recupera o establece el número de caracteres que StringBuilder puede contener Índice StringBuilder utilizado para obtener o establecer un caracter en la posición específica [] . Determina cuando un substring existe al final de un string Determina cuando un substring existe al principio de un string. String.ToString() .

Un arreglo value type no contiene instancias boxed."Dennis Ritchie". Note que para definir un arreglo se utilizan los corchetes [] después del tipo del arreglo. todas las variables contenidas en el arreglo son referidos como elementos los cuales deben ser del mismo tipo. Es posible inicializar un arreglo al momento de crearlo: string[] asPersonas = new string[] {"Tim Berners -Lee". El valor inicial de un arreglo es null. Los arreglos en C# son referencias a objetos. utilizando un formato específico para el objeto Asegura que StringBuilder tiene suficiente espacio para un número de caracteres específico Inserta la representación string de un objeto específico en una posición específica Elimina los caracteres específicos Reemplaza todas las instancias de un caractes con un nuevo caracter Método Append() AppendFormat() EnsureCapacity() Insert() Remove() Replace() Arreglos Un arreglo contiene variables a las cuales se accede a través de índices."Brendan Eich"."James Gosling"}. Cuando un arreglo es creado inicialmente contiene los valores por default para los tipos que este contendrá. un arreglo de objetos es creado utilizando new. por lo que el tipo del arreglo.Length MaxCapacity Recupera o establece la longitud Recupera la capacidad máxima del StringBuilder Descripción Agrega la representación string de un objeto Agrega la representación string de un objeto. Durante la inicialización es posible omitir new tipo[x] y el compilador podría determinar el tamaño de almacenamiento para el arreglo del número de items en la lista de inicialización: . Ejemplo: string[] aPersonas. Sintaxis: tipo[] identificador.

Ejemplo: . utilice la palabre reservada new seguido del tipo y entre corchetes el número de elementos que contendrá.1 o nIndice < nombreArreglo.Array del runtime NET. class Arreglo{ static public void Main(){ string[] aNombres = {"Hugo". Arreglos Multidimensionales Los Arreglos Multidimensionales son aquellos que tienen más de una dimensión. } } Otra alternativa al ejemplo anterior es: int[] aiNumeros = new int[3]. using System."Luis"}.] identificador. aiNumeros[2] = 43.WriteLine(aNombres[0]). donde cada dimensión comienza con el índice 0."James Gosling"}. si requiere hacer un barrido de todos los elementos del arreglo.WriteLine(aNombres[1]). Console.WriteLine(aNombres[2]). Cada elemento de un arreglo de strings es un string con el valor null : string[] asNombres = new string[5]. comience a partir del índice 0 hasta la longitud del arreglo menos uno (nombreArreglo. los métodos IndexOf() y LastIndexOf() y BinarySear ch podrían buscar elementos en un arreglo."Paco". Es posible ordernar y buscar los elementos de un arreglo gracias a que los arreglos en C# están basados en el tipo System."Brendan Eich". aiNumeros[1] = 33."Dennis Ritchie".Length ).Length . Sintaxis: tipo[. aiNumeros[0] = 4.string[] asPersonas = {"Tim Berners -Lee". Console. El método Sort() podría ordenar los elementos de un arreglo. La dimensión del arreglo puede ser simple o multidimensional. El método Reverse podría invertir el orden de los elementos de un arreglo. Cada elemento de un arreglo de ints es un int con el valor 0: int[] aiNumeros = new int[5]. Al declarar el arreglo especifique solamente el número de elementos que este contendrá. Console.

] asBidimensional = new string[iRenglon. asBidimensional[3. {55. asBidimensional[0.1] = "11". asBidimensional[3. asBidimensional[1. "Dennis M.22}.44}. j++){ Console.1] = "01". Console.1] = "21".Length).0] = "10". int iColumna = 2. asBidimensional[2. simplemente defina arreglos como elementos del arreglo: string[. 2.0] = "30".Length). Ejemplo: using System. j < iColumna. i < iRenglon.WriteLine("Longitud del arreglo aiBidimensional : " + aiBidimensional.] asMulti = {{"a".Length). string[."3"}}."2"}.WriteLine("Longitud del arreglo asPersonas : " + asPersonas. asBidimensional[1.string[.j]). i++){ for(int j = 0. //Define 4 arreglos de 2 dimensiones int iRenglon = 4.{"c".WriteLine("Longitud del arreglo asBidimensional : " + asBidimensional. Para definir un arreglo multidimensional. 3}.Length). Console. "Brendan Eich".1] = "31". } } Console. {33.66}.88} }.] asBidimensional = new string[2. Ritchie".0] = "20". iColumna]. int[. 4]. {77.{"b". asBidimensional[2. for(int i = 0.WriteLine("Longitud del arreglo aiNumeros : " + aiNumeros. class App{ public static void Main(){ string[] asPersonas = {"Tim Berners -Lee"."1"}. Console.0] = "00".] aiBidimensional = { {11.WriteLine("Dimen sión " + i + " elemento " + j + " : " + aiBidimensional[i. } } Arreglo de Arreglos . // 4 renglones * 2 columnas = 8 Elementos asBidimensional[0. int[] aiNumeros = new int[3] {1. "James Gosling"}.

Arreglos de Objetos Un arreglo de objetos es creado utilizando new. aProgramadores[1] = new Empleado("Eric S.iEdad).WriteLine(" --. Raymond". public int iEdad. Este ejemplo define un arreglo de arreglo de tipo int donde su dimensión es 3 elementos. 33). } //Métodos public string Tipo(){ return "Persona".Un Arreglo de Arreglos es también conocido como jagged array porque no tiene que ser rígido.WriteLi ne("Mexicano. } } class App{ //Aplicación public static void Main(){ Persona Mexicano = new Persona("Gerado Ángeles Nava".sNombre : " + Mexicano. iEdad){} public new string Tipo(){ return "Empleado". //Constructor public Persona(string sNombre. } } //Herencia Simple public class Empleado : Persona{ public Empleado(string sNombre.Tipo : " + Mexicano.WriteLine("Mexicano. 60). 50 ).sNombre = sNombre.sNombre).iEdad : " + Mexicano. Console. . Es posible declarar y manipular arreglos de objetos de la siguiente manera: using System. public class Persona{ //Propiedades public string sNombre. donde estos elementos son arreglos.Tipo()).Arreglo de Objetos ---"). Console. int iEdad):base(sNombre. aProgramadores[0] = new Empleado("Bill Gates".iEdad = iEdad. Console.WriteLine("Mexicano. Console. Empleado[] aProgramadores = new Empleado[2]. this. int iEdad){ this. Por ejemplo: int[][] aiIDs = new int[3][].

Tipo()). "JavaScript". } } } Conversión de Arreglos Una conversión implícita es posible si los arreglos tienen el mismo número de dimensiones. "Visual Basic".Length.sNombre). "C++"}.WriteLine("aProgramadores["+i+"]. "Pr olog". funciones de búsqueda y ordenamiento. Clase Array La clase Array provee entre otras. Array. si los elementos de un arreglo tienen una conversión de referencia implícita para los tipos de elementos del otro arreglo y ambos arreglos son tipos referencia.Length. elemento++) Console. i < aProgramadores. En el siguiente ejemplo se muestra como es ordenado un arreglo de strings: using System. "Java". Una conversión explícita tiene los mismos requerimientos de una conversión implícita excepto que los elementos de un arreglo deben ser convertibles explícitamente a los tipos de elementos del otro arreglo.iEdad : " + aProgramadores[i].WriteLine("Elemento [" + elemento + "] = " + aLenguajes[elemento]).Tipo : " + aProgramadores[i].WriteLine("aProgramadores[" + i + "]. } } Salida: Elemento Elemento Elemento Elemento Elemento Elemento Elemento Elemento Elemento Elemento Elemento [0] = ActionScript [1] = C [2] = C# [3] = C++ [4] = Java [5] = Java [6] = JavaScript [7] = Pascal [8] = PHP [9] = Prolog [10] = SQL .iEdad).Sort(aLenguajes).WriteLine("aProgramadores[" + i + "]. "Pascal".for(int i = 0. "C#". Console. "SQL". "PHP". Console. elemento < aLenguajes. class App{ public static void Main(){ string[] aLenguajes = {"Java". "C". "ActionScript". i++){ Console. for(int elemento = 0.sNombre : " + aProgramadores[i].

4. -0.01 1. -6.09 -6. int id){ this. } } .7. class App{ public static void Main(){ double[] aNumeros = {8.9.nombre = nombre. public class Lenguaje : IComparable{ string nombre.id > lenguajeB.002. this.id < lenguajeB. public Lenguaje(string nombre.9.Elemento [11] = Visual Basic La función Sort(). if(this. 1.87}. por ejemplo una ordenación utilizando una propiedad numérica: using System.7 99. 6.002 0. }else{ return 0. elemento++) Console.Length .9 8.2.5.Sort(aNumeros).id){ return -1. 99.87 Interface IComparable La función sort no trabaja con clases o estructuras porque no conoce su orden.id){return 1.2 6.CompareTo(object o){ Lenguaje lenguajeB = (Lenguaje)o.01. } } Salida: Elemento Elemento Elemento Elemento Elemento Elemento Elemento Elemento Elemento [0] [1] [2] [3] [4] [5] [6] [7] [8] = = = = = = = = = -102. Array.} if(this. } } public override string ToString(){ return nombre + " " + id. también se puede utilizar con números: using System. 0. for(int elemento = 0.09.id = id.WriteLine("Elemento [" + elemento + "] = " + aNumeros[elemento]).9 4. } int IComparable. elemento < aNumeros. -102. int id. pero si desea ordenarlas utilice la interface IComparable .5 -0.

. entonces se requiere una clase separada para cada tipo de ordenamiento que implementen IComparer y podría también implementar la función Comapare() : using System. public Lenguaje( string nombre.} if(this. Array.2).CompareTo(object o){ Lenguaje lenguajeB = (Lenguaje)o. int id.8). Lenguaje lenB = (Lenguaje)oB.5). aLenguaje[2] = new Lenguaje("JavaScript". aLenguaje[0] = new Lenguaje("C". } public class OrdenaNombres : IComparer{ public int Compare(object oA. aLenguaje[3] = new Lenguaje("Java".3). aLenguaje[1] = new Lenguaje("ActionScript". } } public override string ToString(){ return nombre + " " + id. }else{ return 0. using System.id){return 1. aLenguaje[4] = new Lenguaje("PHP".id = id. } int IComparable.id){ return -1.WriteLine(len). foreach(Lenguaje len in aLenguaje) Console.nombre = nombre.Sort(aLenguaje).Collections.class App{ public static void Main(){ Lenguaje[] aLenguaje = new Lenguaje[5]. public class Lenguaje : IComparable{ string nombre. if(this. this.id > lenguajeB. int id){ this. Cada clase sólo puede implementar una interface a la vez. } } Salida: PHP 1 JavaScript 2 C 3 ActionScript 5 Java 8 Interface IComparer Es posible definir múltiples tipos de ordenamientos gracias a que el diseño del Framework provee esta capacidad. object oB){ Lenguaje lenA = (Lenguaje)oA. por lo que solamente se podría permitir un tipo de ordenamiento.id < lenguajeB.1).

} } Salida: ActionScript 5 C 3 Java 8 JavaScript 2 PHP 1 IComparer Como Propiedad En el ejemplo anterior el usuario tiene que crear una instancia del ordenamiento deseado y hacer un cast de IComparer .Add(aLenguaje[2]). aList. } . aLenguaje[1] = new Lenguaje("ActionScript". int id.Add(aLenguaje[0]).id){return 1.Compare(lenA.3). aList.Coll ections. public class Lenguaje : IComparable{ string nombre.} if(this. aList. aLenguaje[0] = new Lenguaje("C".5). using System. aLenguaje[2] = new Len guaje("JavaScript".id = id. aList.WriteLine(len). }else{ return 0. public Lenguaje(string nombre. } int IComparable.Add(aLenguaje[1]).nombre. aLenguaje[3] = new Lenguaje("Java".OrdenaNombres()). if(this.id){ return -1.Sort((IComparer) new Lenguaje.Add(aLenguaje[4]).id < lenguajeB.Add(aLenguaje[3]).nombre). pero es posible simplificar esto utilizando una propiedad estática y hacerlo por el usuario: using System.CompareTo(object o){ Lenguaje lenguajeB = (Lenguaje)o.return String. aList.1). foreach(Lenguaje len in aList) Console.id > lenguajeB.2).8). ArrayList aList = new ArrayList(). aLenguaje[4] = new Lenguaje("PHP". int id){ this. aList.nombre = nombre. this.lenB. } } } class App{ public static void Main(){ Lenguaje[] aLenguaje = new Lenguaje[5].

3).WriteLine(len).nombre).Compare(lenA. aLenguaje[4] = new Lenguaje("PHP". } public static IComparer Ordena{ get{ return (IComparer) new OrdenaNombres().nombre.Sort(aLenguaje.2). Lenguaje. object oB){ Lenguaje lenA = (Lenguaje)oA. aLenguaje[2] = new Lenguaje("JavaScript". Array.} public override string ToString(){ return nombre + " " + id. return String.lenB. } } public class OrdenaNombres : IComparer{ public int Compare(object oA. } } Salida: ActionScript 5 C 3 Java 8 JavaScript 2 PHP 1 Expresiones Regulares Las Expresiones Regulares proveen un método muy poderoso para hacer funciones de busquedas y reemplazamiento.Ordena). Operador as El Operador as checa el tipo del operador izquierdo y si puede ser convertido explicitamente a el operador derecho. foreach(Lenguaje len in aLenguaje) Console. aLenguaje[1] = new Lenguaje("ActionScript". Secuencias de Escape . Lenguaje lenB = (Lenguaje)oB. si no puede ser convertido la operación falla y regresa null .1). aLenguaje[0] = new Lenguaje("C". se obtiene como resultado el objeto convertido a el operador derecho. Este operador sólo puede se utilizado con clases. aLenguaje[3] = new Lenguaje("Java".5). } } } class App{ public static void Main(){ Lenguaje[] aLenguaje = new Lenguaje[5]. 8).

un valor de tipo boxed no puede ser unboxed (convertido) a un tipo compatible. using System. Otra forma de definir el concepto boxing es que este mecanismo permite que los value types parezcan o tengan la apariencia de reference types. Cuando un tipo de valor es boxed se asigna espacio a una instancia de objeto y el valor del value type es copiado al nuevo objeto. class App{ public static void Main(){ int iEdad = 33.Secuencia de Escape ' " \ a b f n r t v Boxing Descripción Comilla simple Comilla doble Diagonal invertida Nulo Alert Retroceso Form Feed Nueva línea Retorno de carro Tabulador Tabulador vertical Boxing es un mecanismo que crea una liga entre los tipos de valores y las tipos de referencia permitiendo a un tipo de valor ser convertido a un tipo objeto y viceversa. en ese caso primero obtenga el valor correcto y después realice un cast al tipo que requiera: (valorRequerido) valorRequerido vr = (valorRequerido)(valorBoxed)objeto. Si requiere obtener otro tipo de valor diferente al que contiene el boxed. . object oNumero = iEdad. //Unbox //cast necesario porque oNumero podría contener cualquier tipo de objeto } } Nota. Observe las siguientes líneas: int iNumero = 2012. //Box int iNumero = (int)oNumero. durante la conversión unboxing el tipo debe coincidir exactamente. Conversiones Boxing Boxing un valor se refiere a la conversión implícita de cualquier tipo de valor al tipo objeto.

object oNumero = iNumero.InvalidCastException ): int iNumero = 2012. donde el valor de la variable nNumero es copiado al objeto oNumero . Suponga que tiene una variable de tipo int y asigna el valor de esta variable int a un objeto. si no se escribe un constructor para la clase el compilador provee automáticamente un constructor default. lo que implica que los valores son independientes y no hay una liga entre ellos: using System. . Console. después declara una variable de tipo double y aplica un cast (double) al objeto para asignar su valor a la variable double. Conversiones Unboxing Al contrario que Boxing. Console.NET el programador no puede controlar la destrucción de objetos. al realizar la operación Unboxing C# checa que el value type que se requiere este almacenado en la instancia del objeto. Unboxing es un mecanismo de una operación explícita. En el runtime . primero se ejecuta el constructor de la clase el cual contiene código de inicialización. //invocación implicita a una operación boxing double dNumero = (double)oNumero. entonces las variables entera y objeto existen en la pila pero los valores de los objetos residen en el área o espacio asignado. class Box{ public static void Main(){ int iNumero = 2012. //invocacion explícita ( cast) //CLR dispara la excepción System. por lo que es necesario indicar al compilador que tipo de valor deseamos extraer de un objeto. object oNumero = iNumero. si la verificación es exitosa el valor es Unboxing. } } Al ejecutar el código notará que el valor de oNumero es 2005 y el valor de iNumero no cambio permanece en 2012.WriteLine(oNumero). el objeto contiene sólo un valor int y no puede ser asignado a la variable double porque el CLR dispara una excepción (System. //invoc ación implicita a una operación boxing oNumero = 2005.WriteLine(iNumero). //invocación implicita a una operación boxing Al asignar el valor de la variable entera nNumero a una variable objeto se realiza internamente una operación boxing.InvalidCastException Constructores y Destructores Antes de acceder a los métodos o propiedades de una clase.object oNumero = iNumero.

class NombreClase{ public NombreClase() : base(){} //Constructor que provee el compilador } Las características de un constructor son: y y y y y y y Siempre tiene el mismo nombre que la clase. private int iMotor. iPuerta = Puerta. private int iVentana. es posible crear un constructor private . espacial //Constructor: public Vehiculo(int Rueda. Por lo general tienen el modificador público. Si la clase sólo contiene miembros estáticos. Al codificar no se está limitado a los parámetros del constructor.} set{iRueda = value. anf ibio. iAsiento = Asiento. private string sTipo. int Asiento. Son utilizados para inicializar varibles. sTipo = Tipo. string Tipo){ iRueda = Rueda. int Ventana. class Vehiculo{ //Propiedades: private int iRueda. private int iAsiento. Los constructores son invocados invocados automaticamente sólo cuando una instancia de un objeto es creada con new. using System.Un constructor puede invocar un constructor del tipo base utilizando la sintaxis base . iVentana = Ventana. iHelice = Helice. _ int Motor. int Puerta. lo cual significa que no podrá ser accesible fuera de la calse o que sólo se puede acceder desde la clase. int Helice. Un objeto no puede ser instanciado desde la definición de la clase. private int iHelice. } //Lectura/escritura de propiedades: public int Ruedas{ get{return iRueda. No puede ser invocado desde la definición de la clase. iMotor = Motor.//Aereo.} } . private int iPuerta. No tiene declarado un tipo de regreso. terrestre. es posible enviar argumentos iniciales para inicializar ciertos miembros.

Motores). Es posible escribir un método que libere recursos después de ser utilizados.} set{iHelice = value. } } : " + : " + : " + : " + : " + : " + : " + En un sentido estricto en C# no se tienen destructores. pero porque escribir un método para liberar recursos si existe un destructor: .Ruedas). Console.0. Console.WriteLine("Tipo MiAvion. Console.WriteLine("Helices MiAvion.WriteLine("Ventanas MiAvion.100.Helices).Asientos).1. Console. Console.} } public string Tipo{ get{return sTipo.} } public int Asientos{ get{return iAsiento.} } } //Aplicación: class AplicConstructor{ public static void Main(){ Vehiculo MiAvion = new Vehiculo(2.WriteLine("Ruedas MiAvion."Aereo"). pero el termino destructor se refiere a la liberación de recursos.200.public int Puertas{ get{return iPuerta. Console.} } public int Motores{ get{return iMotor.WriteLine("Puertas MiAvion.WriteLine("Motores MiAvion.} set{iAsiento = value.Puertas).} set{iVentana = value.} set{iMotor = value.} } public int Ventanas{ get{return iVentana.} } public int Helices{ get{return iHelice.3.} set{sTipo = value. Console.WriteLine("Asientos MiAvion.Ventanas).} set{iPuerta = value.Tipo).

entonces es buena idea proveer un método explícito Release . ya que el runtime sólo garantiza que algo es invocado después del inicio del programa y antes de ser creada la primer instancia de un objeto. el cual no es invocado inmediatamente después que las variables quedan fuera de ámbito. Parámetros De algún modo se deben pasar valores a un método y también se debe regresar el resultado de un método.public ~NombreClase(){ //liberar recursos } La razón por la cual se debería escribir un método adicional es por el recolector de basura. Constructor Estático Un Constructor Estático podría ser invocado antes de ser creada la primer instancia de un objeto. Para declarar un constructor estático se utiliza el modificador static : class NombreClase{ static NombreClase(){ . los métodos son parte del Tipo (class). y es útil para configurar el trabajo que necesita hacerse una vez. la colección garbage de cualquier forma realiza la liberación de cualquier objeto. En el runtime . } } Métodos La mayor parte de la funcionalidad es implementada en los métodos. pero es una buena práctica no olvidar liberar los recursos. } La invocación del método Release en el destructor no es obligatoria. lo que significa que no puede ser determinada la instancia que es creada en el constructor estático. sólo se invoca el recolector de basura en ciertos intervalos o condiciones de memoria. Lo que podría suceder es que los recursos se agoten antes de ser utilizados. el cual también puede ser invocado por el destructor: public void Release(){ //Liberar recursos } public ~NombreClase(){ Release(). los valores son manipulados en: .NET el usuario no tiene control sobre cuando el constructor estático es invocado. pero los métodos no son parte de la instancia (object ). .

2000)). Console.Menor(21.Valores en Parámetros in Se utilizan valores en parámetros para pasar una variable por valor a un método.10.Menor(21. la variable del método es inicializada con una copia del valor del caller (quien realizó la invocación).int iMesA.WriteLine(iA + " > " + iB). 21.2005)).2000.int iAñoB){ int iA = (iDiaA * 10000) + (iMesA + 100) + (iAñoA).2000)).9.2000.9.int iDiaB. 21.10.10. int iB = (iDiaB * 10000) + (iMesB + 100) + (iAñoB).Mayor(21.WriteLine("La fecha mayor es : " + MiFecha.1971.9. Console. int iB = (iDiaB * 10000) + (iMesB + 100) + (iAñoB). }else{ return iDiaB + "/" + iMesB + "/" + iAñoB.9.10. }else{ return iDiaB + "/" + iMesB + "/" + iAñoB.WriteLine("La fecha menor es : " + MiFecha.int iAñoA. Console.int iDiaB.Menor(21.int iMesB.int iMesA. using System. //Test Line (Delete) if(iA < iB){ return iDiaA + "/" + iMesA + "/" + iAñoA.Mayor(21.2000.2000. } } } class AplicFecha{ public static void Main(){ Fecha MiFecha = new Fecha().WriteLine("La fecha menor es : " + MiFecha.10.int iAñoA.1971)).WriteLine("La fecha mayor es : " + MiFecha.WriteLine(iA + " < " + iB).int iMesB. 21. Console.9. } } public string Menor(int iDiaA. Console.2005)).Mayor(21.1971)). 21.9.WriteLine("La fecha menor es : " + MiFecha. Console.WriteLine("La fecha mayor es : " + MiFecha. Console.10. Console.int iAñoB){ int iA = (iDiaA * 10000) + (iMesA + 100) + (iAñoA). public class Fecha{ public string Mayor(int iDiaA. 21. //Test Line (Delete) if(iA > iB){ return iDiaA + "/" + iMesA + "/" + iAñoA.1971. 21. } .

modificar el valor y regresarlo como resultado del método. . porque se modifico de manera directa } } class Parametros{ public static void Main(){ Param MiParam = new Param(). el compilador de C# no permite utilizar variables que no han sido inicializadas. Al contrario de los valores en parámetros no se pasa una copia del valor. //Se modifica el valor directamente //No se regresa un valor. el resultado de los métodos Mayor y Menor es pasado a el caller como un valor de regreso y es manipulado sin ser almacenarlo en una variable intermedia. para ello se utiliza el modificador ref seguido del tipo y del nombre del parámetro. public class Param{ public vo id ParametroRef(ref int RefParametro){//No regresa un valor explícito RefParametro *= RefParametro. por lo que antes de utilizar o establecer los valores de una variable debe ser inicializada. Valores en Parámetros ref Es posible pasar un valor como parámetro a un método. int iValorRef = 5. } } //Se requiere inicializar el Good Practice.//Se invoca el método pasando la referencia del valor Console. Inicializar la variable al declararla. 2.ParametroRef(ref iValorRef). sino la referencia del valor y por ello al modificar el valor se hace la modificación directa. valor MiParam. se recomienda tener dos variables. Si no hay modificadores los parámetros son siempre pasados por valor. una en el parámetro y otra en el parámetro ref.WriteLine("ref : " + iValorRef). para ello existen dos formas de hacerlo: 1. es posible utilizar expresiones constantes.} Al pasar un valor y no una referencia a la variable. Recuerde. también es necesario inicializar el valor que se pasa como paramétro por medio de una variable intermedia y no directamente a través de una expresión constante: using System.

class MiClase{ private int MiPropiedad. Console.WriteLine("MiEdad : " + MiEdad).MiPropiedad = MiOutParam. } 10. 15.MiPropiedad : " + MiObjeto. this. public void AsignarValor(out int MiOutParam){//Se cambia la definición de la función 24. 12. public static void Main(){ 28. } 27.MiPropiedad). 20. using System. 16. public class Param{ public void ParametroOut(out int OutParametro){ OutParametro = 4 * 4. 14. 5. using System.WriteLine("MiObjeto. MiObjeto.WriteLine("MiEdad : " + MiEdad). 4. 32. Valores en Parámetros out Un parámetro out puede ser utilizado sólo para contener el resultado de un método. } 17. Por ejemplo cambiar la definición de la función y utilizar un parámetro out en vez de un parámetro ref.MiPropiedad = MiRefParam.MiPropiedad).MiPropiedad : " + MiObjeto. MiObjeto. class MiClase{ 6. private int MiPropiedad. . MiClase MiObjeto = new MiClase(). int MiEdad = 33. 29. 23. } 34.//No se inicializa la va riable 30. 31. es necesario especificar el modificador out para indicar el tipo de parámetro. MiClase MiObjeto = new MiClase(). this. 9. int MiEdad. 26. 19.WriteLine("MiObjeto.AsignarValor(out MiEdad). a diferencia de los parámetros ref el caller no necesita inicializar la variable antes de invocar el método: using System. Console.//Se inicializa la variable al declararla 13. public static void Main(){ 11.3. } Los parámetros out son exactamente como los parámetros ref excepto que una variable sin inicializar puede ser pasada como parámetro y el caller define un parámetro out en vez de ref. public void AsignarValor(ref int MiRefParam){ 8.AsignarValor(ref MiEdad). 22. Console. MiOutParam = 33. } 18. 33. 7. 21. 25. Console.

WriteLine("out : " + iValorOut). porque es regresado en el parámetro out } } class Parametros{ public static void Main(){ Param MiParam = new Param(). //Se invoca el método con un parámetro out Console. //No se gregresa un valor.//Resultado de la invocación del método } } //Se requiere inicializar el .ParametroOut(out iValorOut). //Se invoca el método con un parámetro out Console.WriteLine("out : " + iValorOut). int iValorOut. Console. //No se requiere inicilizar el valor MiParam. //Se modifica el valor directamente //No se regresa un valor.WriteLine("ref : " + iValorRef). valor MiParam. int iValorRef = 5.ParametroIn(3)).ParametroRef(ref iValorR ef).ParametroOut(out iValorOut).WriteLine(" in : " + MiParam.//Se invoca el método pasando la referencia del valor Console. } public void Parametro Ref(ref int RefParametro){//No regresa un valor explícito RefParametro *= RefParametro. Ref y Out using System.//No se gregresa un valor. public class Param{ public int Parametro In(int InParametro){ return InParametro * InParametro.//Resultado de la invocación del método } } Ejemplo de Parámetros In. porque se modifico de manera directa } public void Parametro Out(out int OutParametro){ OutParametro = 4 * 4. porque es regresado en el parámetro out } } class Parametros{ public static void Main(){ Param MiParam = new Param(). //No se requiere inicilizar el valor MiParam. int iValorOut.

//Se invoca el método redefinido en la clase derivada: Console. Cuando se invoca un método virtual se está derivando el método de clase que es invocado y no el método de la clase base: ((ClaseBase)InstanciaClaseDerivada). es decir.//Se redefine la funcionalidad del método } } class RedefinirMetodos{ public static void Main(){ ClaseBase ClsBase = new ClaseBase().3)).Calculo(5. no es posible cambiar los modificadores que definen al método.Redefinición de Métodos (Overriding) Uno de los principios básicos de la programación orientada a objetos es el polimorfismo. } } class ClaseDerivada : ClaseBase{//Se deriva de la clase base public override int Calculo(int iA.Calculo(5. //Se crea una instancia de la clase derivada: ClaseDerivada ClsDer = new ClaseDerivada().NombreMetodo_PuedeSerRedefinido(). el cual hace posible que una clase derivada pueda redefinir (override) métodos de la clase base.WriteLine("Clase derivada : " + ClsDer. class ClaseBase{ public virtual int Calculo(int iA. Para indicar que una clase deriva de otra se utiliza el operador : el cual denota esta acción: class ClaseDerivada : ClaseBase{} El siguiente ejemplo muestra como se redefine un método: using System. al derivar de la clase base se agrega la palabra reservada override en el nuevo método: override void NombreMetodo_PuedeSerRedefinido() No es posible cambiar la accesibilidad de un método que es redefinido. int iB){//Se especifica que el método será redefinido return iA . int iB){ return iA + iB.3)).WriteLine("Clase base : " + ClsBase. } . Console.iB. Para indicar que se puede redefinir el método se emplea la palabra reservada virtual : virtual void NombreMetodo_PuedeSerRedefinido Después.

MetodoOculto().MetodoOculto(). } } class Hiding{ public static void Main(){ ClaseDerivada MiClaseDerivada = new ClaseDerivada(). } } El código anterior demuestra que es posible derivar una clase que implementa un método que la clase base no contiene. esto se logra haciendo uso de una característica especial de la redefinición de métodos llamada ocultamiento de métodos y al derivar de la clase base: using System. MiClaseDerivada. se produce un error: using System. MiClaseDerivada.} Ocultamiento de Métodos (Hiding) Es posible ocultar métodos de la clase base.WriteLine("Hiding Methods"). } } class Hiding{ public static void Main(){ ClaseDerivada MiClaseDerivada = new ClaseDerivada(). class ClaseBase{ public void MetodoOculto(){ Console. } } .WriteLine("Hiding Methods"). Por otro lado si la clase base contiene el método y se trata de derivar una clase que trata de implemetar un método que si contiene la clase. class ClaseBase{ //Sin código } class ClaseDerivada : ClaseBase{//Clase derivada de la clase base public void MetodoOculto(){//Método Oculto Console. } } class ClaseDerivada : ClaseBase{//Clase derivada de la clase base public void MetodoOculto(){//Se implementa un método que si existe Console.WriteLine("Hiding Methods").

MetodoOculto()' because it hides inherited member 'ClaseBase.Metod oOculto(). se le indica al compilador que se está redefiniendo el método de la clase base y que debería ocultar este método.MetodoOculto()' Hiding.WriteLine("Hiding Methods using new"). ya que si es posible ocultar un método contenido en la clase base: using System. class NombreClase{ int iNombrePropiedad.El compilador indicará un mensaje similar al siguiente: Hiding.MetodoOculto().cs(10.WriteLine("Hiding Methods").cs(4. una propiedad permite especificar a un conjunto de sentencias realizar el acceso mientras se permita utilizar el campo o arreglo. } } Al hacer uso del modificador new. en vez de permitir a un usuario acceder directamente a un campo o arreglo. } } class HidingClassMet{ public static void Main(){ ClaseDerivada MiClaseDerivada = new ClaseDerivada().14): (Location of symbol related to previous warning) El error principal es que no se hace uso del modificador new. Propiedades Las propiedades son convenientes para separar la interfaz de un objeto de su implementación. //declaración de la propiedad //Especificación del acceso a la propiedad public int NombrePropiedad { . } } class ClaseDerivada : ClaseBase{//Clase derivada de la clase base new public void MetodoOculto(){//Método Oculto Console.14): warning CS0108: The keyword new is required on 'ClaseDerivada. MiClaseDerivada. class ClaseBase{ public void MetodoOculto(){//Método Oculto Console. Se puede asegurar de invocar el método que redefine la clase derivada utilizando la siguiente sintaxis: ((ClaseBase)MiClaseDerivada).

Ciudadano.} } } Ejemplo: using System.Mexicano = true. Propiedades (properties) Los atributos son implementados como variables miembro con acceso público via accessors (get o set).} } private bool bMexicano. Console. Campos (fields) 2.Edad = 33. Ciudadano.WriteLine("Nombre Ciudadano : " + Ciudadano.} set{bMexicano = value.Nombre).} set{sNombre = value. public string Nombre{ get{return sNombre. Los accessors (get o set ) especifican las sentencias que son ejecutadas cuando se requiere leer o escribir el valor de una propiedad.WriteLine("Edad Ciudadano : " + Ciudadano. Console.get{return iNombrePropiedad. public bool Mexicano{ get{return bMexicano.} } private string sNombre. } } Existen dos maneras de exponer el nombre de los atributos: 1. class Propiedades{ private int iEdad.} set{iEdad = value.} set{iNombrePropiedad = value.WriteLine("Mexicano Ciudadano : " + Ciudadano.} } public static void Main(){ Propiedades Ciudadano = new Propiedades(). Ciudadano.Nombre = "Gerardo Ángeles Nava". public int Edad{ get{return iEdad.Edad). .Mexicano). Console.

public int Sueldo{ get{return iSueldo.} set{iSueldo = value.WriteLine("Edad : " + Empleado. sólo es posible establecer el valor de la propiedad. El siguiente ejemplo muestra como se implentan los accessors para las propiedades: using System. Empleado. get only. u override .} } } class AplicPersona{ public static void Main(){ Persona Empleado = new Persona().Sueldo). el valor puede ser fabricado cuando se necesite sin almacenarlo. class Persona{ private int iSueldo. set only. Propiedades Estáticas Propiedades estáticas no pueden ser declaradas con los modificadores virtual . en este caso el accessors set es pasado en el nuevo valor para la propiedad en el parámetro value . ya que el valor actual es almacenado en este que es accesible dentro de la clase. } } Note. Accessors Es posible ocultar los detalles de la estructura de almacenamiento de la clase reordenando los accessors. abstract Las propiedades estáticas pueden ser inicializadas hasta que sea necesario hacerlo. es posible tener acceso al valor de la propiedad para leerlo y escribirlo. sólo es posible leer el valor de la propiedad.Los accessors para la lectura del valor de una propiedad son marcados con la palabra reservada get y los accessors para modificar el valor de una propiedad son marcados con la palabra reservada set. Si en vez de utilizar propiedades desea utilizar campos deberá dejar fuera los accessors y redefinir la variable como: public int Sueldo. Console. . Las operaciones que pueden realizarse con los atributos son: y y y Implementar get y set. que se utiliza el parámetro value .Sueldo = 33.

} } } class App{ public static void Main(){ Persona ET = Pers ona. int iBrazos. sintaxis: atributos modificadores declarador{instrucciones} Los índices o indexers regresan o establecen un string en un índice dado. para ello se utiliza la característica de C# indexer .0. this. int iOjos. } public static Persona Piernas{ get{ return(new Persona(2.Piernas.8)). } } public static Persona Brazos{ get{ return(new Persona(0. La parte del declarador consiste del tipo string y la palabra reservada this para denotar el indexer de la clase: public string this[int iIndex]{ get{intrucciones} set{intrucciones} } Las reglas de implementación para get y set son las mismas reglas de las propiedades. public Persona(int piernas. } } public static Persona Ojos{ get{ return(new Persona(0.4.0)). this.WriteLine(ET).iBrazos = brazos. } } Índices Es posible incluir una forma de acceso indexado a la clase tal como si la clase se tratará de un arreglo. . también existen restricciones como que es necesario especificar al menos un parámetro y los modificadores ref y out no están permitidos. class Persona{ int iPiernas. la única diferencia es que la lista de parámetros se define libremente entre los corchetes.0. Console. int ojos){ this.0)).iPiernas = piernas. int brazos.using System.iOjos = ojos. los indexers no tienen atributos por lo que utilizan el modificador public .

ya que una clase publica el evento que puede lanzar y las clases que están interesadas en un evento específico pueden subscribir al evento.} } public int Contador{ get{return aIPs. MiDNS. int iContador = MiDNS.} } } class AplicResolverDNS{ public static void Main(){ ResolverDNS MiDNS = new ResolverDNS().mx").exe AplicResolverDNS. using System. Para tratar de manera fácil con eventos. Console. La rutina o tarea que un evento podría invocar es definida por un delegado. la convención de diseño para eventos es emplear dos parámetros. for(int i = 0. } public IPAddress this[int iIndex]{ get{return aIPs[iIndex].informatique. i < iContador.WriteLine(MiDNS[i]).Ejemplo: using System.AddressList. } } } Si el namespace para la clase DNS no está contenida en la biblioteca central. aIPs = IPHE.com. public void Resolver(string strHost){ IPHostEntry IPHE = Dns. iContador).Resolver("www. Eventos Una clase puede usar un evento para notificar a otra clase o clases que algo ocurrio.WriteLine("Se encontro {0} p ara el host ".Net. los eventos usan el idioma "publish-subscribe". donde el primer parámetro es el objeto que lanza el evento y el segundo parámetro es un objeto que contiene la información acerca del evento el cual siempre deriva de la clase EventArgs .Length. al compilar incluya la referencia a la biblioteca que la contiene: csc /r:System.dll /out:resolver.cs Los índices pueden tener más que un parámetro para simular un arreglo virtual multidimensional.Contador.Net.//Directiva namespace para la clase DNS class ResolverDNS{ IPAddress[] aIPs. . i++){ Console.GetHostByName(strHost).

CD. } } Modificadores Miembro . Los delegados pueden ser implementados como métodos o instancias estáticas. Modificadores Los modificadores pueden clasificarse en: y y y Modificadores de Clase Modificadores Miembro Modificadores de Acceso Modificadores de Clase Existen dos tipos de modificadores de clase: 1. abstract class ClaseAbstracta{ abstract public void MiMetodo(). ambos accesos comparten la comodidad de tipo que el evento debe tener delegate. } } public class ModificadorClase{ public static void Main(){ ClaseDerivada CD = new ClaseDerivada().WriteLine("Clase sealed").MiMetodo(). Cada evento puede ser utilizado por cero o más clientes y un cliente puede utilizar un evento en cualquier momento. abstract o Una clase abstracta no puede ser inicializada o Sólo clases derivadas que no son abstractas pueden ser inicializadas o Las clases derivadas deben implementar todos los miembros abstractos de la clase base abstracta o No puede aplicarse un modificador sealed a una clase abstracta 2. sealed o Clases sealed no pueden ser heredadas o Utilice este modificador para prevenir herencia accidental Ejemplo: using System. } sealed class ClaseDerivada:ClaseAbstracta{ public override void MiMetodo(){ Console.Los eventos pueden ser declarados como campos o propiedades de clase.

operadores y constructores. de otra forma el tipo de acceso por default es implícito. este modificador de acceso es el menos restrictivo. No es permitido el acceso desde fuera. por lo tanto no puede contener referencias de la clase. un método o accessor pueden ser redefinidos por las clases que reciben la herencia. Este modificador aplica a campos y variables locales La expresión constante es evaluada en tiempo de compilación. propiedades.Algunos modificadores miembro son: y abstract o Indica que un método o accessor no contiene una implementación. el miembro es accesible en la clase y todas las clases derivadas. y const o o y y y event o Define un campo o propiedad como tipo event o Utilizado para ligar al código cliente a eventos de la clase extern o Indica al compilador que el método es implemetado externamente override o Utilizado para modificar un método o accessor que es definido virtual en cualquiera de las clases base y o La firma de redefinición y método base debe ser el readonly o Un campo declarado con el modificador readonly static o Miembros mismo puede ser cambiado sólo en su declaración o en el constructor de la clase contenedora y que son declarados static pertenecen a la clase y no a una instancia de la clase o Pueden utilizarse modificadores static con campos. o La clase que recibe la herencia debe proveer la palabra reservada override . El acceso protected permite a otras clases depender de la implementación interna de la clase y por lo tanto deberían ser otorgados sólo cuando sea necesario. . el miembro es accesible desde cualquier parte. y virtual o Indican que Modificadores de Acceso Los modificadores de acceso definen el nivel de acceso que cierto código tiene en los miembros de la clase como métodos y propiedades. Los modificadores de acceso son: y y public . que son implicitamente virtual . protected . métodos. Es necesario aplicar el modificador de acceso deseado a cada miembro.

Sentencia switch Sentencia if Al escribir uno o varios flujos de acción el código contenido en estos se ejecutará siempre y cuando la evaluación de la expresión en la sentencia if se evalue como verdadera (tenga cuidado en C# if(0){} o if(1){} no es válido). en otras palabras internal protected permite acceso internal o protected . private . es visto como público a nivel del componente . este tipo de acceso es otorgado a todo el código que es parte del mismo componente (aplicación o biblioteca) . Sentencias de Iteración Sentencias de Selección Las Sentencias de selección son aquellas que se utilizan para realizar operaciones basadas en el valor de una expresión. Este modificador permite que un miembro sea accesible desde las clases en el mismo ensamblaje.NET. Las Sentencias de selección son aquellas que se utilizan para escribir diferentes flujos de acción en base a una condición dada. existen dos tipos de sentencias de selección: 1. Sentencias de Selección 2. internal. Sentencias de Control Las Sentencias de Control se emplean para controlar la ejecución y flujo del código. Las clases derivadas no pueden acceder al código. Sentencia if 2.y y sólo el código dentro de la misma clase puede acceder este miembro.NET y privado fuera de este. if(expresión -booleana){ la expresión se evaluo verdadera } Es posible indicar código alterno en caso de que la expresión booleana se evalue falsa: if(expresión -booleana){ la expresión se evaluo verdadera }else{ la expresión se evaluo falsa } . pero no desde las clases fuera de este. las cuales se dividen en: 1. El modificador internal protected provee mayor flexibilidad en como una clase es definida y se utiliza para indicar que un miembro pueder ser accedido desde una clase internal o protected .

char chLetra = sNombre[0]. Recuerde que siempre podrá realizar un cast explícito.Nota C# no puede convertir valores numéricos a booleanos. si el valor cumple con la condición Los operadores de la tabla son implementados via la sobrecarga de operadores y la implementación es especifica para el tipo de dato.WriteLine("?"). }else{ EsMayuscula(chLetra). } /* No es soportado por C# if(0){ Console. >= Evalua Verdadero.WriteLine("se evaluo verdadero").IsDigit(chLetra)){ Console. EsMinuscula(chLetra). <=. si se comparan dos variables de diferente tipo se realiza una conversión implícita que debe existir para que el compilador cree el código necesario automáticamente. class Caracteres{ public static void Main(){ string sNombre = "Gerardo Angeles Nava". si ambos valores son los mismos Verdadero. class SeleccionIf{ public static void Main(){ if(1 == 1){ Console. si los valores son diferentes Verdadero. Ejemplo using System.//Extrae el segundo caracter del string . >. si está habituado a otra forma. solo puede hacer comparaciones entre ellos para evaluar el resultado de la expresión el cual es un valor booleano.WriteLine(chLetra + " es un dígito"). en la siguiente tabla se muestran los operadores válidos en C#: Operador == != <. } */ } } Nota el operador de igualdad en C# es ==.//Extrae el primer caracter del string if(Char. } chLetra = sNombre[1]. using System. sera cosa tiempo acostumbrarse a escribirlo correctamente.

} } } En el ejemplo anterior se muestra la aplicación de la sentencia de selección if y el uso del método IsDigit de la clase Char. porque puede que nunca se le asigne el valor correspondiente a la variable en caso de que una expresión anterior se evalue verdadera: if(a == b || (c == (iValor = d))){} En el ejemplo anterior. Good Practice: nunca asigne valores a variables dentro de una condición que utiliza operadores lógicos (&&.!).WriteLine(chCaracter + " minúscula"). }else{ EsMayuscula(chLetra).IsDigit(chLetra)){ Console. EsMinuscula(chLetra).WriteLine(chLetra + " es un dígito").WriteLine(chLetra + " es un dígito"). . si la expresión a == b se evalua verdadera entonces la variable iValor nunca contendrá el valor d.IsDigit(chLetra)){ Console. } } public static void EsMayuscula(char chCaracter){ if(chCaracter >= 'A' && chCaracter <= 'Z'){ Console. Sentencia switch La sentencia de selección switch tiene una expresión de control y los flujos de código alternos son ejecutados dependiendo del valor constante asociado con esta expresión.if(Char. } sNombre = "123". chLetra = sNombre[2]. switch(expresion -de-control){ case expresion -contante: sentencias.||. break.//Extrae el tercer caracter del string if(Char. }else{ EsMayuscula(chLetra). también se muestra como determinar si un caracter correponde a las letras mayúsculas o minúsculas.WriteLine(chCaracter + " mayúscula"). EsMinuscula(chLetra). } } public static void EsMinuscula(char chCaracter){ if(chCaracter >= 'a' && chCaracter <= 'z'){ Console.

case expresion -contante: goto default. case 6: Console. case 4: Console.case expresion -contante: goto case 2. ulong. break. case 5: Console. case 3: Console. break. short.WriteLine("Mayo"). ¿Cómo funciona la sentencia de selección switch ? y y y y Se evalua la expresión de control Si la expresión constante en las etiquetas case coincide con el valor evaluado en la expresión de control. break. break. . } Los tipos de datos permitidos para la expresión de control son sbyte . break. string o un tipo enumeración (enumeration ). i <= 12. break. case 7: Console.WriteLine("Enero"). break. i++){ Mes(i). } } public static void Mes(int iMes){ switch(iMes){ case 1: Console.WriteLine("Marzo").WriteLine("Junio").WriteLine("Febrero"). long.WriteLine("Julio"). entonces las sentencias contenidas para ese caso son ejecutadas Si la expresión constante en las etiquetas case no coincide con el valor evaluado en la expresión de control. class SentenciaSwitch{ public static void Main(){ for(int i = 0. byte. uint. case 2: Console. entonces el control es transferido al final del bloque switch Ejemplo: using System. default: sentencias. char. ushort .Write Line("Abril"). entonces el código contenido en el caso por default es ejecutado Si la expresión constante en las etiquetas case no coincide con el valor evaluado en la expresión de control y no existe un caso por default .

break. Opcion(iOpcion). break. case 6: Console. break. case 12: Console. break. case 10: Console. case 11: Console. Opcion(iOpcion). iOpcion = 8.WriteLine(" seis"). class SentenciaSwitch{ public static void Main(){ int iOpcion = 4. case 8: goto default.WriteLine("Diciembre"). break. case 9: Console. default: Console.WriteLine(" diez"). case 10: Console. case 4: Console.case 8: Console. iOpcion = 10. Opcion(iOpcion). } public static void Opcion(int iValor){ switch(iValor){ case 2: goto case 6. break. break. default: .WriteLine("Septiembre"). } } } Es posible utilizar sentencias goto dentro del switch de la siguiente manera: y y goto case expresion -contante goto default Ejemplo: using System.WriteLine("Noviembre").WriteLine("Mes no válido").WriteLine("Octubre"). break.WriteLine("Agosto"). break.WriteLine(" cuatro"). Opcion(iOpcion). iOpcion = 2.

break. no será posible evaluar otro tipo de expresión. Es posible salir de un ciclo for a través de las instrucciones: 1. long lAux = 1. long lCalcular = Int64. Ejemplo: Factorial 5"). iterador) Los componentes de la sentencia for: inicializador. goto Ejemplo: using System. for(lAux = 1. lAux++){ lFactorial *= lAux.WriteLine(" por defecto"). class Factorial{ public static void Main(string[] aArgs){ if(aArgs. no son obligatorios. condición.WriteLine("Debe proporcionar un argumento. } } } Sentencias de Iteración (repetición) Las Sentencias de Iteración (también conocidas como looping statements) son aquellas que nos permiten ejecutar un bloque de código repetidamente mientras una condicíon específica sea verdadera: y y y y for foreach while do Sentencia for La Sentencia for se utiliza cuando se conoce previamente cuantas veces ha de repetirse un bloque de código. lAux <= lCalcular. Sintaxis: for(inicializador. break 2. . iterador. } long lFactorial = 1.Console.Parse(aArgs[0]). Este bloque se repetira mientras la condición evalue una expresión booleana verdadera. return.Length == 0){ Console. condición.

No se puede pasar la variable de iteración como un parámetro ref o out. lAux. lCalcular.WriteLine("Elemento " + i + " = " + aArgs[i]). lFactorial).WriteLine("{0}! es {1}". foreach(Tipo indentificador in expresión){} La variable de iteración es declarada por el Tipo. Es posible acceder a las colecciones Keys y Values de la interfaz IDictionary : using System.WriteLine("{0}! * {1}". indentificador y expresión correspondiente a la colección. En el siguiente ejemplo el método GetEnvironmentVariables() regresa una interfaz de tipo IDictionary . class App{ public static void Main(string[] aArgs){ for(int i = 0. class App{ public static void Main(string[] aArgs){ foreach(String s in aArgs){ Console. clase o interface que regresa debe tener un método público MoveNext y una propiedad pública Current . } } Sentencia foreach La Sentencia foreach es un comando para enumerar los elementos de una colección. } Console. using System. i++){ Console. } } } El ejemplo anterior implementado con foreach : using System. El siguiente ejemplo muestra el uso de for : using System. La variable de iteración representa el elemento de la colección para cada iteración. i < aArgs. la clase debe soportar un método con la firma GetEnumerator() y la estructura.Length. } } } No es posible asignar un nuevo valor a la variable de iteración. Para que una clase soporte la sentencia foreach .//Test Line Console.Collections.WriteLine(s). . lFactorial).

html")){ Console.html").ToString()). es necesario tener una precaución extra al decidir el tipo de variable de iteración. return. class SentenciaWhile{ public static void Main(){ if(!File.Keys. } StreamReader SR = File. } } Es posible utilizar la sentencia break para salir del ciclo o continue para saltar una iteración.WriteLine("El archivo test.WriteLine("{0} = {1}".GetEnvironmentVariables(). Sentencia do La diferencia entre la sentencia while y do es que do se evalua después de su primer iteración.OpenText("test. using System.class SentenciaForEach{ public static void Main(){ IDictionary VarsAmb = Environment. Console. VarsAmb. por lo que al menos siempre se ejecuta una vez: . Este bloque se repetira mientras la condición evalue una expresión booleana verdadera. por lo que puede ejecutarse 0 o más veces.Exists("test. porque un tipo equivocado no puede ser detectado por el compilador. strIterador.IO. while(null != (strLinea = SR.WriteLine("Existen {0} variables de ambiente declaradas". pero si detectado en tiempo de ejecución y causar una excepción. VarsAmb[strIterador]. } } } Nota. Sentencia while La Sentencia while se utiliza cuando no se conoce previamente cuantas veces ha de repetirse un bloque de código.Count). no será posible evaluar otro tipo de expresión. String strLinea = null. } SR. while(condicional){} Ejemplo: using System.WriteLine(strLinea).Keys){ Console.Close().html no existe"). foreach(String strIterador in VarsAmb.ReadLine())){ Console.

chContinuar = strDatos[0]. } } Sentencias de Salto Las Sentencias de Salto como break. goto y return sirven para ir de una sentencia a otra break La Sentencia break es utilizada para salir de la iteración en curso o sentencia switch y continuar con la ejecución después de esa sentencia. if(chContinuar == 'n') break.WriteLine("La suma de los números es: " + dSuma).ReadLine().Write("Proporcione un número: "). strDatos = Console. } public void Run(){ char chContinuar = 's'. strDatos = Console. lo convierte en un Tipo double y suma su valor mientras la entrada sea 's' o hasta que la entrada sea 'n'. string strDatos. LeerDatos. continue .ReadLine(). Es posible salir de un ciclo do a través de la sentencia break y es posible saltar una iteración utilizando la sentencia continue El siguiente ejemplo le la entrada de la consola toma el primer caracter leido. goto .Write("¿Continuar s/n?"). }while(chContinuar == 's'). continue La Sentencia continue salta todas las sentencias siguientes en la iteración en curso y entonces continua la ejecución en la sentencia de iteración (siguiente iteración). using System. Console.Parse(strDatos). Console.Run(). class Consola{ public static void Main(){ Consola LeerDatos = new Consola(). double dSuma = 0. dSuma += Double. }while(condición). do{ Console.do{ sentencias.

/. Una sentencia goto no puede ser utilizada para saltar adentro de un bloque de sentencias. checked.y. %=. return La Sentencia return regresa a la función invocadora y opcionalmente retorna un valor. --x. sizeof. +=. >> <. |= . f(x). ya que C# no permite utilizar variables que no han sido inicializadas. ^=. ~. >>=. x. (T)x *. -. <=. >=. Categoría Primary Unary Multiplicative Additive Shift Relational Equality Logical AND Logical XOR Logical OR Conditional AND Conditional OR Conditional Assignment typeof Operador (x). -=.La Sentencia goto puede ser utilizada para saltar directamente a una etiqueta. como buena práctica no se recomienda el uso de goto. Su uso podría ser empleado en sentencias switch o para transferir el control fuera de un loop anidado. así como también no pueden realizarse operaciones con variables de clase que no han sido inicializadas. Precedencia de Operadores Cuando una expresión contiene múltiples operadores. % +. ya que el compilador no puede rastrear la asignación definitiva en todas las situcaciones. Asignación Definitiva Las reglas de Asignación definitiva previenen la observación del valor de una variable no asignada. x++. ++x. <<=. &=. != & ^ | && || ?: =. is ==. a[x]. unchecked +. *=. Nota. typeof. !. /=. x --. >. new. Puede accederse al elemento de un arreglo aún si no ha sido inicializado. <<. la precedencia de operadores controla el orden en el cual los elementos de la expresión son evaluados.

pero en vez de determinar cuando un objeto es un tipo específico o interface. if(ut != null){ sentencias. as también realiza la conversión explicita a ese tipo o interface y si no lo puede convertir el operador regresa null. //conversiones explícitas c = (int) d. int c = b. Utilizando is if(UnObjeto is UnTipo){ UnTipo ut = (UnTipo) UnObjeto. El operador as es muy similar al operador is. Utilizar as es más eficiente que utilizar is. long d = c. porque as sólo necesita checar el tipo del objeto una vez e is checa el tipo cuando el operador es utilizado y lo checa otra vez cuando la conversión se realiza. is El operador is es utilizado para determinar cuando una referencia a un objeto puede ser converitda a un tipo específico o interface.El operador typeof regresa el tipo del objeto. A continuación se presenta la jerarquía de conversión en C## Manejo de Excepciones . b = (short) c. el cual es una instancia de la clase System.Type Una instancia ya existente puede obtener el tipo de objeto con el método de la instancia GetType() . } Utilizando as UnTipo ut = UnObjeto as UnTipo. } Conversiones En C# las conversiones se dividen en conversiones explícitas y conversiones implícitas que son aquellas que podrían siempre ocurrir: //conversiones implícitas sbyte a = 55. a = (sbyte) b. short b = a.

} } El ejemplo encierra el bloque de código que podría lanzar una excepción con try. Es posible cambiar el comportamiento de chequeo de overflow utilizando un switch al compilar.Las excepciones son el método fundamental de manejo de condiciones de error. El caso del código para calcular un factorial. iB. la cual es parte del lenguaje común en tiempo de ejecución (CLR). donde la propiedad catch determina por coincidencia el tipo de excepción a el nombre de la excepción generada.iB. iA. }catch(Exception e){ //Manejo de la excepción Console. class ExceptionDivision0{ public static void Main(){ int iA = 33.WriteLine("{0}/{1} = {2}". int iB = 0. el compilador no prodruce una advertencia..NET detiene la ejecución del código y busca el bloque try en el cual la excepción tuvo lugar."). } Console. por lo que se determina que bloque catch es el que mejor y ejecuta el código que contiene. pero si trata de obtener el factorial de 2000 dara por resultado 0. puede ser que encuentre más de un bloque catch relacionado al bloque try que genero la excepción. iA . .WriteLine("Continua la ejecución del código. e). Ejemplo: using System. Jerarquía de Excepciones Todas las excepciones derivan de la clase Exception . el compilador actuo en modo silencioso porque por default el compilador tiene deshabilitada la opción de chequeo de overflow. try{ //Sentencia que puede lanzar una excepción Console.WriteLine("La operac ión {0}/{1} genero la excepcion : {2}". iA/iB). El compilador de C# puede manejar silenciosamente situaciones que podrían producir un error sin notificarnos explicitamente de ello. por ejemplo una situación como un overflow que es cuando el cálculo de una operación excede el rango válido de resultados posibles para el tipo de dato.. entonces busca si este bloque tiene relacionado un bloque catch . Un bloque catch con una coincidencia especifica hacen más general la excepción: using System. class DivisionCero{ public static void Main(){ int iA = 33. En caso de generarse una excepción el runtime .

la excepción atrapada es envuelta en una excepción que tiene información adicional: using System. esto usualmente es lo menos que se esperaria del manejo de excepciones ya que un objeto debería siempre mantener un estado válido después de generarse una excepción.iB. Se llama Caller Confuse. lo cual provocará dejar al objeto en un estado incorrecto.. Trabajar con Excepciones Existen tres formas básicas de trabajar con excepciones: Caller Beware La primer forma es no atrapar la excepción.WriteLine("Continua la ejecución del código. class ExcDivZeroInf{ public static void Main(){ int iA = 33. y causará daños cuando el caller trate de utilizarla de nuevo.int iB = 0. int iB = 0. Caller Confuse La segunda forma es atrapar la excepción y tratar de hacer acciones que dejen la operación como estaba hasta antes de generarse la excepción y entonces relanzar la excepción. iA . iA . } } En este ejemplo el bloque catch que atrapa la excepción DivideByZeroException es una coincidencia más específica.WriteLine("Se genero la excepcion : DivideByZeroException").WriteLine("{0}/{1} = {2}". pero si además de escribir el catch para DivideByZeroException escribe el catch para Exception . el compilador le notificara que existe una excepción que atrapa todas las excepciones y esto es porque Exception ocupa la cima de la jerarquía de todas las excepciones..").iB. porque después de generase una excepción. } Console.WriteLine("{0}/{1} = {2}". try{ Console. . try{ Console. por lo que es la única que será ejecutada. el caller con frecuencia tiene poca información respecto al entendimiento de los detalles de la excepción o como podría ser solucionada. iA/iB). Caller Inform Las tercer forma Caller Inform agrega información que es devuelta al usuario. iA/iB). }catch(DivideByZeroException){ Console.

Ejemplo: Factorial 5"). } Console.cs /checked+ Una vez que se compilo de con la opción de chequeo de overflow habilitado.. } } Chequeo de Overflow Si requerimos controlar el chequeo de overflow para la aplicación completa. } .WriteLine("Continua la ejecución del código. return.". el compilador de C# debe establecerse como checked.WriteLine("Debe proporcionar un argumento.WriteLine("{0}! * {1}".} //Habilitar chequeo de overflow //Test Line Console. lFactorial). for(lAux = 1.OverflowException Este tipo de situaciones es posible atraparlas y manejarlas a través de las excepciones que se producen. lAux++){ checked{lFactorial *= lAux. } long lFactorial = 1. throw(new DivideByZeroException("Información adicional. e)).")..exe : System. long lCalcular = Int64.Length == 0){ Console. lAux <= lCalcular. class FactorialChecked{ public static void Main(string[] aArgs){ if(aArgs.Parse(aArgs[0]). Por default el compilador tiene deshabilitada la opción de chequeo. long lAux = 1. lAux.}catch(DivideByZeroException e){ Console. Para indicar explicitamente que el compilador cheque el overflow escriba: csc Factorial. al intentar obtener el factorial de 2000 de presenta la ventana Just-In-Time-debbuging notificandonos que ocurrio una excepción en Factorial. Chequeo programático de Overflow Existe otra opción si es que no deseamos activar el Chequeo de Overflow para la aplicación completa y habilitar sólamente partes especificas de código. para ello se utiliza la sentencia checked : using System..WriteLine("Se genero la excepcion : DivideByZeroException")..

Console.WriteLine("{0}! es {1}", lFactorial); } }

lCalcular,

También es posible hacer el caso contrario, es decir, indicar que no se realice el chequeo de overflow para partes especificas de código, para ello se utiliza la sentencia:
unchecked{sentencias;}

Sentencias para el Manejo de Excepciones Es posible atrapar, manejar y limpiar las excepciones que se producen utilizando las sentencias siguientes:
y y y

try - catch try - finally try - catch - finally

try - catch Para evitar que se muestre el mensaje que indica que una excepción ocurrio, es necesario atrapar la excepción y lo mejor de todo es que continue la ejecución del programa, para ello se utiliza try y catch .
try contiene el código que quizá pueda lanzar una excepción y catch maneja la excepción si esta ocurre: try{ //sentencias que pueden lanzar una excepción }catch(nombreExcepción){ //manejo de la excepción }

El siguiente ejemplo maneja la excepción FileNotFoundException que se produce cuando se intenta manipular un archivo que no existe, si esto ocurre se presenta un mensaje que muestra el nombre del archivo que se intento manipular y no se encontro a través de una propiedad pública de la excepción llamada FileName .
using System; using System.IO; class SentenciaWhile{ public static void Main(){ try{ StreamReader SR = File.OpenText("test.html"); String strLinea = null; while(null != (strLinea = SR.ReadLine())){ Console.WriteLine(strLinea); } SR.Close(); }catch(FileNotFoundException e){//En caso de que el archivo no exista

Console.WriteLine("No se encontro el archivo : " + e.FileName); return; } } }

try - finally Es posible limpiar el manejo de errores utilizando try y el constructor finally , sin eliminar el mensaje de error, pero el código contenido en el bloque finally es ejecutado aún después de ocurrir una excepción. El siguiente código maneja una variable booleana que indica si se produjo un error, simplemente poniendola dentro del bloque try, si el código contenido fué ejecutado la variable booleana es false lo cual indica que no ocurrieron excepciones, si el bloque no se ejecuto la variable booleana mantiene su valor inicial lo cual significa que si ocurrieron excepciones y entonces se ejecuta el bloque Finally el cual evalua el valor de la variable booleana y presenta la indicación correspondiente.
using System; using System.IO; class SentenciaTryFinally{ public static void Main(){ bool bExcepcion = true; try{ StreamReader SR = File.OpenText("test.html"); String strLinea = null; while(null != (strLinea = SR.ReadLine())){ Console.WriteLine(strLinea); } SR.Close(); bExcepcion = false; } finally{ if(bExcepcion){ Console.WriteLine(">>> No se encontro el archivo"); }else{ Console.WriteLine(">>> No ocurrieron excepciones"); } } } }

Note que en caso de no existir el archivo se produce una excepción y se presenta el mensaje que indica que ha ocurrido una excepción pero también fué ejecutado el bloque finally , el código que contiene el bloque finally siempre es ejecutado ocurra o no una excepción. Puede emplear la sentencia finally para reestablecer los valores previos a la generación de la excepción.

try - catch - finally Combinar try para controlar el código que puede lanzar excepciones, atrapar la excepción con catch y llevar acabo instrucciones necesarias con finally hacen una mejor solución cuando ocurren las excepciones. Es posible utilizar una sentencia catch por cualquier excepción que pudiera ocurrir, es decir, tener más de un bloque catch , pero es necesario conocer la jerarquía de las excepciones porque puede ocurrir que un bloque previo catch sea más general y contenga todas las excepciones lo cual produciria un error.
using System; using System.IO; class SentenciaTryCatchFinally{ public static void Main(){ bool bExcepcion = true; bool bModificacion = false; try{ bModificacion = true; StreamReader SR = File.OpenText("test.htmlX"); String strLinea = nul l; while(null != (strLinea = SR.ReadLine())){ Console.WriteLine(strLinea); } SR.Close(); bExcepcion = false; }catch(FileNotFoundException e){//En caso de que el archivo no exista Console.WriteLine("No se encontro el archivo : " + e.FileName); return; } finally{ if(bExcepcion){ bModificacion = false;//Valor antes de generarse la excepción if(!bModificacion){ Console.WriteLine("Entro en modo modificación, _ pero las modificaciones no se realizaron"); } Console.WriteLine("Causa : No se encontro el archivo"); }else{ Console.WriteLine("No ocurrieron excepciones"); } } } }

Lanzamiento de Excepciones Para atrapar una excepción con la sentencia catch primero debe generarse la excepción, pero es posible que a través de codigo se lanze o invoque una excepción:

en caso de que un argumento sea null cuando no sea permitido Lanzada por un método cuando un argumento no está en el rango permitido Clase base para excepciones que son originadas u ocurren en ambientes fuera del CLR Excepción que contiene información HRESULT COM Excepción que encapsula información del manejo de excepciones destructurada Win32 InvalidOperationException ArgumentException ArgumentNullException ArgumentOutOfRangeException InteropException ComException SEHException Relanzamiento de Excepciones El siguiente código muestra como es posible atrapar una excepción. .throw new NombreExcepcion(excepcion).Length == 0){ Console.WriteLine("Debe proporcionar un argumento. Ejemplo: Factorial 5"). manejarla y se volverla a invocar: using System. al crear una clase podrian crearse también excepciones propias de esta clase. return. class FactorialCheckedReThrow{ public static void Main(string[] aArgs){ if(aArgs. A continuación se presenta una tabla que contiene las excepciones estándar que provee el runtime: Tipo Exception SystemException IndexOutRangeException NullreferenceException Descripción Clase base para todas los objetos exception Clase base para todos los errores generados en tiempo de ejecución Lanzada en tiempo de ejecución cuando el índice de un arreglo está fuera de rango Disparada en tiempo de ejecución cuando un objeto null es referenciado Lanzada por ciertos métodos cuando invocan a métodos que son inválidos para el estado de los objetos actuales Clase base de todos los argumentos de las excepciones Lanzada por un método. El poder lanzar o invocar una excepción es util cuando no se ha contemplado cierto escenario o para nuevos escenarios.

} public static void Main(){ try{ AplicMisExcepciones. using System. } } }catch(OverflowException){ Console. throw. lCalcular).Probar(). esto es conveniente cuando se utiliza la clase y manejar posibles escenarios de error con las clases de excepciones creadas. lAux <= lCalcular. //Test Line Console. }catch(Exception e){ Console. } } Creación de Clases Exception Es recomendable utilizar las clases predefinidas para excepciones. lFactorial). long lCalcular = Int64. } } } Se deben tomar ciertas consideraciones al crear excepciones: y y Al lanzar una excepción se debe proporcionar un texto significativo Lanzar excepciones solo cuando se presente una condición realmente excepcional . lAux.WriteLine("{0}! * {1}". para ciertos escenarios es posible crear clases de excepciones apropiadas. lFactorial). public class MiExcepcion:Exception{ public MiExcepcion(string str):base(str){} } public class AplicMisExcepciones{ public static void Probar(){ throw new MiExcepcion("ocurrio un error").Parse(aArgs[0]). long lAux = 1. por ejemplo cuando creamos una clase. lAux++){ lFactorial *= lAux. } Console.} long lFactorial = 1. try{ checked{ //Habilitar chequeo de overflow for(lAux = 1.WriteLine(e). lCalcular.WriteLine("{0}! es {1}".WriteLine("El fac torial {0}! causo una excepción". también podemos crear excepciones para esta clase.

como es el caso cuando se trabaja en un sólo archivo la clase y la aplicación que hace uso de la clase: csc /t:library /out:ClsPersona. } } Compilación de Componentes Al compilar un componente se crea una biblioteca y no se crea una aplicación.y y y y y y y Lanzar un ArgumentException si el método o propiedad envio mal los parámetros Lanzar un InvalidOperationException cuando la operación invocada no es apropiada para el estado actual de los objetos Lanzar la excepción más apropiada Usar excepciones encadenadas No utilizar excepciones para errores esperados o normales No usar excepciones para control o flujo normal No lanzar NullReferenceException o IndexOutOfRangeException en métodos Componentes Así como es posible escribir clases y hacer uso de estas en un mismo archivo. Métodos). using System.cs Si utiliza nombres de espacio: csc /r:System.dll NombreComponente.} set{iSueldo = value. public void AsignarNombre(string sValor){ sNombre = sValor. también es posible escribir en un archivo (ejecutable) unicamente la clase lo cual es conocido como componente y en otro archivo (también ejecutable) el uso de la clase lo cual es conocido como cliente. Propiedades.} } public string sNombre. } public string ObtenerNombre(){ return sNombre. Creación de Componentes Para crear un componente unicamente es necesario escribir la Clase con todos sus miembros (Constructores.cs .dll /t:library /out:NombreComponente.dll ClsPersona. public int Sueldo{ get{return iSueldo.nombreBiblioteca. almacenarla en un archivo y compilar el componente. public class ClsPersona{ private int iSueldo.

dll NombreCliente. class AplicClsPersona{ public static void Main(){ ClsPersona Empleado = new ClsPersona().WriteLine("Edad : " + Empleado.ObtenerNombre()). aunque es buena práctica especificarlo ya que algunas aplicaciones no sólo tienen un archivo fuente. Empleado.dll Recuerde que el switch /out no es obligatorio ya que se utiliza para especificar un nombre distinto al nombre del archivo fuente. } } Compilación de Clientes Es necesario indicarle al compilador una referencia a la nueva biblioteca de componentes DLL: csc /r:NombreComponente. . Console.Sueldo = 33.WriteLine("Nombre : " + Empleado. entonces el compilador podría llamar a la biblioteca con el primer nombre de archivo fuente en la lista.cs Nota para hacer uso de una clase es necesario que tenga el modificador de acceso public.Donde el switch /t:library indica al compilador de C# crear una biblioteca y no buscar el método estático Main.NET son utilizados para organizar las clases y otros tipos en una estructura jerarquica. Creación de una Aplicación Cliente Para hacer uso de los componentes creados es posible crear aplicaciones cliente donde se creen instancias de las clases creadas: using System. Los namespace en C# se utilizan para organizar programas y la jerarquía natural de la organización facilita presentar los elementos de un programa a otros programas.AsignarNombre("Gerardo Ángeles Nava"). Console. Namespaces Los nombres de espacio namespace en el runtime .Sueldo). Empleado. Los namespace son utiles para la organización interna de aplicaciones. El propósito del uso de namespace hacen las clases fáciles de usar y prevenir colisiones con las clases escritas por otros programadores. Si su clase requirio de nombres de espacio (namespace) es necesario hacer referencia a estas bibliotecas mediante el switch /r:NombreBiblioteca. Una vez que ha compilado su componente puede escribir una Aplicación Cliente.

WriteLine("Alias de una clase"). enumeraciones. para ello sólo es necesario utilizar la palabra reservada namespace seguida de un nombre que lo identifique y encerrar entre llaves el código que deseamos pertenezca a este.NombreNamespaceB{ class NombreClase{ public static void Function(){} } } Las colisiones entre tipos o nombres de espacio que tienen el mismo nombre se pueden resolver utilizando una variante de la cláusula using que permite definir un alias para la clase: using Alias = System. class NombreClase{ public static void Main(){ Alias. delegados e interfaces. namespace NombreEspacio{ public class NombreCla se{ //propiedades //métodos } } Ejemplo: .Console. por ejemplo para poder escribir a la consola se utiliza el namespace System . using NombreOtrosEspacios. estructuras. } } Envolver Clases en Namespace Es posible envolver (wrapping) las clases en un namespace.Un namespace contiene tipos que pueden ser utilizados en la construcción de programas: clases. No es obligatorio jerarquizar los namespace pero es una buena práctica organizar los namespace creados de manera jerarquica para dar claridad a la aplicación. Los nombres de espacio son definidos utilizando la sentencia: namespace Para múltiples niveles de organización los namespaces pueden ser anidados: namespace NombreNamespaceA{ namespace NombreNamespaceB{ class NombreClase{ public static void Function(){} } } } El código anterior puede ser simplificado de la siguiente manera: namespace NombreNamespaceA.

} public string ObtenerNombre(){ return sNombre.Sueldo = 33. Empleado.using System.WriteLine("Nombre : " + Empleado. aunque para evitar conflictos es preferible utilizar la directiva: Ejemplo: using System. class iAplicClsPersona{ public static void Main(){ iPersona Empleado = new iPersona(). using informatique. Console.dll iPersona.ObtenerNombre()).WriteLine("Edad : " + Empleado.mx.dll iAplicPersona.cs Utilizar Namespace en Aplicaciones Cliente Al desarrollar componentes utilizando namespace la aplicación cliente debe importarlo: using NombreEspacio.} set{iSueldo = value.cs Especificar de manera absoluta el namespace: . } } Compilar: csc /r:iPersona.Sueldo). Console.com. public void AsignarNombre(string sValor){ sNombre = sValor.mx{ public class iPersona{ private int iSueldo.com. Empleado.AsignarNombre("Gerardo Ángeles Nava"). } } } Compilar: csc /t:library /out:iPersona. public int Sueldo{ get{return iSueldo.} } public string sNombre. Otra posibilidad es hacer una referencia absoluta a los elementos del namespace. namespace informatique.

iAsiento = Asiento. Console.iPersona(). iMotor = Motor.AsignarNombre("Gerardo Ángeles Nava"). iVentana = Ventana.com. private int iMotor. Empleado. class iAplicClsPersonaAbs{ public static void Main(){ informatique. } public int Ruedas{ .mx : using System. Empleado. private int iVentana. anfibio.mx. pero es posible agregar y envolver más clases o componentes al mismo namespace. _ int Helice.cs archivoFuente2.com.iPersona Empleado = new informatique. después de la compilación son parte del mismo namespace: csc /t:library /out:NombreComponente.dll iAplicPersonaAbs.Sueldo = 33. int Puerta.//Aereo. iHelice = Helice.ObtenerNombre()). Console.cs Agregar Múltiples Clases a Un Namespace En el punto anterior envolvimos una clase a un namespace. espacial //Constructor public iVehiculo(int Rueda.com.cs Agregando otra clase al namespace informatique.dll archivoFuente1. sin importar que esten contenidos en diferentes archivos.com. int Motor.mx. iPuerta = Puerta. string Tipo){ iRueda = Rueda.mx{ class iVehiculo{ private int iRueda. int Asiento. } } Compilar: csc /r:iPersonaAbs. private int iPuerta.WriteLine("Edad : " + Empleado. private string sTipo. int Ventana.Sueldo).WriteLine( "Nombre : " + Empleado. namespace informatique.using System. sTipo = Tipo. private int iHelice. terrestre. private int iAsiento.

Sueldo).WriteLine(" Nombre : " + Empleado.cs Aplicación Cliente: using System."Aereo").get{return iRueda.} } } } Compilar: csc /t:library /out:informatique.WriteLine("Edad : " + Empleado.} } public int Motores{ get{return iMotor. using informatique.} set{iPuerta = value.100.Sueldo = 33.} set{iMotor = value.} set{iHelice = value.} set{iAsiento = value. Console.com.Ruedas).} } public int Puertas{ get{return iPuerta.AsignarNombre("Gerardo Ángeles Nava").0.mx.ObtenerNombre()).} set{iVentana = value.} set{sTipo = value. Console.200.1. //Clase que está contenida en otro archivo iVehiculo MiAvion = new iVehiculo(2.WriteLine("Ruedas : " + MiAvion.} set{iRueda = value.3.com.mx.} } public int Asientos{ get{return iAsiento.dll iPersona.} } public int Helices{ get{return iHelice.} } public string Tipo{ get{return sTipo. Empleado.cs iVehiculo. Empleado. class iAplic{ public static void Main(){ iPersona Empleado = new iPersona(). Console.} } public int Ventanas{ get{return iVentana. .

: " + Console. Console.WriteLine("Ventanas : " + MiAvion.dll Compilación Condicional La Compilación Condicional permite excluir o incluir código.WriteLine("Asientos : " + MiAvion. el nombre del archivo de ensamble debe ser pasado al compilador. Console.cs Recuerde que sus clases deben tener el modificador de acceso public.Net. de lo contrario el compilador notificara un error (error CS0122: is inaccessible due to its protection level). Console. Console. El compilador de C# no soporta macros.WriteLine("Puertas MiAvion.Net residen en el ensamble System.mx. Namespace y Ensambles Un objeto puede ser utilizado desde un archivo fuente C# sólo si ese objeto puede ser localizado por el compilador C#.Console. en C# existen dos formas de hacer esto: 1.WriteLine("Motores MiAvion.Asientos). por default el compilador sólo abre el ensamble conocido como mscorlib. Atributo conditional Uso del Preprocesador C# el compilador emula el preprocesador.Ventanas).WriteLine("Helices MiAvion. Para referenciar objetos localizados en otros ensambles. } } : " + : " + : " + Compilar: csc /r:informatique. por ejemplo los tipos de namespace en el System.Motores). por lo que tendrá que agregar el modificador de acceso y volver a compilar.Helices).com. Uso del Preprocesador 2.Tipo). esto es posible utilizando un switch al compilar: /r:nombreEnsamble Es así como se crea un correlación entre el namespace de un objeto y el nombre del ensamble en el cual reside. el cual contiene las funciones principales para el CLR. ya que no hay un preprocesador por separado.dll iAplic.Write Line("Tipo MiAvion.Puertas).dll . en cambio soporta las siguientes directivas: .

RELEASE. Otra forma utilizada para definir símbolos es usar el compilador y es de ámbito global para todos los archivos: csc /define:DEBUG nombreArchivo. al igual que el símbolo RELEASE. . #else sentencia. Pero es posible definir o no los símbolos al compilar la aplicación: . es necesario separar cada símbolo con una coma (.cs Si el código fuente incluye directivas de definición de símbolos. basado sobre si son o no son definidos los símbolos. El siguiente código no define símbolos en el archivo fuente: . Una forma para definir un símbolo es utilizando la directiva #define en un archivo fuente C#. #if NOMBRE_SIMBOLO sentencia. define un símbolo DEBUG y su ámbito es el archivo donde es definido.cs Si se requiere definir múltiples símbolos utilizando el compilador.) csc /define:DEBUG.y y y Definición de símbolos Exclusión de código basado en símbolos Lanzamiento de errores y advertencias Definición de símbolos La Definición de símbolos es utilizada para excluir o incluir código dependiendo si son o no son definidos ciertos símbolos. sentencia.DEMOVERSION nombreArchivo. está definición deberá realizarse antes de cualquier otra sentencia: #define DEBUG #define RELEASE En este caso #define DEBUG . es posible deshabilitarlas utilizando la directiva #undef cuyo ámbito también corresponde al archivo donde es definida: #undef DEBUG Exclusión de código basado en símbolos El principal propósito de los símbolos es la inclusión o exclusión condicional del código. #endif .

#else y #endif las cuales actuan como su contraparte. es posible utilizar &&. class NombreClase{ public static void Main(){ #if SIMBOLO_A . #endif } } Lanzamiento de errores y advertencias Existe otro uso de las directivas del preprocesador para lanzar errores del compilador o advertencias dependiendo de ciertos símbolos. #if SIMBOLO_WARNING #error Presentar el mensaje de advertencia correspondiente #endif Atributo conditional Un atributo conditional evalua la invocación de una función cuando sierto símbolo es definido y evalua a nada cuando una versión liberada es construida. . la sentencia condicional if C#. para ello se utilizan las directivas: y y #warning #error Por ejemplo #if SIMBOLO_ERROR #error Presentar el mensaje de er ror correspondiente #endif . cualquier otro tipo de regreso no es permitido. #else . || y !: //#define SIMBOLO_A #define SIMBOLO_B #define SIMBOLO_C #if SIMBOLO_A #undef SIMBOLO_C #endif using System. Un atributo conditional debe tener un tipo void de regreso. . #elif SIMBOLO_B && SIMBOLO_C .cs Las directivas del preprocesador emulado utilizadas para evaluar el símbolo son: #if.csc /define:NOMBRE_SIMBOLO NombreAplicacion.

La documentación es una parte extremadamente importante del software y en especial de los componentes por ser utilizados por otros desarrolladores. ///.</summary> En caso de requerir más una línea para el comentario de documentación utilice el tag: ///<para> ///. ///</para> En caso de requerir una referencia a otros elementos utilice el tag: ///<see cref="NombreElemento"/> En caso de requerir una referencia a un tópico de interes utilice: ///<seealso cref="System. Para describir un elemento se utiliza el tag <summary></summary> .. el cual se escribe en el código fuente anteponiendo tres diagonales que son indicativo de un comentario de documentación: ///<summary>Descripción. Elementos XML Nota: todo comentario de documentación son tags XML (eXtensible Markup Language).[conditional ("NOMBRE_SIMBOLO")] método A [conditional("NOMBRE_SIMBOLO")] método B . Comentarios de Documentación en XML Es posible construir automáticamente la Documentación utilizando comentarios en el código. La salida que es generada por el compilador es XML puro y puede ser utilizada como entrada para la documentación de un componente.. para un volumen mayor de documentación es: ///<remarks> Es posible incluir listas utilizando los tags : ///<list type="bullet"> /// <item>Constructor /// <see cref="Constructor()"/> .Net"/> Un tag contrario a summary .

csc /doc:Persona.. public int Sueldo{ get{return iSueldo.</value> Una vez que el proceso de documentación para un componente es terminado. /// <code> /// .cc Ejemplo: using System./// <see cref="Constructor(string)"/> /// </item> ///</list> Para describir parámetros se utiliza el tag: ///<paramref name="nombreParametro"/> Es posible encerrar en un tag un ejemplo completo e incluir la descripción y código: ///<example> /// . ///</example> Para describir los parámetros de regreso utilice: ///<returns> /// <para>true: valor obtenido</para> /// <para>false: valor no obtenido</para> ///</returns> Para describir propiedades de clase se utiliza un tag especial: ///<value>Propiedad. es posible crear un archivo XML basado en la documentación descrita en el código fuente y hacerla disponible a quienes utilicen el componente. /// </code> /// .. /// /// Clase Persona /// Autor : Gerardo Ángeles Nava /// Fecha : 10/09/2005 /// Descripción : Clase que define lo que es y puede hacer una persona /// /// class Persona{ ///La propiedad iSueldo se emplea para obtener y asignar el valor del sueldo de una persona private int iSueldo.xml AplicPersona. para ello simplemente se utiliza al compilar el switch /doc: seguido del documento XML.} .

enumeración o delegado F.AsignarNombre("Gerardo Ángeles Nava"). Empleado. Componentes . denota eventos !.NET El compilador de C# por default siempre crea componentes . denota un namespace identifica un tipo.Sueldo = 33. El compilador realizará validación sobre los tags XML en el archivo fuente. Empleado.NET para los ejecutables. Console. Console. Los parámetros para métodos son encerrados entre paréntesis y separados por comas (.WriteLine("Edad : " + Empleado. identifica un método. los cuales por ejemplo tienen los siguiente significados. estos son reemplazados por el símbolo #. Si un elemento tiene períodos en su nombre.ObtenerNombre()). } } class AplicPersona{ public static void Main(){ Persona Empleado = new Persona(). T. el cual puede ser una clase.WriteLine("Nombre : " +Empleado. en caso de existir errores el compilador lo notificará y aún así el documento XML es generado pero tendrá un mensaje de error. se refiere a una propiedad la cual también puede ser un indíce o propiedad índice.). M. permite la . } } Salida: para ver el documento XML generado de clic aquí. Un Componente . y y y y y y y N. incluyendo constructores y operadores.NET es la unidad fundamental reusable y compartida en el CLR.set{iSueldo = value.} } public string sNombre. } public string ObtenerNombre(){ return sNombre.NET también es limitante para asegurar la seguridad. describe un campo o clase P. estructura.Sueldo). ///Utilizado para asignar el valor de la propiedad sNombre public void AsignarNombre(string sValor){ sNombre = sValor. denota un error el cual provee información acerca de una liga que el compilador C# no pudo resolver. interface. El documento XML tendrá algunos identificadores seguidos de dos puntos (:) y la ruta del namespace. E. un componente .

version:1. este registro se hace en un manifiesto y el CLR los números de versión contenidos para cargar la versión apropiada de un componente .0. Se considera una versión incompatible cuando major version.NET utilizando el switch /reference:nombreBiblioteca la información de dependencia registra las herramientas de desarrollo.NET Un componente . el contenido representa algo humano y no para la máquina.1.dll.revision La versión compatible es utilizada por el class loader para decidir cual es la versión del componente .0.distribución de clases y resolución de tipos.NET deberá ser instalado como compartido.NET Compartidos Si se requiere construir software que se comparta con otras aplicaciones. Se podría considerar una versión compatible cuando el build number es diferente a la versión solicitada.NET dependiente en tiempo de ejecución. .dll nombreArchivoFuente. Cualquier componente .minor version. incluyendo la versión de las bibliotecas ligadas. el componente .1. esto puede comprobarse en las propiedades del archivo.build number.NET que cargará.minor version es diferente de la versión solicitada.cs El switch /a. en caso de existir diferentes versiones.0. Componentes . el cual es considerado sólo para propósitos de documentación y su contenido podría ser SuperControl Build 1880 . Se considera una QFE (Quick Fix Engineering) compatible cuando revision es diferente. Una aplicación puede contener múltiples componentes . Para indicar al compilador que agregue un version information al componente se utiliza el switch: csc /a.version crea una biblioteca con el version information 1.NET contiene cuatro partes referentes al número de versión llamado versión compatible: major version.NET que reside en el directorio de la aplicación es considerado privado y no es version-checked Componentes .NET Privados Al ligar una aplicación a un componente . Además del número de versión (versión compatible) se almacena otro número en el componente llamado informational version.0 /t:library /out:nombreArchivoFuente.

iPersona" "Assembly"="iPersona. esta es una característica de iteroperabilidad proporcionada por la plataforma . PublicKeyToken=null" "RuntimeVersion"="v1.iPersona" "Assembly"="iPersona.com.NET para todos los lenguajes de programación que emiten código administrado.iPersona" [HKEY_CLASSES_ROOTCLSID{37504224 -213A-3943-845AE572758E4174}InprocServer32] @="mscoree.4322" . Culture=neutral. para registrar un objeto COM se utiliza la aplicación regsvr32 y para registrar un componente .NET deberán ser capaces de invocar componentes COM y componentes COM deberán hacer uso de los nuevos componentes . Culture=neutral.Interoperabilidad COM COM es una técnica de interoperabilidad.0.com.dll" "ThreadingModel"="Both" "Class"="informatique. por lo que los clientes .0] "Class"="informatique .reg Ahora puede examinar el archivo generado nombreArchivoComponente.4322" [HKEY_CLASSES_ROOTCLSID{37504224 -213A-3943-845AE572758E4174}InprocServer32 . Version=0.0.NET en Componentes COM La interoperabilidad permite a clientes COM utilizar componentes .iPersona" [HKEY_CLASSES_ROOTinformatique.exe .0.com. Version=0. Uso de Componentes . Si requiere examinar las entradas agregadas al Registry escriba en la línea de comandos: regasm nombreComponente.0.reg . para hacer esto posible en COM primero es necesario registrar un objeto antes de poder ser utilizado.com.NET se utiliza regasm.1.iPersonaCLSID] @="{37504224 -213A-3943-845A-E572758E4174}" [HKEY_CLASSES_ROOTCLSID{37504224 -213A-3943-845A-E572758E4174}] @="informatique.NET.0. Nota asegurese de que el directorio en el que se encuentra exista el archivo .NET en el Registry y también crear un archivo Registry.mx.mx.dll o escriba la ruta completa de su ubicación. esta herramienta permite registrar un componente .0.com.dll /regfile:nombreArchivoComponente.mx.0.mx.1.mx.iPersona] @="informatique.NET. PublicKeyToken=null" "RuntimeVersion"="v1.mx.0. Ejemplo: REGEDIT4 [HKEY_CLASSES_ROOTinformatique.com.

NET. Para que sea posible invocar un componente COM desde un objeto .dll Esta herramienta importa el tipo de biblioteca COM. crea y almacena un RCW que puede ser utilizado en el CLR en el archivo nombreBiblioteca.iPersona" [HKEY_CLASSES_ROOTCLS ID{37504224 -213A-3943-845AE572758E4174}Implemented Categories_ {62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}] El motor de ejecución mscoree. Invocación de Servicios .NET y todas las clases ya están registradas y se tiene una biblioteca tipo para ambientes Uso de Componentes COM en Componentes .NET Los Clientes .com. es necesario envolver el código unsafe.NET pueden interoperar con objetos clásicos COM. El Componente .NET tlbexp nombreComponente.tlb Esta biblioteca tipo puede ser utilizada en lenguajes de programación que soporten esta vinculación. La herramienta a utilizar es tlimp (type library import): tlbimp nombreComponente. Para ver los metadatos para el RCW utilice ildasm. esta información es una ayuda para poder escribir el objeto .dll /out:nombreBiblioteca. Una herramienta genera el código wrapper basado en la información obtenida de la biblioteca tipo. El motor de ejecución es responsable de proveer la CCW (COM Callable Wrapper) al objeto.exe . así podrá distinguir el nombre de la clase que fué generada para el objeto COM original.[HKEY_CLASSES_ROOTCLSID{37504224 -213A-3943-845AE572758E4174}ProgId] @="informatique. para que un componente utilise COM debe tener una biblioteca tipo para el CLR esto se traduce a los metadatos que son almacenados con los tipos.dll .NET que utiliza el componente COM. un RCW (Runtime Callable Wrapper) es construido desde la información de la biblioteca tipo. Una vez registrado el componente puede ser utilizado por lenguajes de programación que soporten esta vinculación. también es posible emplear la utileria tlbexp la cual permite generar una biblioteca tipo para el componente .dll /out:nombreBiblioteca. cuando la envoltura o wrapper es invocada.dll es invocado cuando una instancia del objeto (componente registrado) es requerida. más no la biblioteca por si sóla.mx.

Debugging El SDK . CORDBG. cgarset = conjuntoCaracteres ] Unicamente el argumento dll es obligatorio y los demás opcionales. depurador de línea de comando 2. Para crear una versión depurada son necesarios dos switches al compilar: csc /optimize . la cual contiene información de depuración no optimizada y un archivo adicional PDB (program database) para depuración y un estado de información del proyecto es creado. fixed . SDK. al declarar una variable con este modificador previene al recolector de basura de reacomodarlo. y denota un contexto no seguro. depurador UI o El depurador SDK no soporta la depuración de código nativo. aunque si se omite el atributo name. o No es posible la depuración de una máquina remota o Window register y disassembly aunque se implementan no son funcionales Antes de depurar el código de una aplicación es necesario crear una versión depurada./debug+ nombreArchivoFuente.Se se requiere invocar una función provista por el WIN32 o alguna DLL unmanaged.NET incorpora dos herramientas de depuración de errores: 1. PInvoke se encarga de ejecutar la función correcta y también de la colocación de los argumentos para y desde sus contrapartes unmanaged. Código No Seguro Si requiere de escribir código no seguro. se utilizan los Servicios de invocación de plataforma (PInvoke). name = puntoEntrada. cuando requiera realizar acciones no seguras se debe envolver el código correspondiente con este modificador. el cual puede ser aplicado a constructores. métodos y propiedades. sólo es posible depurar código administrado.exe y . Simplemente utilice el atributo sysimport al definir un método externo: [sysimport( dll = nombreDLL.cs Estos comandos utilizados al compilar crea dos archivos: nombreArchivoFuente. deberá utilizar dos palabras reservadas: y unsafe . el nombre de la función de implementación externa debe coincidir con el nombre del método estático interno.

así como también es posible observar las variables.NET plantea dos posibles soluciones para la seguridad: 1. Seguridad Hoy en día el código viene de distintas fuentes. . interrumpe la ejecución cuando una ubicación específica en el archivo fuente se alcanza Data. cuando una excepción no es controlada apropiadamente por el código se muestra la ventana de depuración llamada JIT just in time. interrumpe la ejecución cuando una dirección de memoria específica se alcanza Una vez que se interrumpe la ejecución. es posible continuarla utilizando los comandos: y y y y Step Over Step Into Step Out Run to Cursor Es posible modificar valores de variables simplemente dando doble clic en la columna valor de aquella variable que se desea modificar. también puede ser instalado via una página web o correo electrónico. Las excepciones son un punto excelente de comienzo para una sesión de depuración.pdb Para configurar la sesión de depuración es necesario seleccionar la aplicación que se desea depurar y comenzar el depurador SDK ejecutando dbgurt. interrumpe la ejecución cuando una variable cambia a un valor especifico Function. interrumpe la ejecución en una ubicación específica dentro de una función específica Address. no solo el que es instalado via un setup por el servidor. Seguridad de acceso al código 2. Es posible establecer diferentes tipos de breakpoint: y y y y File.exe .nombreArchivoFuente. para ello es necesario dar clic en la columna nombre y escribir el nombre de las variables que se desean observar. Seguridad basada en roles Seguridad de acceso al código . mismos que son pasados a la aplicación cuando la sesión de depuración inicia. el cual esta almacenado en el directorio ProgramFilesNGWSSDKGuiDebug Una vez que la aplicación depuradora comienza se selecciona el programa que se desea depurar en donde será también posible especificar argumentos en la línea de comandos.

permisos que no son obligatorios para la ejecución correcta del código. Existen dos puntos importantes de la seguridad de acceso al código. este otorgamiento esta basado en el requerimiento del código. el beneficio de activar el requerimiento de permisos es conocer cuando se tiene el permiso apropiado para realizar acciones y cuando no. Es posible prevenir al código de el otorgamiento de permisos adicionales que no son necesarios. 1. para ello el código administrado debe ser verificado como tipo seguro. El código C# es de tipo no seguro. . El código puede requerir que quien invoca (caller) debe tener permisos especificos La ejecución de código está restringido en tiempo de ejecución. el runtime forza la restricción de seguridad del código administrado. permiso que el código necesita para ejecutarse correctamente. La categoria de los permisos es: y y Required. es decir. La seguridad de acceso al código otorga permisos cuando un componente es cargado. pero que podría ser bueno tenerlos. para determinar cuando el código es seguro. realizando chequeos para verificar que los permisos otorgados a quien invoca (caller) coincidan con el permiso requerido para la operación. verificar los permisos indispensables. Optional. evadiendo hoyos de seguridad que son creados cuando código menos confiable invoca código altamente confiable. definiendo operaciones permitidas por las políticas de seguridad. donde el requerimiento mínimo para beneficiarse de la seguridad de acceso al código es para generar un código de tipo seguro. Funciones de la seguridad de acceso al código: y y y y y y El administrador puede definir las políticas de seguridad asignando ciertos permisos para definir grupos de código. Los permisos mínimos garantizan que el código se ejecute con los recursos justos cuando el código requiere de muchos permisos sin que falle. dependiendo su identidad y de donde viene. El código es confiable en distintos grados. pero el IL y los metadatos son inspeccionados antes de dar el visto bueno del tipo de seguridad del código. Cada acceso a tipos se realiza sólo en un sentido permitido. Los permisos son definidos para representar ciertos derechos para acceder a distintos recursos del sistema. Es importante que el runtime sea capaz de checar los permisos de quien invoca de manera confiable. El código puede requerir los permisos necesarios de ejecución y los permisos que podrían ser utilizados. 2. Permisos que son requeridos por el código.La Seguridad de acceso al código controla el acceso protegiendo los recursos y operaciones. Verificar el tipo de seguridad del código administrado.

etc. permiso que se necesita para que el código nunca se otorgue. El tipo de acceso escritura incluye permisos para crear y eliminar variables de ambiente. aunque la política de seguridad lo permita. invocación de código no administrado.Emit RegistryPermission . serialización. creación y escritura en el registry SecurityPermission . el acceso lectura incluye acceder a la información del archivo. permisos derivados basados en URL de donde el código tiene origen Seguridad basada en roles . ZoneIdentityPermission . controla el acceso a archivos basado en el sistema de archivos de diálogo. tiempo de expiración y almacenamiento de datos. este acceso permite utilización. UIPermission . IsolatedStoragePermission . FileDialogPermission . FileIOPermission .NET provee resistencia de software publisher StrongNameIdentityPermission . el tipo escritura incluye eliminar y sobreescribir. clase que define permisos de acceso a variables de ambiente. es posible especificar tres tipos de acceso a archivos de entrada y salida: lectura. define el acceso a varios aspectos de la interfaz de usuario. permisos derivados basados en el sitio web de donde el código tiene origen URLIdentityPermission . El usuario debe autorizar el acceso al archivo via el cuadro de diálogo. y y y y y y y Permisos Identidad Los Permisos Identidad son: y y y y y PubilsherIdentityPermission . Permisos Estándar Los Permisos Estándar son: y EnvironmentPermission . define la zona de donde el código tiene origen. acceso a eventos y uso del portapapeles. se utiliza para restringir vulnerabilidades potenciales. la firma de componentes . incluyendo el uso de windows.y Refused. un URL puede pertenecer a sólo una zona SiteIdentityPermission . el acceso adición no permite leer otros bits. donde son posibles dos tipos de acceso. colección de permisos simples que son utilizados por el sistema de seguridad. Control de lectura. ReflectionPermission . controla la capacidad de leer el tipo de información de tipos miembro no públicos y controla el uso de Reflection. escritura y adición. de sólo lectura y escritura al valor de una variable de ambiente. tamaño de almacenamiento. sobreescritura de chequeos de seguridad. define el nombre del componente criptograficamente. ya que el nombre compromete la identidad. controla el acceso a almacenamientos aislados. es posible controlar la ejecución de código.

"123"). representa usuarios no autentificados. Función ToString() Analice el siguiente ejemplo: using System. this. Generic principals. pero es posible acceder directamente a la información de identidad principal y realizar chequeos de role e identidad en el código cuando sea necesario. string pwd. relación de usuarios windows y sus roles. La clase Principalpermission provee consistencia con la seguridad de acceso. Pueden extender la noción básica de la identidad y los roles del principal.pwd = pwd.WriteLine("Empleado : " + empleado). el acceso a recursos de otro usuario es permitido. La restricción es que la aplicación debe proveer un módulo de autentificación de los tipos que el principal puede implementar.La Seguridad basada en roles representa a un usuario o agente que actua en representación de un usuario dado. Custom principals. Las aplicaciones . Console. Un role es un nombre para un conjunto de usuarios quienes comparten los mismos privilegios.usr = login. permitiendo al runtime realizar la autorización en un sentido similar al chequeo de la seguridad de acceso al código. 3. también puede ser un agente. string pwd){ this. class Empleado{ string usr. definido por una aplicación. public Empleado(string login. Existen tres tipos de principal: 1. } } Salida: Empleado : Empleado .NET hacen decisiones basadas en la identidad principal o su role como miembro. } } class App{ public static void Main(){ Empleado empleado = new Empleado("gangeles". Un principal no necesariamente es un usuario. Un principal puede ser un miembro de múltiples roles y de esta manera se puede utilizar un role para determinar si ciertas acciones requeridas quizá sean realizadas por un principal. 2. Windows principals.

} public override string ToString(){ return("Usuario : " + usr + ".} return true. } } Salida: Usuario : gangeles. Ejemplo: using System.La salida fue el nombre de la clase Empleado ya que es la representación más cercana que encontro. if(usr != empB. string pwd){ this. En el siguiente ejemplo se redefinen las funciones operator==() y operator!=() . estos operadores deben ser redefinidos en pares."123"). Console. } } class App{ public static void Main(){ Empleado empleado = new Empleado("gangeles". this.usr = login. para permitir la sintaxis del operador. string pwd. string pwd){ this. Password : " + pwd). } public override string ToString(){ return("Usuario : " + usr + ". } public override bool Equals(object o){ Empleado empB = (Empleado)o. class Empleado{ string usr.WriteLine(empleado). string pwd. .pwd = pwd. Es posible especificar algo con mayor sentido para ello se necesita redefinir la función ToString() : using System.usr){return false.pwd){return false.pwd = pwd. no pueden ser redefinidos separadamente.usr = login. class Empleado{ string usr.} if(pwd != e mpB. this. Password : " + pwd). Password : 123 Función Equals() La función Equals() es utilizada para determinar cuando dos objetos tienen el mismo contenido. public Empleado(string login. public Empleado(string login.

Si la clase no tiene un identificador único pero tiene tiene otros campos. } } Salida: El empleado1 es igual al empleado2 : True empleado1 == empleado2 : True Al compilar el ejemplo anterior se presentara un warning indicando que no fue redefinada la función GetHashCode() ya que los valores que regresa son requeridos para ser relacionados al valor de regreso de Equals() . string pwd){ this.Write("empleado1 == empleado2 : ").Write(empleado1 == empleado2).} public static bool operator==(Empleado empA.WriteLine("El empleado1 es igual al empleado2: "+empleado1. class Empleado{ string usr. Empleado empB){ return empA.usr = login. Console.usr){return false. this. } public override bool Equals(object o){ Empleado empB = (Empleado)o. pero si no existe un valor único el código hash debería ser creado fuera de los valores contenidos en la función. Console.Equals(empB). Si no es redefinido el código hash podría ser sólo identico para la misma instancia de un objeto y una búsqueda para un objeto que es igual pero no la misma instancia podría fallar. } public override string ToString(){ return("Usuario : " + usr + ". Console. Es posible utilizar un miembro que es único para el código hash."123"). if(usr != empB. Cuando se invoca la función Equals() y dos objetos son iguales siempre se debe regresar el mismo código hash. } public static bool operator!=(Empleado empA.} . string pwd. public Empleado(string login.Equals(empB). podrías ser utilizados por la función hash: using System. Empleado empB){ return !empA. } } class App{ public static void Main(){ Empleado empleado1 = new Empleado("gangeles".Equals(empleado2)).pwd = pwd. Empleado empleado2 = new Empleado("gangeles". Password : " + pwd)."123").

} } class App{ public static void Main(){ Empleado empleado1 = new Empleado("gangeles".Equals(empB). Empleado empleado2 = new Empleado("gangeles". Console.Equals(empleado2))."123"). donde esta llave es una versión condensada de la instancia.Equals(empB). Interface IHashCodeProvider Si requiere definir diferentes códigos hash para un objeto específico. Empleado empB){ return empA. } } La implementación del código GetHashCode anterior agrega los elementos y los regresa.Write("empleado1 == empleado2 : ")."123"). public Lenguaje(string nombre. Empleado empB){ return !empA. Console. } public static bool operator==(Empleado empA. Console. estas nuevas implementaciones son pasadas al contructor de la Hashtable : using System.GetHashCode().WriteLine("El empleado1 es igual al empleado2: "+empleado1.} return true.if(pwd != empB. this. } . Una tabla hash utiliza esta llave para limitar drasticamente el número de objetos que deben ser buscados para encontrar un objeto específico en una colección de objetos. public class Lenguaje : IComparable{ public string nombre.Write(empleado1 == empleado2). } public override int GetHashCode(){ return usr.nombre = nombre. using System. int id. Una tabla hash trabaja utilizando una función hash. } public static bool operator!=(Empleado empA.GetHashCode() + pwd.id = id.pwd){return false.Collections. la cual produce un entero llave para una instancia específica de una clase. Clase Hashtable La clase Hashtable es muy utilizada para realizar una búsqueda de objetos por una llave. podría hacer esto implementado la Interface IHashCodeProvider para proveer una función alterna hash y además de que se requiere una coincidencia de la implementación de IComparer . int id){ this.

Compare(lenA.id){ return -1. aLenguaje[1] = new Lenguaje("ActionScript". } } class App{ public static void Main(){ Lenguaje[] aLenguaje = new Lenguaje[5]. } } public static IHashCodeProvider HashNombre{ get{ return (IHashCodeProvider) new HashNombreCls(). Lenguaje lenB = (Lenguaje)oB. Hashtable lenguajes = new Hashtable(Lenguaje.5). lenguajes. lenguajes. aLenguaje[3] = new Lenguaje("Java". aLenguaje[2] = new Lenguaje("JavaScript". return String.3).nombre.HashNombre.Add(aLenguaje[0]. return len. aLenguaje[4] = new Lenguaje("PHP".nombre).id){return 1. aLenguaje[0] = new Lenguaje("C".Add(aLenguaje[1]. } } } class HashNombreCls : IHashCodeProvider{ public int GetHashCode(object o){ Lenguaje len = (Lenguaje)o. } } public class OrdenaNombres : IComparer{ public int Compare(object oA.nombre. "bnm"). } public static IComparer OrdenaPorNombre{ get{ return (IComparer) new OrdenaNombres().CompareTo(object o){ Lenguaje lenguajeB = (Lenguaje)o.id > lenguajeB. object oB){ Lenguaje lenA = (Lenguaje)oA.8).2).GetHashCode( ). . if(this. Lenguaje.OrdenaPorNombre).int IComparable. } public override int GetHashCode(){ return id.lenB.1).} if(this. "zxc"). }else{ return 0.id < lenguajeB. } } public override string ToString(){ return nombre + " " + id.

s). Console.saludo. Console.s).saludo.Add(aLenguaje[2]. } } Salida: miClase : Hello World! miClon : Hello World! miClase : Hola Mundo miClon : Hola Mundo El resultado anterior es porque la copia hecha por la función MemberWiseClonre() es una copia.WriteLine("miClase : " + miClase. Lenguaje clone = new Lenguaje("MiLenguaje".lenguajes.saludo.s = s. string s = (string) lenguajes[clone]. Console.saludo. class Saludo{ public string s.saludo. La implementación por default de esta función produce una copia de un objeto.ToString().s). 12345).s = "Hola Mun do".s). "tgh").MemberWiseClone() puede ser utilizada para crear un clon de un objeto. los campos de un objeto son copiados exactamente en lugar de ser duplicados: using System. lenguajes.WriteLine("miClon : " + miClon. public MiClase(string s){this.saludo = new Saludo(s). "wer").WriteLine(clone. lenguajes. "sdf"). } } class MiClase{ public Saludo saludo. el valor de saludo es el mismo en ambos objetos por lo que se se cambia un valor dentro del objeto Saludo afecta ambas instancias de MiClase .Add(aLenguaje[3]. Interface ICloneable .WriteLine("miClase : " + miClase. Console. } } Función IClonable La función object.} } class App{ public static void Main(){ MiClase miClase = new MiClase("Hello World!").WriteLine("miClon : " + miClon. Console.} public MiClase Clon(){return (MiClase)MemberwiseClone(). public Saludo(string s){ this. s). miClon.Clon().Add(aLenguaje[4]. MiClase miClon = miClase.

Para crear una copia deep, donde una nueva instancia de Saludo es creada para para la nueva instancia de MiClase , para ello se hace una implementación de la interface ICloneable :
using System; class Saludo{ public string s; public Saludo(string s){ this.s = s; } } class MiClase : ICloneable{ public Saludo saludo; public MiClase(string s){this.saludo = new Saludo(s);} public object Clone(){return (new MiClase(this.saludo.s));} } class App{ public static void Main(){ MiClase miClase = new MiClase("Hello World!"); MiClase miClon = (MiClase) miClase.Clone(); Console.WriteLine("miClase : " + miClase.saludo.s); Console.WriteLine("miClon : " + miClon.saludo.s); miClon.saludo.s = "Hola Mundo!"; Console.WriteLine("miClase : " + miClase.saludo.s); Console.WriteLine("miClon : " + miClon.saludo.s); } }

Salida:
miClase : Hello World! miClon : Hello World! miClase : Hello World! miClon : Hola Mundo

La invocación a Memberwiseclone() regresa una nueva instancia de Saludo y su contenido puede ser modificado sin afectar el contenido de miClase . Note que en este caso ICloneable requiere implementar la función Clone() . Formato Numérico Los tipos numéricos son formateados a través de la función miembro Format() del tipo de dato, la cual puede ser invocada directamente a través de String.Format() la cual invoca a la función Format() de cada tipo de dato o Console.WriteLine() la cual invoca a String.Format() .

Existen dos tipos de métodos para el formateo específico numérico: Formato Estándar String Formato Estándar String, el cual puede ser utilizado para convertir un tipo numérico a una representación específica string. Este formato consiste del formato específico del caracter seguido de la secuencia de precisión específica de digitos, los formatos soportados son: Formato Descripción C, c D, d E, e E, f G, g N, n X, x Currency Decimal Ejemplo
Console.WriteLine("0:C", 123.8977); Console.WriteLine("0:D7", 12345);

Salida $123,345.90 0012345 3.334590E+004 3.334590E+004 33345.8977 33,345.90 FF

Scientific Console.WriteLine("0:E", (exponential) 33345.8977); Fixed-point General Number
Console.WriteLine("0:F", 33345.8977); Console.WriteLine("0:G", 33345.8977); Console.WriteLine("0:N", 33345.8977); Console.WriteLine("0:X",

Hexadecimal 255);

Formato Personalizado String El Formato Personalizado String, son utilizados para obtener más control, sobre la conversación que está disponible a través del formato estándar de strings. Reemplazo de Cero o Digito
Console.WriteLine("{0:000}",12);

Salida: 012

Reemplazo de Espacio o Digito
Console.WriteLine("{0:#### #}",123);

Salida: 123

Punto Decimal
Console.WriteLine("{0:#####.000}",12345.2);

Salida: 12345.200

Separador de Grupo
Console.WriteLine("{0:##,###}",1123456789);

Salida: 1,123,456,789

Separador de Grupo

Console.WriteLine("{0:000,.##}",12394);

Salida: 123.95

Porcentaje
Console.WriteLine("{0:##.000%}",98144);

Salida: 98.144%

Notación Exponencial
Console.WriteLine("{0:###.000E -00}",3.1415533E+04);

Salida: 314.155E-02

Separador de Sección
Console.WriteLine("{0:###.00;0;(###.00)}", -456.55);

Salida: 457

Escape y Literales
Console.WriteLine("{0:### \#}",255);

Salida: 255#

Parseo Numérico Los números pueden ser parseados utilizando el método Parse() , esto es posible ya que lo provee el tipo de dato.
int iValue = Int32.Parse("123"); double dValue = Double.Parse("1.23");

Input/Output El lenguaje Común en Tiempo de Ejecución .NET provee funciones de entrada/salida en el namespace System.IO . La lectura y escritura la realiza la clase Stream , la cual describe como los bytes pueden ser escritos o leidos. Stream es una clase abstracta que en la práctica las clases derivan de Stream para ser utilizadas. Clases disponibles:
y y y y FileStream , flujo en un archivo de disco MemoryStream , flujo que es almacenado en memoria NetworkStream , flujo en una conexión de red BufferedStream , implementa un buffer en la cima de otro stream.

Lectura y Escritura de Archivos Existen dos formas de obtener flujos (streams) que conectan a un archivo, uno utilizando la clase FileStream , la cual provee un control total sobre el acceso de archivos, incluyendo modo de acceso, compartido y buffering.

Close().Close().A continuación se muestra un ejemplo donde. La información de los metadatos en un objeto contiene información suficiente para que el runtime serialice los campos. El tipo apropiado de sincronización y/o exclusión depende del diseño del programa. Threading (Hilos) El namespace System.Threading contiene clases utilizadas para threading y sincronización. f. } s. } } Salida. pero C# soporta exclusión simple utilizando la sentencia lock. lock utiliza la clase System. class App{ public static void Main(){ FileStream f = new FileStream("nuevo.txt".Threading. iNumberLine <= 10. si no existe se crea: using System.mx .IO. Agradecimientos a Juan Garcia por enviar el tutorial original de informatique.com. pero es necesario indicar al runtime hacerlo correctamente a través de dos atributos [Serializable] el cual es utilizado para marcar un objeto que es posible serializar y [NonSerialized] que es aplicado para un campo o propiedad para indicar que no debería ser serializado. for(int iNumberLine = 1. iNumberLine++){ s.WriteLine("Linea " + iNumberLine). Archivo Nuevo. FileMode.Monitor y provee funcionalidad similar a la invocación de CriticalSection en Win32. cada vez que el programa es ejecutado se sobreescribe el contenido del archivo en caso de que este exista.Create). StreamWriter s = new StreamWriter(f). using System.txt cuyo contenido es: Linea Linea Linea Linea Linea Linea Linea Linea Linea Linea 1 2 3 4 5 6 7 8 9 10 Serialización La Serialización es el proceso utilizado por el runtime para objetos persistentes en algún orden de almacenamiento o para transferirlos de un lugar a otro.

Sign up to vote on this title
UsefulNot useful