Documentos de Académico
Documentos de Profesional
Documentos de Cultura
VS2005 CSharp Es-Es PDF
VS2005 CSharp Es-Es PDF
El contenido de este documento se ha retirado y ya no se actualiza o admite. Algunos vínculos podrían no funcionar. El contenido retirado
representa la versión más reciente actualizada de este contenido.
Conceptos del lenguaje Visual C#
Visual C#
Microsoft Visual C# 2005 es un lenguaje de programación diseñado para crear una amplia gama de aplicaciones que se
ejecutan en .NET Framework. C# es simple, eficaz, con seguridad de tipos y orientado a objetos. Con sus diversas innovaciones,
C# permite desarrollar aplicaciones rápidamente y mantiene la expresividad y elegancia de los lenguajes de tipo C.
Visual Studio admite Visual C# con un editor de código completo, plantillas de proyecto, diseñadores, asistentes para código,
un depurador eficaz y fácil de usar, además de otras herramientas. La biblioteca de clases .NET Framework ofrece acceso a una
amplia gama de servicios de sistema operativo y a otras clases útiles y adecuadamente diseñadas que aceleran el ciclo de
desarrollo de manera significativa.
En esta sección
Introducción a Visual C#
Introduce las funciones de C# 2.0 para los programadores sin experiencia previa con este lenguaje o con Visual Studio, y
ofrece una guía para encontrar ayuda en Visual Studio. Aquí es también donde se buscan las páginas "Cómo".
Utilizar el entorno IDE de Visual C#
Introduce el entorno de desarrollo de Visual C#.
Escribir aplicaciones con Visual C#
Proporciona una orientación de alto nivel que cubre las tareas de programación comunes utilizando C# y .NET Framework,
con vínculos a documentación más detallada.
Migrar a Visual C#
Compara el lenguaje C# con Java y C++, y describe cómo utilizar el Ayudante para la conversión del lenguaje Java para
convertir aplicaciones de Java y Visual J++ a Visual C#.
Guía de programación de C#
Proporciona información y ejemplos prácticos sobre cómo utilizar las construcciones de lenguaje C#.
Referencia de C#
Proporciona información de referencia detallada sobre conceptos de programación de C#, palabras clave, tipos, operadores,
atributos, directivas de preprocesador, modificadores de compiladores y errores y advertencias del compilador.
Especificación del lenguaje C#
Se vincula a la última versión de las características técnicas de C# en formato Microsoft Word.
Ejemplos de Visual C#
Código fuente de ejemplo que muestra cómo programar con Visual C#.
Secciones relacionadas
Lo nuevo en el lenguaje y el compilador de C# 2.0
Describe las nuevas características del lenguaje.
Lo nuevo en Visual C# 2005
Describe las nuevas funciones del editor de código, entorno de desarrollo, asistente para código y depuración.
Actualizar las aplicaciones de Visual C# a Visual Studio 2005
Describe cómo actualizar los proyectos existentes a Microsoft Visual Studio 2005.
Vea también
Otros recursos
Visual Studio
Introducción a Visual C#
Introducción a Visual C#
Los temas siguientes son de gran ayuda para desarrollar aplicaciones mediante el uso de Microsoft Visual C# 2005. También
muestran las numerosas funciones nuevas de Microsoft Visual Studio 2005 y la versión 2.0 del lenguaje C#.
En esta sección
Guía de orientación de la documentación de Visual C#
Proporciona una orientación de alto nivel del contenido de la documentación de Visual C#.
Introducción al lenguaje C# y .NET Framework
Proporciona información general sobre el lenguaje C# y la plataforma .NET.
Lo nuevo en Visual C# 2005
Lo nuevo en Microsoft Visual C# 2005.
Lo nuevo en el lenguaje y el compilador de C# 2.0
Lo nuevo en la versión 2.0 de C#.
Actualizar las aplicaciones de Visual C# a Visual Studio 2005
Actualizar los proyectos existentes a Microsoft Visual Studio 2005.
Crear la primera aplicación de C#
Escribir, compilar y ejecutar una aplicación sencilla en C#.
Utilizar Starter Kits de C#
Utilizar Starter Kits de C#.
Recursos adicionales de ayuda (Visual C#)
Vínculos a otros recursos de ayuda.
Cómo se utiliza C#
Vínculos a temas que muestran la forma de realizar una gran variedad de tareas concretas.
Secciones relacionadas
Utilizar el entorno IDE de Visual C#
Guía para utilizar el entorno de desarrollo de Visual C#.
Migrar a Visual C#
Convertir aplicaciones de Java y Visual J++ a Visual C#.
Escribir aplicaciones con Visual C#
Proporciona información general sobre tareas de programación comunes al utilizar C# y .NET Framework, y vínculos a
documentación más detallada.
Guía de programación de C#
Proporciona información sobre conceptos de programación en C# y describe la forma de realizar diversas tareas en este
lenguaje.
Referencia de C#
Proporciona información de referencia detallada sobre palabras clave, operadores, directivas de preprocesador,
modificadores del compilador, y errores y advertencias del compilador de C#.
Ejemplos de Visual C#
Código fuente de ejemplo que muestra cómo se programa con Visual C#.
Terminología de C#
Glosario de términos de C#.
Vea también
Otros recursos
Visual C#
Visual Studio
Introducción a Visual C#
Lenguaje C#
La sintaxis de C# es muy expresiva, aunque cuenta con menos de 90 palabras clave; también es sencilla y fácil de aprender. La
sintaxis de C# basada en signos de llave podrá ser reconocida inmediatamente por cualquier persona familiarizada con C, C++
o Java. Los desarrolladores que conocen cualquiera de estos lenguajes pueden empezar a trabajar de forma productiva en C#
en un plazo muy breve. La sintaxis de C# simplifica muchas de las complejidades de C++ y, a la vez, ofrece funciones eficaces
tales como tipos de valores que aceptan valores NULL, enumeraciones, delegados, métodos anónimos y acceso directo a
memoria, que no se encuentran en Java. C# también admite métodos y tipos genéricos, que proporcionan mayor rendimiento
y seguridad de tipos, e iteradores, que permiten a los implementadores de clases de colección definir comportamientos de
iteración personalizados que el código de cliente puede utilizar fácilmente.
Como lenguaje orientado a objetos, C# admite los conceptos de encapsulación, herencia y polimorfismo. Todas las variables y
métodos, incluido el método Main que es el punto de entrada de la aplicación, se encapsulan dentro de definiciones de clase.
Una clase puede heredar directamente de una clase primaria, pero puede implementar cualquier número de interfaces. Los
métodos que reemplazan a los métodos virtuales en una clase primaria requieren la palabra clave override como medio para
evitar redefiniciones accidentales. En C#, una estructura es como una clase sencilla; es un tipo asignado en la pila que puede
implementar interfaces pero que no admite la herencia.
Además de estos principios básicos orientados a objetos, C# facilita el desarrollo de componentes de software a través de
varias construcciones de lenguaje innovadoras, entre las que se incluyen:
Firmas de métodos encapsulados denominadas delegados, que permiten notificaciones de eventos con seguridad de
tipos.
Propiedades, que actúan como descriptores de acceso para variables miembro privadas.
Atributos, que proporcionan metadatos declarativos sobre tipos en tiempo de ejecución.
Comentarios en línea de documentación XML.
Si necesita interactuar con otro software de Windows, como objetos COM o archivos DLL nativos de Win32, podrá hacerlo en
C# mediante un proceso denominado "interoperabilidad". La interoperabilidad permite que los programas de C# realicen
prácticamente lo mismo que una aplicación de C++ nativa. C# admite incluso el uso de punteros y el concepto de código "no
seguro" en los casos en que el acceso directo a la memoria es absolutamente crítico.
El proceso de generación de C# es simple en comparación con el de C y C++, y es más flexible que en Java. No hay archivos de
encabezado independientes, ni se requiere que los métodos y los tipos se declaren en un orden determinado. Un archivo de
código fuente de C# puede definir cualquier número de clases, estructuras, interfaces y eventos.
A continuación se enumeran otros recursos de C#:
Para disponer de una introducción general al lenguaje, vea el capítulo 1 de Especificación del lenguaje C#.
Para obtener información detallada sobre aspectos concretos del lenguaje C#, vea Referencia de C#.
Para tener una comparación entre la sintaxis de C# y las de Java y C++, vea
Lenguaje de programación C# para desarrolladores de Java y C# para los desarrolladores de C++.
Arquitectura de la plataforma .NET Framework
Los programas de C# se ejecutan en .NET Framework, un componente que forma parte de Windows y que incluye un sistema
de ejecución virtual denominado Common Language Runtime (CLR) y un conjunto unificado de bibliotecas de clases. CLR es la
implementación comercial de Microsoft de Common Language Infrastructure (CLI), norma internacional que constituye la base
para crear entornos de ejecución y desarrollo en los que los lenguajes y las bibliotecas trabajan juntos sin problemas.
El código fuente escrito en C# se compila en un lenguaje intermedio (IL) conforme con la especificación CLI. El código de
lenguaje intermedio, junto con recursos tales como mapas de bits y cadenas, se almacena en disco en un archivo ejecutable
denominado ensamblado, cuya extensión es .exe o .dll generalmente. Un ensamblado contiene un manifiesto que ofrece
información sobre los tipos, la versión, la referencia cultural y los requisitos de seguridad del ensamblado.
Cuando se ejecuta un programa de C#, el ensamblado se carga en CLR, con lo que se pueden realizar diversas acciones en
función de la información del manifiesto. A continuación, si se cumplen los requisitos de seguridad, CLR realiza una
compilación Just In Time (JIT) para convertir el código de lenguaje intermedio en instrucciones máquina nativas. CLR también
proporciona otros servicios relacionados con la recolección automática de elementos no utilizados, el control de excepciones y
la administración de recursos. El código ejecutado por CLR se denomina algunas veces "código administrado", en
contraposición al "código no administrado" que se compila en lenguaje máquina nativo destinado a un sistema específico. En
el diagrama siguiente se muestran las relaciones en tiempo de compilación y tiempo de ejecución de los archivos de código
fuente de C#, las bibliotecas de clases base, los ensamblados y CLR.
La interoperabilidad del lenguaje es una función clave de .NET Framework. Como el código de lenguaje intermedio generado
por el compilador de C# cumple la especificación de tipos común (CTS), este código generado en C# puede interactuar con el
código generado en las versiones .NET de Visual Basic, Visual C++, Visual J# o cualquiera de los más de 20 lenguajes
conformes con CTS. Un único ensamblado puede contener varios módulos escritos en diferentes lenguajes .NET, y los tipos
admiten referencias entre sí como si estuvieran escritos en el mismo lenguaje.
Además de los servicios en tiempo de ejecución, .NET Framework también incluye una amplia biblioteca de más de 4.000
clases organizada en espacios de nombres que ofrecen una diversidad de funciones útiles para la entrada y salida de archivos,
la manipulación de cadenas, el análisis de archivos XML y los controles de formularios Windows Forms. La aplicación de C#
típica utiliza continuamente la biblioteca de clases de .NET Framework para el tratamiento de las tareas comunes de
"infraestructura".
Para obtener más información sobre la plataforma .NET Framework, consulte Información general acerca de .NET Framework.
Vea también
Otros recursos
Visual C#
Escribir aplicaciones con Visual C#
Introducción a Visual C#
Si no se cambia a las opciones de la línea de comandos, se puede dificultar el diagnóstico del compilador cuando se utilizan
ensamblados de confianza.
Si utiliza /warnaserror (Tratar advertencias como errores) (Opciones del compilador de C#), puede volver a convertirlo en una
advertencia agregando /warnaserror-:1699
a la línea de comandos del compilador. Si es necesario, puede utilizar
/nowarn:1699 para desactivar la advertencia.
Eliminación de la compilación incremental
Se ha eliminado la opción del compilador /incremental. La característica Editar y continuar reemplaza esta
funcionalidad.
Vea también
Otros recursos
Opciones del compilador de C#
Introducción a Visual C#
Biblioteca de clases X X X
Aplicación de consola X X X
Aplicación de dispositivo X X
Proyecto vacío X X X
Plantilla de Excel X
Libro de Excel X
Complemento de Outlook X
Proyecto de prueba X
Servicio de Windows X
Documento de Word X
Plantilla de Word X
Vea también
Conceptos
Aspectos básicos de instalación y configuración
Lo nuevo en Visual Studio 2005
Lo nuevo en Visual C# 2005
Otros recursos
Escribir aplicaciones con Visual C#
Introducción a Visual C#
Cómo se utiliza C#
Este tema "Cómo..." es su puerta de enlace a los temas más importantes basados en tareas sobre programación en C# y
desarrollo de aplicaciones. Las categorías esenciales de lo que puede hacer con C# se muestran en este tema. Los vínculos
proporcionan punteros a páginas importantes de Ayuda sobre procedimientos.
Lenguaje C#
Especificación del lenguaje C#... Subprocesamiento... Genéricos... Fragmentos de código de ejemplo... Ejemplos... etc.
.NET Framework
E/S de archivo… Cadenas… Colecciones… Serialización… Componentes… Ensamblados y dominios de aplicación… etc.
Aplicaciones para Windows
Generar aplicaciones para Windows... Controles... Formularios Windows Forms... Dibujar... etc.
Páginas Web y servicios Web
Páginas Web ASP.NET… Servicios Web XML… etc.
Depuración
Uso del depurador de VS… Clase Trace de .NET Framework… Depuración de transacciones SQL… etc.
Acceso a datos
Conectar a orígenes de datos… SQL Server... Enlace de datos… etc.
Diseñar clases
Diseñador de clases… Trabajar con clases y otros tipos... Crear y modificar miembros de tipos… Instrucciones de diseño de
bibliotecas de clases… etc.
Seguridad
Seguridad de acceso a código… Procedimientos recomendados de directivas de seguridad... Conjuntos de permisos... etc.
Programación de Office
Programación de Office... Controles... Word... Excel... etc.
Dispositivos inteligentes
Lo nuevo en proyectos de Smart Device... Programar dispositivos inteligentes... Depuración de dispositivos inteligentes... etc.
Implementación
ClickOnce… Windows Installer
Recursos adicionales
Los sitios siguientes requieren una conexión a Internet.
Centro para desarrolladores de Visual Studio 2005
Contiene muchos artículos y recursos sobre el desarrollo de aplicaciones con Visual Studio 2005. Este sitio se actualiza
regularmente con nuevo contenido.
Centro para desarrolladores de Visual C#
Contiene muchos artículos y recursos sobre el desarrollo de aplicaciones de C#. Este sitio se actualiza regularmente con
nuevo contenido.
Centro para desarrolladores de Microsoft .NET Framework
Contiene muchos artículos y recursos sobre el desarrollo y depuración de aplicaciones de .NET Framework. Este sitio se
actualiza regularmente con nuevo contenido.
Vea también
Otros recursos
Introducción a Visual C#
Introducción a Visual C#
Dispositivos inteligentes
Esta página proporciona vínculos a la Ayuda de las tareas más habituales de programación de dispositivos inteligentes. Para
ver otras categorías de tareas frecuentes tratadas en la Ayuda, vea Cómo se utiliza C#.
Introducción a los dispositivos inteligentes
Lo nuevo en proyectos de Smart Device
Describe las características nuevas o ampliadas que ofrece Visual Studio 2005.
Capacidades de dispositivos y herramientas de desarrollo necesarias
Proporciona tablas que contienen una instantánea de las variaciones del hardware de dispositivos inteligentes, las
características de hardware y las herramientas de desarrollo.
Herramientas remotas para proyectos de dispositivos
Proporciona una lista de las herramientas remotas disponibles en eMbedded Visual C++ 4.0 y que se distribuyen con Visual
Studio 2005 para ayudarle a desarrollar y depurar aplicaciones de dispositivos.
Cómo: Optimizar la Ayuda para el desarrollo de Smart Device
Muestra la forma de determinar el tipo de Ayuda que se ha instalado, cómo se agrega la Ayuda de Desarrollo móvil e
incrustado, y cómo se filtra la Ayuda.
Cómo: Iniciar el emulador de dispositivos en Visual Studio
Muestra cómo iniciar el emulador de dispositivos con el cuadro de diálogo Conectar con dispositivo o el Administrador del
emulador de dispositivos.
Actualizar proyectos creados con herramientas antiguas
Describe las mejoras realizadas en el entorno de desarrollo de Visual Studio 2005.
Seleccionar un lenguaje de programación
Describe las opciones de lenguajes de programación para desarrollar una aplicación, un control o biblioteca para la
implementación en un dispositivo inteligente.
Tutorial: Crear aplicaciones de Windows Forms para un dispositivo
Muestra la diferencia principal existente entre la programación de escritorio y la programación de dispositivos, esto es, que
se debe establecer como destino para un dispositivo. En este tutorial, el dispositivo es un emulador integrado de Pocket PC
2003.
Programar dispositivos inteligentes con Visual Basic y C#
Programación para dispositivos con .NET Compact Framework
Proporciona información sobre cómo desarrollar aplicaciones de dispositivos inteligentes con el lenguaje Visual Basic o C# y
.NET Compact Framework.
Referencia de .NET Compact Framework para proyectos de dispositivos
Proporciona información sobre .NET Compact Framework como subconjunto de la biblioteca de clases de .NET Framework.
Cómo: Crear aplicaciones para dispositivos utilizando Visual C# o Visual Basic
Describe cómo crear aplicaciones para dispositivos y las diferencias entre este proceso y el de creación de aplicaciones de
escritorio.
Cómo: Compartir código fuente entre plataformas (Dispositivos)
Describe la utilización de constantes del compilador para compartir el mismo código fuente en plataformas diferentes.
Cómo: Cambiar plataformas en proyectos de dispositivos
Describe cómo cambiar de una plataforma a otra en el mismo proyecto.
Cómo: Actualizar proyectos a las versiones más recientes de .NET Compact Framework
Describe cómo actualizar la plataforma de un proyecto existente si se instala una versión posterior de la plataforma.
Administrar fragmentos de código en proyectos de dispositivos
Describe la utilización de miniprogramas que pertenecen exclusivamente a los proyectos de dispositivos.
Cómo: Comprobar la compatibilidad del código en plataformas en proyectos de dispositivos
Describe cómo garantizar que la plataforma de destino admite el código.
Cómo: Controlar eventos de HardwareButton (Dispositivos)
Describe cómo reemplazar las teclas de la aplicación en Pocket PC.
Cómo: Cambiar la orientación y la resolución de formularios (Dispositivos)
Describe cómo cambiar la orientación y resolución si los valores predeterminados faltan o son incorrectos.
Cómo: Cambiar el dispositivo predeterminado (Proyectos administrados)
Describe cómo cambiar el dispositivo de destino durante el desarrollo del proyecto.
Cómo: Optimizar la Ayuda para el desarrollo de Smart Device
Describe cómo utilizar el filtro de Ayuda de Smart Device para mostrar sólo los elementos de .NET Framework admitidos
para el desarrollo de aplicaciones para dispositivos.
Conexiones de dispositivos
Cómo: Conectar al emulador de dispositivos en una sesión de Virtual PC
Describe la técnica para establecer una conexión a falta de TCP/IP.
Cómo: Obtener acceso al sistema de archivos del emulador de Smartphone
Describe cómo obtener acceso al sistema de archivos del emulador de Smartphone, que no tiene su propio visor de archivos.
Cómo: Conectar mediante Bluetooth
Describe cómo conectar utilizando Bluetooth.
Cómo: Conectar mediante IR
Describe cómo conectar utilizando Infrared.
Cómo: Conectar a un dispositivo basado en Windows CE sin ActiveSync
Describe los pasos que hay que seguir para conectar a un dispositivo cuando los servicios de ActiveSync no están
disponibles.
Cómo: Obtener acceso a los archivos del equipo de desarrollo desde el emulador
Describe cómo utilizar una carpeta compartida para tener acceso a los archivos del equipo de desarrollo desde el emulador.
Cómo: Establecer opciones de conexión (dispositivos)
Describe dónde encontrar los cuadros de diálogo comunes para establecer opciones de conexión.
Depuración de dispositivos inteligentes
Diferencias entre depuradores de dispositivos y de escritorio
Describe las diferencias entre los depuradores de dispositivo y de escritorio.
Cómo: Conectar a procesos de dispositivos administrados
Describe cómo conectar con los procesos de dispositivo administrado.
Cómo: Cambiar la configuración del Registro en un dispositivo
Describe cómo utilizar el Editor de Registro remoto para cambiar la configuración del Registro en el dispositivo.
Tutorial: Depurar una solución que incluye código administrado y código nativo
Describe cómo depurar estas soluciones mixtas.
Datos en proyectos de dispositivos administrados
Cómo: Generar código SqlCeResultSet (Dispositivos)
Describe cómo generar conjuntos de resultados en lugar de conjuntos de datos.
Cómo: Cambiar la cadena de conexión en tiempo de diseño (Dispositivos)
Describe cómo cambiar la cadena que Visual Studio utiliza para conectar a una base de datos de SQL Server Mobile en
tiempo de diseño.
Cómo: Cambiar la cadena de conexión en tiempo de ejecución (Dispositivos)
Describe cómo cambiar la cadena que la aplicación utiliza para conectar a una base de datos de SQL Server Mobile en
tiempo de ejecución.
Cómo: Agregar botones de exploración (Dispositivos)
Describe una alternativa a la clase DataNavigator, que no se admite en .NET Compact Framework.
Cómo: Conservar cambios de datos en la base de datos (Dispositivos)
Describe cómo volver a aplicar los cambios en el conjunto de datos a la base de datos.
Cómo: Crear una base de datos (Dispositivos)
Describe cómo utilizar el entorno de Visual Studio para crear una base de datos de SQL Server Mobile, dentro o fuera de un
proyecto.
Cómo: Agregar una base de datos a un proyecto de dispositivos
Describe cómo agregar una base de datos de SQL Server Mobile, disponible en el Explorador de servidores, como origen de
datos para un proyecto de Visual Basic o Visual C#.
Cómo: Agregar una base de datos de SQL Server como origen de datos (Dispositivos)
Describe cómo agregar una base de datos de SQL Server como origen de datos para un proyecto de Visual Basic o Visual C#.
Cómo: Agregar un objeto comercial como origen de datos (Dispositivos)
Describe cómo agregar un objeto comercial como origen de datos para un proyecto de Visual Basic o Visual C#.
Cómo: Agregar un servicio Web como origen de datos (Dispositivos)
Describe cómo agregar un servicio Web como origen de datos para un proyecto de Visual Basic o Visual C#.
Cómo: Administrar tablas en una base de datos (Dispositivos)
Describe cómo agregar y quitar tablas, y cómo editar un esquema de tabla existente.
Cómo: Administrar columnas en una base de datos (Dispositivos)
Describe cómo agregar y quitar columnas, y editar sus propiedades.
Cómo: Administrar índices en una base de datos (Dispositivos)
Describe cómo agregar y quitar índices, y cómo cambiar su propiedad de criterio de ordenación.
Cómo: Administrar contraseñas para bases de datos (Dispositivos)
Describe cómo establecer una contraseña para una nueva base de datos de SQL Server Mobile y cómo cambiar una
contraseña para una base de datos existente.
Cómo: Reducir y reparar una base de datos (Dispositivos)
Describe cómo comprimir y reparar bases de datos de SQL Server Mobile.
Cómo: Crear consultas parametrizadas (Dispositivos)
Describe cómo crear consultas parametrizadas.
Tutorial: Aplicación de consulta parametrizada
Proporciona instrucciones paso a paso para un proyecto completo que incluye la generación de una consulta parametrizada.
Cómo: Crear aplicaciones Principal-Detalle (Dispositivos)
Describe cómo implementar una relación principal-detalle.
Tutorial: Aplicación Principal-Detalle para una base de datos
Proporciona instrucciones paso a paso para un proyecto completo que incluye la creación y ejecución de una aplicación
principal-detalle.
Cómo: Obtener una vista previa de datos en una base de datos (Dispositivos)
Describe varias opciones para ver datos en una base de datos.
Cómo: Generar vistas de resumen y edición para aplicaciones de datos (Dispositivos)
Describe cómo utilizar formularios de datos para ver y modificar filas únicas de datos en una cuadrícula de datos.
Empaquetar e implementar soluciones de dispositivo
Tutorial: Empaquetar una solución Smart Device para su implementación
Proporciona instrucciones paso a paso para empaquetar una aplicación y sus recursos.
Seguridad en los proyectos de dispositivos
Cómo: Importar y aplicar certificados en proyectos de dispositivos
Describe el uso eficaz del cuadro de diálogo Seleccionar certificado para la firma de proyectos de dispositivos.
Cómo: Iniciar Signtool.exe como evento posterior a la generación (Dispositivos)
Describe cómo firmar un proyecto cuando los eventos posteriores a la generación han cambiado los binarios originales.
Cómo: Consultar un dispositivo para conocer su modelo de seguridad
Describe cómo determinar los certificados que ya están instalados en el almacén de certificados de dispositivos.
Cómo: Firmar una aplicación de Visual Basic o Visual C# (Dispositivos)
Muestra los pasos que hay que seguir para firmar una aplicación escrita en comparación con .NET Compact Framework.
Cómo: Firmar un ensamblado de Visual Basic o Visual C# (Dispositivos)
Muestra los pasos que hay que seguir para firmar los ensamblados de proyectos.
Cómo: Firmar un archivo CAB (Dispositivos)
Muestra los pasos que hay que seguir para firmar un proyecto CAB de dispositivos.
Cómo: Poner en servicio un dispositivo en un proyecto de Visual Basic o Visual C#
Muestra los pasos que hay que seguir para agregar certificados digitales al almacén de dispositivos en proyectos
administrados.
Cómo: Poner en servicio un dispositivo con un modelo de seguridad
Describe el uso de RapiConfig.exe para proporcionar un dispositivo con un modelo de seguridad.
Vea también
Conceptos
Cómo se utiliza C#
Implementación (Cómo se procede en C#)
Esta página proporciona vínculos a la ayuda de las tareas de implementación más habituales. Para ver otras categorías de
tareas frecuentes tratadas en la Ayuda, vea Cómo se utiliza C#.
ClickOnce
Cómo: Publicar aplicaciones ClickOnce
Muestra cómo hacer que una aplicación ClickOnce esté disponible para los usuarios publicándola en un servidor Web,
recurso compartido de archivo o discos extraíbles.
Cómo: Especificar una ubicación de publicación
Muestra cómo especificar la ubicación dónde se colocarán los archivos de aplicación y el manifiesto.
Cómo: Especificar una dirección URL de instalación
Muestra cómo utilizar la propiedad Dirección URL de instalación para especificar el servidor Web donde los usuarios irán
a descargar la aplicación.
Cómo: Especificar una dirección URL de soporte
Explica cómo utilizar la propiedad Dirección URL de soporte para identificar una página Web o recurso compartido de
archivo donde los usuarios pueden ir para obtener información sobre la aplicación.
Cómo: Especificar el modo de instalación de ClickOnce
Muestra cómo establecer el Modo de instalación para especificar si la aplicación estará disponible con o sin conexión.
Cómo: Habilitar AutoStart para instalaciones con CD
Muestra cómo habilitar Autoinicio para que la aplicación ClickOnce se inicie automáticamente cuando se inserta el disco.
Cómo: Establecer la versión de publicación de ClickOnce
Muestra cómo establecer la propiedad Versión de publicación, que determina si la aplicación que se está publicando se
tratará o no como una actualización.
Cómo: Incrementar automáticamente la versión de publicación de ClickOnce
Muestra cómo cambiar la propiedad Versión de publicación para producir la aplicación que se va a publicar como una
actualización.
Cómo: Especificar los archivos que se van a publicar mediante ClickOnce
Explica cómo excluir archivos, marcarlos como archivos de datos o requisitos previos y crear grupos para la instalación
condicional.
Cómo: Instalar requisitos previos mediante una aplicación ClickOnce
Muestra cómo especificar un conjunto de componentes de requisitos previos para empaquetar junto con la aplicación.
Cómo: Administrar actualizaciones de aplicaciones ClickOnce
Describe cómo especificar cuándo y cómo se llevarán a cabo las comprobaciones de actualización, si éstas son obligatorias y
dónde debe comprobar dichas actualizaciones la aplicación.
Cómo: Incluir un archivo de datos en una aplicación ClickOnce
Proporciona procedimientos que muestran cómo agregar un archivo de datos de cualquier tipo a la aplicación ClickOnce.
Cómo: Implementar .NET Framework mediante Systems Management Server
Describe las tareas que se deben realizar en el servidor que ejecuta Systems Management Server.
Cómo: Agregar un editor de confianza a un equipo cliente para aplicaciones ClickOnce
Muestra cómo utilizar la herramienta de línea de comandos CertMgr.exe para agregar un certificado de editor al almacén de
los editores de confianza en un equipo cliente.
Cómo: Especificar una ubicación alternativa para las actualizaciones de la implementación
Muestra cómo especificar una ubicación alternativa para las actualizaciones en el manifiesto de implementación para que la
aplicación pueda actualizarse desde el Web tras la instalación inicial.
Cómo: Implementar .NET Framework mediante Active Directory
Proporciona un procedimiento para implementar .NET Framework utilizando Active Directory.
Cómo: Recuperar información de la cadena de consulta en una aplicación ClickOnce
Muestra cómo utilizar una aplicación ClickOnce para obtener información de la cadena de consulta. También muestra la
forma en que la aplicación ClickOnce puede utilizar un fragmento de código para leer estos valores la primera vez que se
inicializa la aplicación.
Cómo: Habilitar la configuración de seguridad para aplicaciones ClickOnce
Muestra cómo deshabilitar temporalmente la configuración de seguridad durante el desarrollo.
Cómo: Establecer una zona de seguridad para una aplicación ClickOnce
Muestra cómo establecer una zona de seguridad para rellenar la tabla Permisos necesarios para la aplicación.
Cómo: Establecer permisos personalizados para una aplicación ClickOnce
Muestra cómo restringir la aplicación a los permisos concretos que necesita para funcionar correctamente.
Cómo: Determinar los permisos de una aplicación ClickOnce
Describe cómo analizar la aplicación para determinar qué permisos se necesitan ejecutando la herramienta Calculadora de
permisos.
Cómo: Depurar una aplicación ClickOnce con permisos restringidos
Muestra cómo depurar la aplicación con los mismos permisos que el usuario final.
Windows Installer
Implementación de Windows Installer
Vínculos a los artículos sobre cómo utilizar la implementación de Windows Installer para crear paquetes del instalador que
se van a distribuir a los usuarios.
Tutorial: Implementar una aplicación basada en Windows
Describe el proceso de creación de un instalador para una aplicación para Windows que inicia el Bloc de notas.
Tutorial: Instalar componentes compartidos mediante módulos de combinación
Cómo utilizar los módulos de combinación para garantizar que los componentes compartidos se empaquetan y entregan
para la implementación coherente.
Tutorial: Crear una acción personalizada
Muestra el proceso de crear una acción personalizada de DLL para dirigir a un usuario a una página Web al final de una
instalación.
Tutorial: Utilizar una acción personalizada para mostrar un mensaje durante la instalación
Explica cómo utilizar una acción personalizada para obtener los datos introducidos por el usuario y transferirlos a un cuadro
de mensaje que aparece durante la instalación.
Tutorial: Utilizar una acción personalizada para precompilar un ensamblado durante la instalación
Describe cómo transferir el nombre de la ruta de acceso de una DLL a la propiedad CustomActionData para precompilar el
ensamblado al código nativo durante la instalación.
Tutorial: Utilizar una acción personalizada para crear una base de datos en la instalación
Muestra el uso de una acción personalizada y la propiedad CustomActionData para crear una base de datos y una tabla de la
base de datos durante la instalación.
Tutorial: Redirigir una aplicación para que apunte a un servicio Web XML diferente en la instalación
Muestra cómo crear una aplicación Web que se pueda redirigir a un servicio Web XML diferente utilizando la propiedad de
comportamiento de dirección URL, una clase de instalador, y un proyecto de programa de instalación Web.
Cómo: Instalar los requisitos previos en la implementación de Windows Installer
Muestra cómo detectar automáticamente la existencia de componentes durante la instalación e instalar un conjunto
predeterminado de requisitos previos, un proceso conocido como programa previo.
Cómo: Crear o agregar proyectos de implementación
Muestra cómo especificar dónde y cómo se implementará una solución durante y después del desarrollo.
Cómo: Crear o agregar un proyecto de instalación
Describe cómo crear archivos de Windows Installer (.msi), que se utilizan con el fin de distribuir la aplicación para su
instalación en otro equipo o servidor Web.
Cómo: Crear o agregar un proyecto de módulo de combinación
Muestra cómo crear un proyecto de módulo de combinación para empaquetar archivos o componentes que se compartirán
entre varias aplicaciones.
Cómo: Crear o agregar un proyecto CAB
Muestra cómo crear un proyecto CAB para crear archivos contenedores (.cab) que se pueden utilizar para descargar
componentes a un explorador Web.
Cómo: Establecer las propiedades del proyecto de implementación
Muestra cómo establecer propiedades dependientes de la configuración mediante el cuadro de diálogo Propiedades de la
implementación.
Cómo: Agregar elementos a un proyecto de implementación
Muestra cómo especificar qué componentes se deben incluir en el instalador y dónde instalarlos en el equipo de destino.
Cómo: Agregar módulos de combinación a un proyecto de implementación
Muestra cómo utilizar los módulos de combinación (archivos .msm) para compartir componentes entre varios proyectos de
implementación.
Cómo: Agregar y quitar iconos
Muestra cómo instalar y asociar iconos con la aplicación en un equipo de destino durante la instalación.
Cómo: Excluir elementos de un proyecto de implementación
Muestra cómo excluir un archivo o archivos de un proyecto de implementación.
Cómo: Establecer una instalación condicional basándose en las versiones del sistema operativo
Muestra cómo establecer la propiedad Condición para agregar lógica condicional a un instalador; por ejemplo, para instalar
distintos archivos o establecer valores de Registro diferentes para diversas versiones de un sistema operativo.
Vea también
Conceptos
Cómo se utiliza C#
Implementar aplicaciones de C#
Entorno de desarrollo de Visual C#
Herramientas de Visual C#
A continuación se detallan las herramientas y ventanas más importantes de Visual C#. Las ventanas de la mayoría de estas
herramientas se pueden abrir desde el menú Ver.
El Editor de código, para escribir código fuente.
El compilador de C#, para convertir el código fuente de C# en un programa ejecutable.
El depurador de Visual Studio, para probar el programa.
El Cuadro de herramientas y el Diseñador, para desarrollar rápidamente interfaces de usuario con el mouse.
El Explorador de soluciones, para ver y administrar archivos de proyecto y configuraciones.
El Diseñador de proyectos, para configurar opciones del compilador, rutas de implementación, recursos, etc.
La Vista de clases, para desplazarse por el código fuente según los tipos, no los archivos.
La Ventana Propiedades, para configurar propiedades y eventos en los controles de la interfaz de usuario.
El Examinador de objetos, para ver los métodos y clases disponibles en las bibliotecas de vínculos dinámicos, incluidos
los ensamblados de .NET Framework y los objetos COM.
Document Explorer, para explorar y buscar la documentación del producto en su equipo local y en Internet.
Cómo expone las herramientas el IDE
Puede interactuar con las herramientas a través de ventanas, menús, páginas de propiedades y asistentes en el IDE. El IDE
básico tiene un aspecto similar al siguiente:
Puede tener acceso rápidamente a las ventanas de herramientas o archivos abiertos presionando CTRL + TAB. Para obtener
más información, vea Desplazamientos y búsquedas (Visual C#).
Ventanas del Editor y del Diseñador de Windows Forms
El Editor de código y el Diseñador de Windows Forms utilizan la ventana principal grande. Para alternar entre la vista de código
y la vista Diseño, puede presionar F7 o hacer clic en Código o Diseñador en el menú Ver. En la vista Diseño, puede arrastrar
controles a la ventana desde el Cuadro de herramientas, que se puede hacer visible haciendo clic en la ficha Cuadro de
herramientas del margen izquierdo. Para obtener más información sobre el Editor de código, vea Editar código (Visual C#).
Para obtener más información sobre el Diseñador de Windows Forms, vea Diseñador de Windows Forms.
La ventana Propiedades de la parte inferior derecha sólo contiene información en vista Diseño. Permite establecer las
propiedades y enlazar los eventos para los controles de la interfaz de usuario, como botones, cuadros de texto, etc. Cuando
esta ventana se establece como Ocultar automáticamente, se contrae en el margen derecho cada vez que se cambia a Vista
Código. Para obtener más información sobre la ventana Propiedades y el Diseñador, vea
Diseñar una interfaz de usuario (Visual C#).
Explorador de soluciones y Diseñador de proyectos
La ventana de la parte superior derecha es el Explorador de soluciones, que muestra todos los archivos del proyecto en una
vista de árbol jerárquica. Cuando se utiliza el menú Proyecto para agregar nuevos archivos al proyecto, se verán reflejados en
el Explorador de soluciones. Además de los archivos, el Explorador de soluciones también muestra la configuración del
proyecto y las referencias a las bibliotecas externas que necesita la aplicación.
Para obtener acceso a las páginas de propiedades del Diseñador de proyectos, haga clic con el botón secundario del mouse
en el nodo Propiedades del Explorador de soluciones y, a continuación, haga clic en Abrir. Utilice estas páginas para
modificar opciones de generación, requisitos de seguridad, detalles de implementación y muchas otras propiedades del
proyecto. Para obtener más información sobre el Explorador de soluciones y el Diseñador de proyectos, vea
Crear un proyecto (Visual C#).
Ventanas Compilador, Depurador y Lista de errores
El compilador de C# no tiene ninguna ventana porque no es una herramienta interactiva, pero puede establecer sus opciones
en el Diseñador de proyectos. Cuando se hace clic en Generar en el menú Generar, el IDE invoca el compilador de C#. Si la
generación se realiza correctamente, el panel de estado muestra un mensaje Generación satisfactoria. Si se producen errores
de generación, aparece la ventana Lista de errores aparece debajo de la ventana del editor/diseñador con una lista de errores.
Haga doble clic en un error para ir a la línea de código fuente que presenta el problema. Presione F1 para consultar la
documentación de Ayuda correspondiente al error resaltado.
El depurador tiene distintas ventanas que muestran valores de variables e información de tipos a medida que se ejecuta la
aplicación. Puede utilizar la ventana Editor de código mientras depura el programa para especificar una línea en la que desee
hacer una pausa durante la ejecución en el depurador y para recorrer el código línea a línea. Para obtener más información,
vea Generar y depurar (Visual C#).
Personalizar el IDE
En Visual C#, todas las ventanas pueden ser acoplables o flotantes, estar ocultas o visibles o cambiarse de ubicación. Para
cambiar el comportamiento de una ventana, haga clic en el icono de flecha abajo o de pin de la barra de título y seleccione
entre las opciones disponibles. Para mover una ventana acoplada a una nueva ubicación, arrastre la barra de título hasta que
aparezcan los iconos de colocación de la ventana. Mantenga presionado el botón primario del mouse y mueva el puntero del
mouse sobre el icono en la nueva ubicación. Coloque el puntero sobre los iconos izquierdo, derecho, superior o inferior para
acoplar la ventana en el lado especificado. Coloque el puntero sobre el icono del medio para transformar la ventana en una
ventana con fichas. Mientras coloca el puntero, aparece un rectángulo azul semitransparente que indica dónde se acoplará la
ventana en la nueva ubicación.
Puede personalizar muchos otros aspectos del IDE haciendo clic en Opciones en el menú Herramientas. Para obtener más
información, vea Opciones (Cuadro de diálogo): Visual Studio.
Vea también
Conceptos
Diseñar una interfaz de usuario (Visual C#)
Crear un proyecto (Visual C#)
Editar código (Visual C#)
Generar y depurar (Visual C#)
Otros recursos
Visual C#
Utilizar el entorno IDE de Visual C#
Entorno de desarrollo integrado de Visual Studio
Visual Web Developer
Elementos de la interfaz de usuario de Visual Web Developer
Entorno de desarrollo de Visual C#
La ilustración siguiente muestra el cuadro de diálogo Nuevo proyecto. Como puede ver, Visual C# está seleccionado de
forma predeterminada en la ventana de la izquierda, y en la derecha, tiene la opción de elegir entre seis o más plantillas de
proyecto. Si expande el nodo Smart Device u Otros tipos de proyectos de la izquierda, aparecerán distintos tipos de
proyectos en el lado derecho.
Los Starter kits son otro tipo de plantilla de proyecto. Si instala un starter kit, verá que aparece en el cuadro de diálogo Nuevo
proyecto. Para obtener más información, vea Starter Kits.
Después de seleccionar una plantilla de proyecto y hacer clic en Aceptar, Visual Studio crea el proyecto y todo está listo para
comenzar la codificación. Los archivos de proyecto, referencias, configuración y recursos son visibles en la ventana
Explorador de soluciones, situada a la derecha.
¿Qué contiene el proyecto?
Propiedades
El nodo Propiedades representa opciones de configuración que se aplican a la totalidad del proyecto y se almacenan en el
archivo .csproj de su carpeta de soluciones. Esta configuración incluye opciones de compilación, seguridad e implementación,
entre muchas otras. Para modificar el proyecto, se utiliza el Diseñador de proyectos, que es un conjunto de Páginas de
propiedades a las que se tiene acceso haciendo clic con el botón secundario del mouse en Propiedades, y seleccionando
Abrir. Para obtener más información, vea Modificar las propiedades de un proyecto (Visual C#).
Referencias
En el contexto de un proyecto, una referencia identifica simplemente un archivo binario que la aplicación necesita para poder
ejecutarse. Normalmente, una referencia identifica un archivo DLL, como uno de los archivos de la biblioteca de clases de .NET
Framework. También puede hacer referencia a un ensamblado .NET (denominado shim) que permite que la aplicación llame a
los métodos de un objeto COM o de un archivo DLL nativo de Win32. Si su programa crea una instancia de una clase definida
en otro ensamblado, debe agregar una referencia al archivo correspondiente en el proyecto antes de compilarlo. Para agregar
una referencia, haga clic en Agregar referencia en el menú Proyecto. Todos los proyectos de C# incluyen de forma
predeterminada una referencia a mscorlib.dll, que contiene las clases básicas de .NET Framework. Puede agregar las
referencias a archivos DLL de .NET Framework adicionales y a otros archivos haciendo clic en el Menú Proyecto y
seleccionando Agregar referencia.
Nota
No confunda el concepto de una referencia de proyecto con el concepto de tipos de referencia en C# u otros lenguajes de pr
ogramación. El primero se refiere a un archivo y a su ubicación en disco. El segundo se refiere a los tipos de C#, que se declar
an con la palabra clave class.
Recursos
Los recursos son datos que se incluyen con la aplicación pero que se pueden almacenar de forma que pueden modificarse con
independencia del resto del código fuente. Por ejemplo, puede almacenar todas las cadenas como recursos en lugar de
codificarlas directamente en el código fuente. De esta forma, podrá traducir las cadenas a distintos idiomas más adelante y
agregarlas a la carpeta de la aplicación que distribuye a los clientes sin necesidad de volver a compilar el ensamblado. Los
cinco tipos de recursos definidos por Visual C# son: cadenas, imágenes, iconos, audio y archivos. Para agregar, quitar o
modificar recursos, utilice el Diseñador de recursos, al que se tiene acceso en la ficha Recursos del Diseñador de
proyectos.
Formularios
Cuando se crea un proyecto de formularios Windows Forms, Visual C# agrega de forma predeterminada un formulario al
proyecto y lo llama Form1. Los dos archivos que representan el formulario se llaman Form1.cs y Form1.designer.cs. El código
se escribe en Form1.cs. El Diseñador de Windows Forms escribe en el archivo designer.cs el código que implementa todas las
acciones que se realizaron al arrastrar y colocar objetos desde el Cuadro de herramientas.
Puede agregar un nuevo formulario haciendo clic en el elemento de menú Proyecto y seleccionando Agregar Windows
Forms. Cada formulario tiene dos archivos asociados. Form1.cs, o como haya decido llamarlo, contiene el código fuente que se
escribe para configurar el formulario y sus controles, como cuadros de lista y cuadros de texto, y responde a eventos tales
como los clics en botones y las pulsaciones de teclas. En los proyectos de formularios Windows Forms simples, la mayoría o
incluso la totalidad de la codificación se hace en este archivo.
El archivo Designer.cs contiene el código fuente que escribe el Diseñador de formularios cuando se arrastran controles y se
colocan en el formulario, cuando se establecen las propiedades en la ventana Propiedades, etc. Normalmente, no debería
modificar manualmente este archivo.
Nota
Naturalmente, si crea un proyecto de aplicación de consola, no contendrá archivos de código fuente para formularios Windo
ws Forms.
Las propiedades del proyecto se agrupan en 10 páginas en el Diseñador de proyectos. Las páginas de propiedades del
Diseñador de proyectos están ubicadas en el mismo panel central que utiliza el Diseñador de Windows Forms y el editor
de código.
Nota
Visual Studio Team System incluye una página de propiedades adicional para análisis de código.
En la ilustración anterior, se muestra la página de propiedades Aplicación. Al hacer clic en las etiquetas en la ficha izquierda
(Generar, Generar eventos, Depurar, etc.) puede tener acceso a la página de propiedades correspondiente. La información
específica del proyecto que se escribe aquí se almacena en un archivo .csproj que no s puede ver en el Explorador de
soluciones y que está ubicado en la carpeta del proyecto de la unidad. Para obtener ayuda para cualquiera de las páginas de
propiedades mientras trabaja en Visual C#, coloque el cursor del mouse en la página y presione F1.
La tabla siguiente ofrece una breve descripción de cada página del Diseñador de proyectos:
Página de prop Descripción
iedades
Aplicación Cambiar el nombre del ensamblado, el tipo de proyecto, la información del ensamblado, incluido el número
de versión, y otras opciones de recursos. Para obtener más información, vea
Página de aplicación, Diseñador de proyectos (C#).
Generar Cambiar la ubicación donde se almacena el ensamblado compilado, las opciones de compilación condicional
, la forma en que se controlan los errores y advertencias, y otros valores de configuración. Para obtener más
información, vea Generar (Página, Diseñador de proyectos) (C#).
Eventos de gener Crear y modificar pasos de generación personalizada. Para obtener más información, vea
ación Eventos de generación (Página, Diseñador de proyectos) (C#, J#).
Depuración Especificar los argumentos de la línea de comandos cuando se ejecuta en el depurador y otros valores de co
nfiguración. Para obtener más información, vea Página Depuración, Diseñador de proyectos.
Recursos Agregar al proyecto cadenas, iconos, imágenes u otros tipos de archivos como recursos. Para obtener más in
formación, vea Página Recursos, Diseñador de proyectos.
Configuración Almacenar valores de configuración tales como las cadenas de conexión para una base de datos o la combin
ación de colores que desea un usuario concreto. Estas configuraciones se pueden recuperar dinámicamente
en tiempo de ejecución. Para obtener más información, vea Página Configuración, Diseñador de proyectos.
Rutas de acceso Especificar la ruta de acceso en la que están ubicados los ensamblados a los que hace referencia el proyecto.
de referencia Para obtener más información, vea Rutas de acceso de referencia (Página, Diseñador de proyectos) (C#, J#).
Firma Especificar las opciones de certificado de ClickOnce y proporcionar un nombre seguro para su ensamblado.
Para obtener más información, vea Página Firma, Diseñador de proyectos y
Información general sobre la implementación de ClickOnce.
Seguridad Especificar la configuración de seguridad que necesita la aplicación para funcionar. Para obtener más inform
ación, vea Página Seguridad, Diseñador de proyectos.
Publicación Especificar las opciones para distribuir su aplicación a un sitio Web, servidor ftp o ubicación de archivo. Para
obtener más información, vea Panel Publicar, Diseñador de proyectos.
Análisis de códig Opciones para las herramientas que analizan el código fuente para detectar problemas potenciales de seguri
o (sólo Visual St dad, comprobar el cumplimiento de las instrucciones de diseño de .NET Framework, etc. Para obtener más in
udio Team Syste formación, vea Análisis de código, Diseñador de proyectos.
m)
Vea también
Conceptos
Introducción al Diseñador de proyectos
Otros recursos
Utilizar el entorno IDE de Visual C#
Entorno de desarrollo integrado de Visual Studio
Entorno de desarrollo de Visual C#
Agregar controles
En el diseñador, se utiliza el mouse para arrastrar controles, como botones y cuadros de texto, hasta una superficie de diseño
que representa el formulario. La siguiente ilustración muestra un cuadro combinado que se ha arrastrado desde la ventana
Cuadro de herramientas a un formulario en el Diseñador de Windows Forms.
A medida que se trabaja visualmente, el diseñador traduce las acciones en código fuente de C# y las escribe en un archivo de
proyecto llamado <nombre>.designer.cs, donde <nombre> es el nombre asignado al formulario. Cuando se ejecuta la
aplicación, el código fuente ajusta la posición y el tamaño de los elementos de la interfaz de usuario para que aparezcan como
en la superficie de diseño. Para obtener más información, vea Diseñador de Windows Forms.
Establecer propiedades
Después de agregar un control al formulario, puede utilizar la ventana Propiedades para establecer sus propiedades, como el
color de fondo y el texto predeterminado. Los valores que especifique en la ventana Propiedades sólo son los valores iniciales
que se asignarán a la propiedad cuando se cree el control en tiempo de ejecución. En muchos casos, se puede tener acceso a
estos valores o modificarlos mediante programación en tiempo de ejecución. Para ello, basta con obtener o establecer la
propiedad en la instancia de la clase del control en la aplicación. La ventana Propiedades resulta útil en tiempo de diseño
porque permite examinar todas las propiedades, eventos y métodos que admite un control. Para obtener más información, vea
Propiedades (Ventana).
Controlar eventos
Los programas con interfaces de usuario gráficas son principalmente controlados por eventos. Esperan hasta que un usuario
haga algo, como escribir texto en un cuadro de texto, hacer clic en un botón o cambiar la selección de una lista. Cuando esto
sucede, el control, que es simplemente una instancia de una clase de .NET Framework, envía un evento a la aplicación. Tiene la
opción de controlar un evento escribiendo un método especial en la aplicación al que se llamará cuando se reciba el evento.
Puede utilizar la ventana Propiedades para especificar los eventos que desea controlar en su código; seleccione un control en
el diseñador y haga clic en el botón Eventos, con el icono de rayo, en la barra de herramientas de la ventana Propiedades
para ver sus eventos. En el diagrama siguiente se muestra el botón de eventos.
Cuando agregue un controlador de eventos a través de la ventana Propiedades, el diseñador escribirá automáticamente el
cuerpo del método vacío, y deberá escribir el código para que el método lleve a cabo la acción deseada. La mayoría de los
controles generan un gran número de eventos, pero en la mayoría de los casos, las aplicaciones sólo necesitan controlar unos
pocos, si no sólo uno. Por ejemplo, puede que necesite controlar el evento Click de un botón, pero no su evento Paint a
menos que desee personalizar su aspecto de forma avanzada.
Pasos siguientes
Para obtener más información sobre las interfaces de usuario de formularios Windows Forms, vea los temas siguientes:
Crear aplicaciones basadas en Windows
Tutorial: Crear un formulario Windows Forms sencillo
Elementos de la interfaz de usuario del Diseñador de Windows Forms
En la biblioteca de clases de .NET Framework, System.Windows.Forms y los espacios de nombres relacionados contienen las
clases utilizadas para el desarrollo con formularios Windows Forms.
Vea también
Otros recursos
Visual C#
Utilizar el entorno IDE de Visual C#
Entorno de desarrollo de Visual C#
Listas de finalización
A medida que se escribe código fuente en el editor, IntelliSense muestra un cuadro de lista que contiene todas las palabras
clave de C# y las clases de .NET Framework. Si encuentra una coincidencia en el cuadro de lista para el nombre que se está
escribiendo, selecciona el elemento. Si el elemento seleccionado es el deseado, se puede presionar la tecla TAB para que
IntelliSense termine de escribir el nombre o la palabra clave. Para obtener más información, vea Listas de finalización en C#.
Información rápida
Cuando el cursor se sitúa sobre un tipo de .NET Framework, IntelliSense muestra información rápida sobre herramientas que
contiene documentación básica sobre el tipo. Para obtener más información, vea Información rápida.
Lista de miembros
Cuando se introduce un tipo de .NET Framework en el Editor de código y después se escribe el operador punto (.), IntelliSense
muestra un cuadro de lista que contiene los miembros del tipo. Cuando se realiza una selección y se presiona TAB, IntelliSense
escribe el nombre del miembro. Para obtener más información, vea Lista de miembros.
Información de parámetros
Cuando se escribe un nombre de método en el Editor de código seguido de un paréntesis de apertura, IntelliSense muestra
información rápida sobre herramientas de parámetros que indica el orden y los tipos de los parámetros del método. Si el
método está sobrecargado, puede el método, se puede desplazarse hacia abajo a través de todas las firmas sobrecargadas.
Para obtener más información, vea Información de parámetros.
Agregar using
En ocasiones, puede intentar crear una instancia de una clase de .NET Framework sin un nombre suficientemente completo. En
este caso, IntelliSense muestra una etiqueta inteligente después del identificador sin resolver. Al hacer clic en la etiqueta
inteligente, IntelliSense muestra una lista de directivas using que permitirán resolver el identificador. Cuando seleccione una
directiva de la lista, IntelliSense la agregará al principio del archivo de código fuente y podrá seguir escribiendo código en la
posición actual. Para obtener más información, vea Agregar using.
Refactorización
A medida que una base de código crece y evoluciona en el transcurso de un proyecto de desarrollo, puede ser deseable hacer
cambios para que sea más legible para los usuarios o más portable. Por ejemplo, puede desear dividir algunos métodos en
métodos de menor tamaño, cambiar los parámetros de un método o cambia el nombre de los identificadores. La función de
refactorización, a la que se tiene acceso mediante un clic con el botón secundario del mouse en el Editor de código, lleva a cabo
estas tareas de forma mucho más cómoda, inteligente y rigurosa que las herramientas tradicionales, como buscar y
reemplazar. Para obtener más información, vea Refactorización.
Fragmentos de código
Los fragmentos de código son unidades pequeñas de código fuente de C# de uso frecuente que se puede escribir con
precisión y rapidez mediante un par de pulsaciones de tecla. Para obtener acceso al menú de fragmentos de código, es preciso
hacer clic con el botón secundario del mouse en el Editor de código. Puede examinar los numerosos fragmentos de código que
se incluyen en Visual C# y crear los suyos propios. Para obtener más información, vea Fragmentos de código (C#).
Subrayado con líneas onduladas
El subrayado con líneas onduladas ofrece información instantánea sobre los errores del código a medida que se escribe. Un
subrayado con líneas onduladas rojas identifica un error de sintaxis, como la falta de un punto y coma o que una llave de cierre
no tiene su correspondiente llave de apertura. Un subrayado con líneas onduladas verdes identifica una advertencia potencial
del compilador, y con líneas azules, identifica un problema de Editar y continuar. La ilustración siguiente muestra un subrayado
con líneas onduladas rojas:
Ayudas de legibilidad
Esquematización
El Editor de código trata automáticamente los espacios de nombres, las clases y los métodos como regiones que se pueden
contraer para facilitar la localización y la lectura de otras partes del archivo de código fuente. También puede crear sus propias
regiones contraíbles delimitando el código con las directivas #region y #endregion.
Colorización
El editor asigna distintos colores a las distintas categorías de identificadores de un archivo de código fuente de C#. Para
obtener más información, vea Color del código.
Vea también
Otros recursos
Utilizar el entorno IDE de Visual C#
Entorno de desarrollo de Visual C#
Exploración CTRL-TAB
En cualquier momento, puede tener varias ventanas activas en un proyecto de Visual C#. Para desplazarse rápidamente a una
ventana, presione CTRL+TAB para abrir una ventana que muestra todas las ventanas activas de herramientas y código fuente.
Mueva las teclas de dirección mientras mantiene presionada la tecla CTRL para seleccionar la ventana que desea mostrar.
Barras de exploración
La parte superior de cada ventana del editor de código contiene la barra de exploración, que se compone de dos cuadros de
lista. El de la izquierda contiene todas las clases definidas en el archivo actual. El de la derecha, contiene todos los miembros de
la clase seleccionada en el cuadro de lista de la izquierda. Puede ir directamente a un método seleccionándolo en el cuadro de
lista derecho.
Buscar en archivos
Si presiona CTRL+MAYÚS+F, se abrirá el cuadro de diálogo Buscar en archivos, que permite realizar operaciones de buscar y
reemplazar en la totalidad de un proyecto.
Nota
Para cambiar el nombre de métodos o tipos, o para cambia parámetros de método, utilice la función Refactorización, que es
más profunda e inteligente que Buscar y reemplazar. Para obtener más información, vea Refactorización.
Los mensajes de error del compilador de C# suelen ser muy claros y descriptivos, pero si no consigue deducir el problema,
puede ir a la página de Ayuda del mensaje presionando F1 con el mensaje de error seleccionado en la lista de errores. La
página de Ayuda contiene información útil adicional. Si todavía no puede resolver el problema, el paso siguiente es plantear su
pregunta en uno de los foros o grupos de noticias de C#. Para obtener acceso a los foros, haga clic en Formular una
pregunta en el menú Comunidad.
Nota
Si la página de Ayuda del error del compilador no es de utilidad para resolver el error, puede enviar una descripción del prob
lema a Microsoft para ayudar a mejorar la documentación. Para enviar el correo electrónico, haga clic en el vínculo situado e
n la parte inferior de la página de Ayuda que contiene el error.
Configuraciones de lanzamiento y de depuración
Mientras siga trabajando activamente en el proyecto, es muy probable que desee generar la aplicación con la configuración de
depuración, que le permite ver el valor de las variables y controlar la ejecución en el depurador. También puede crear y probar
generaciones en la configuración de lanzamiento para comprobar que no se ha introducido ningún error que sólo se
manifieste en uno u otro tipo de generación. En programación de .NET Framework, estos errores son muy raros, pero pueden
producirse.
Cuando esté preparado para distribuir la aplicación a los usuarios finales, cree una generación de lanzamiento, que tendrá un
tamaño muy inferior y un rendimiento muy superior al de la configuración de depuración correspondiente. Puede establecer la
configuración de generación en el panel Generar del Diseñador de proyectos o en la barra de herramientas Generar. Para
obtener más información, vea Configuraciones de generación.
Depuración
Cuando trabaje con el editor de código, puede establecer en cualquier momento un punto de interrupción en una línea de
código presionando F9. Cuando presione F5 para ejecutar la aplicación en el depurador de Visual Studio, la aplicación se
detendrá en la línea y podrá examinar el valor de las variables, observar cómo o cuándo la ejecución sale de un bucle, recorrer
el código línea a línea mediante la tecla F10 o establecer puntos de interrupción adicionales.
También puede establecer puntos de interrupción condicionales, que sólo detendrán la ejecución si se cumple una condición
determinada. Los puntos de seguimiento son similares a los puntos de interrupción, pero en lugar de detener la interrupción,
se limitan a escribir el valor de una variable determinada en la ventana de resultados. Para obtener más información, vea
Puntos de interrupción y puntos de seguimiento.
Cuando la ejecución se detiene en un punto de interrupción, puede situar el cursor sobre cualquier variable del ámbito para
ver información sobre ella. La ilustración siguiente muestra una sugerencia de datos en el depurador:
Puede recorrer el código línea a línea presionando F10 después de que el depurador se haya detenido en un punto de
interrupción. Incluso puede corregir ciertos tipos de errores en el código y proseguir con la depuración sin necesidad de
detener y volver a compilar la aplicación.
El depurador de Visual Studio es una eficaz herramienta, y merece la pena invertir tiempo en leer la documentación para
comprender distintos conceptos como Editar y continuar, Ver datos en el depurador, Visualizadores y Depuración Just-In-Time.
Vea también
Tareas
Cómo: Establecer configuraciones Debug y Release
Cómo: Depurar el código en el editor
Referencia
System.Diagnostics
Otros recursos
Visual C#
Utilizar el entorno IDE de Visual C#
Preparación de la depuración: tipos de proyectos de C#, J# y Visual Basic
Preparación y configuración de la depuración
Entorno de desarrollo de Visual C#
Para agregar un diagrama de clase a un proyecto, haga clic en Agregar nuevo elemento en el menú Proyecto y, a
continuación, haga clic en Agregar diagrama de clase.
Para obtener más información, vea Diseñar y ver clases y tipos.
Examinador de objetos
El Examinador de objetos permite ver información de tipos de archivos DLL nativos y administrados, incluidos objetos COM.
Aunque la información que se ve en el Examinador de objetos es similar a la que se muestra en la Vista de clases, puede
utilizarlo para examinar cualquier DLL del sistema, y no sólo aquellas a las que se hace referencia en su propio proyecto.
Además, el Examinador de objetos también muestra comentarios de documentación XML para el tipo seleccionado. La
ilustración siguiente muestra cómo el Examinador de objetos presenta la información de tipos en archivos binarios.
Para obtener más información, vea Examinador de objetos
Metadatos como origen:
La función Metadatos como origen permite ver la información de tipos de las clases de los ensamblados administrados como
si fueran código fuente de su propio proyecto. Es una forma cómoda de ver a primera vista las firmas de todos los métodos
públicos de una clase cuando no se tiene acceso al código fuente real.
Por ejemplo, si escribe la instrucción System.Console.WriteLine() en el editor de código, coloca el punto de inserción en
Console, hace clic con el botón secundario del mouse y selecciona Ir a definición, verá lo que parece un archivo de código
fuente que contiene la declaración de la clase Console. Esta declaración se construye a partir de los metadatos del ensamblado
mediante el uso de Reflexión y, aunque no expone la implementación de ningún método, muestra todos los comentarios de
documentación XML presentes.
También puede utilizar la función Metadatos como origen seleccionando un tipo administrado en el Examinador de objetos y
haciendo clic en Ventana Definición de código en el menú Ver.
Para obtener más información y una ilustración, vea Metadatos como origen.
Análisis de código para obtener código administrado
La herramienta de análisis de código para obtener código administrado analiza los ensamblados administrados y ofrece
información, como los problemas de seguridad potenciales y las infracciones de las reglas de programación y diseño
establecidas en las Instrucciones de diseño de Microsoft .NET Framework. Esta información se presenta en forma de
advertencias. Para obtener acceso a la herramienta en el Diseñador de proyectos, haga clic con el botón secundario del mouse
en Propiedades en el Explorador de soluciones y seleccione Abrir.
Para obtener más información, vea Análisis de código, Diseñador de proyectos y
Análisis de código para obtener información general de código administrado.
Vea también
Conceptos
Editar código (Visual C#)
Reflexión (Guía de programación de C#)
Otros recursos
Utilizar el entorno IDE de Visual C#
Instrucciones de diseño para desarrollar bibliotecas de clases
Instrucciones de diseño de excepciones
Instrucciones de diseño de miembros
Instrucciones de diseño de tipos
Entorno de desarrollo de Visual C#
Para editar los recursos incrustados, debe trabajar directamente en el archivo .resx para manipular los caracteres o bytes
individuales. Por eso es más conveniente almacenar los tipos de archivo complejos como recursos vinculados durante el
desarrollo. Puede utilizar el Editor binario para modificar archivos de recursos, incluido el archivo .resx, en el nivel binario en
formato ASCII o hexadecimal. Puede utilizar el Editor de imágenes para modificar iconos y cursores así como archivos .jpeg y
GIF almacenados como recursos vinculados. También puede elegir otras aplicaciones como editores para estos tipos de
archivo. Para obtener más información, vea Ver y editar recursos en un editor de recursos.
Compilar recursos en ensamblados
Cuando genera su aplicación, Visual Studio invoca la herramienta resgen.exe para convertir los recursos de la aplicación en
una clase interna llamada Resources. Esta clase está contenida en el archivo Resources.Designer.cs, que se anida en el archivo
Resources.resx en el Explorador de soluciones. La clase Resources encapsula todos los recursos del proyecto en propiedades
get estáticas de sólo lectura para proporcionar recursos con establecimiento inflexible de tipos en tiempo de ejecución.
Cuando genera la aplicación a través del IDE de Visual C#, todos los datos de recursos encapsulados, incluidos los archivos
vinculados y los recursos que se incrustaron en el archivo .resx, se compilan directamente en el ensamblado de la aplicación (el
archivo .exe o .dll). Es decir, el IDE de Visual C# siempre utiliza la opción del compilador /resource. Si genera la aplicación desde
la línea de comandos, puede especificar la opción del compilador /linkresource, que le permitirá implementar recursos en un
archivo independiente del ensamblado principal de la aplicación. Éste es un escenario avanzado y sólo es necesario en ciertas
situaciones raras. Un escenario más común para implementar los recursos independientemente del ensamblado principal de la
aplicación es utilizar ensamblados satélite como se describe a continuación.
Obtener acceso a los recursos en tiempo de ejecución
Para obtener acceso a un recurso en tiempo de ejecución, haga referencia a él como lo haría con cualquier otro miembro de
una clase. El ejemplo siguiente muestra cómo recuperar un recurso de mapa de bits denominado Image01. Tenga en cuenta
que la clase Resources está en un espacio de nombres denominado <projectName>.Properties, por lo que debe usar el
nombre completo de cada recurso o agregar la directiva using correspondiente en el archivo de código fuente desde el que
obtiene acceso a la clase Resources.
System.Drawing.Bitmap bitmap1 = myProject.Properties.Resources.Image01;
Internamente, la propiedad get utiliza la clase ResourceManager para crear una nueva instancia del objeto.
Para obtener más información, vea Recursos en aplicaciones y Generador de archivos de recursos (Resgen.exe).
Recursos en ensamblados satélite
Si crea aplicaciones que se localizarán (traducirán) en varios idiomas, puede almacenar cada conjunto de cadenas de referencia
cultural como un recurso en su propio ensamblado satélite. Cuando distribuya la aplicación, incluya el ensamblado de la
aplicación principal junto con los ensamblados satélite necesarios. A continuación, puede agregar ensamblados satélite
adicionales o modificar los existentes sin volver a compilar el ensamblado de la aplicación principal. Para obtener más
información, vea Crear ensamblados satélite y Buscar y utilizar recursos para una referencia cultural específica.
Vea también
Conceptos
Introducción al Diseñador de proyectos
Otros recursos
Visual C#
Introducción a Visual C#
Ensamblados en Common Language Runtime
Globalizar y localizar aplicaciones
Entorno de desarrollo de Visual C#
Implementar aplicaciones de C#
La implementación es el proceso mediante el cual se distribuye una aplicación o componente finalizado para su instalación en
otros equipos. Para las aplicaciones de consola o las aplicaciones para clientes inteligentes basadas en formularios Windows
Forms, hay dos opciones de implementación: ClickOnce y Windows Installer.
Implementación ClickOnce
La implementación ClickOnce permite publicar aplicaciones para Windows en un servidor Web o en recurso compartido de
archivos de red con el fin de simplificar la instalación. En la mayoría de los escenarios, se recomienda la opción de
implementación ClickOnce porque permite implementar aplicaciones de actualización automática basadas en Windows, que se
pueden instalar y ejecutar con una interacción mínima del usuario.
Para configurar las propiedades para la implementación ClickOnce, puede utilizar el Asistente para publicación (accesible
desde el menú Generar) o la página Publicar del Diseñador de proyectos. Para obtener más información, vea
Panel Publicar, Diseñador de proyectos. Para obtener más información acerca de ClickOnce, vea Implementación ClickOnce.
Windows Installer
La implementación de Windows Installer permite crear unos paquetes del instalador que se distribuyen entre los usuarios; el
usuario ejecuta el archivo y los pasos de instalación mediante un asistente para instalar la aplicación. Esto se hace agregando
un proyecto de instalación a su solución; una vez generado, crea un archivo de instalación que se distribuye entre los usuarios;
el usuario ejecuta el archivo y los pasos de instalación mediante un asistente para instalar la aplicación.
Para obtener más información acerca de Windows Installer, vea Implementación de Windows Installer.
Vea también
Tareas
Cómo: Publicar aplicaciones ClickOnce
Conceptos
Alternativas de implementación
Información general sobre la implementación de ClickOnce
Implementar una aplicación en tiempo de ejecución mediante Windows Installer
Proyectos de instalación
Otros recursos
Visual C#
Entorno de desarrollo de Visual C#
Refactorización
La refactorización es el proceso que consiste en mejorar el código una vez escrito cambiando su estructura interna sin
modificar su comportamiento externo.
Visual C# proporciona los siguientes comandos de refactorización en el menú Refactorización:
Extraer método
Cambiar nombre
Encapsular campo
Extraer interfaz
Promocionar una variable local a parámetro
Quitar parámetros
Reordenar parámetros
Refactorización de varios proyectos
Visual Studio admite la refactorización de varios proyectos. Todas las operaciones de refactorización que corrigen referencias
entre archivos corrigen dichas referencias entre todos los proyectos del mismo lenguaje. Esto sólo funciona en referencias
entre proyectos. Por ejemplo, si tiene una aplicación de consola que haga referencia a una biblioteca de clase, al cambiar el
nombre a un tipo de biblioteca de clase (mediante la operación de refactorización Rename), también se actualizarán las
referencias al tipo de biblioteca de clase en la aplicación de consola.
Obtener vista previa de cambios (Cuadro de diálogo)
Muchas operaciones de refactorización proporcionan la posibilidad de revisar todos los cambios de referencias que realiza una
operación de refactorización en el código, antes de aplicar dichos cambios. Para estas operaciones de refactorización,
aparecerá una opción Vista previa de los cambios de referencia en el cuadro de diálogo de refactorización. Después de
seleccionar dicha opción y aceptar la operación de refactorización, aparecerá el
Obtener vista previa de cambios (Cuadro de diálogo). Observe que el cuadro de diálogo Obtener vista previa de cambios
tiene dos vistas. La vista inferior mostrará el código con todas las actualizaciones de referencias debido a la operación de
refactorización. Si presiona Cancelar en el cuadro de diálogo Obtener vista previa de cambios, se detendrá la operación de
refactorización y el código no sufrirá ningún cambio.
Refactorización tolerante a errores
La refactorización tolera errores. En otros términos, se puede realizar una refactorización en un proyecto que no se puede
generar. Sin embargo, en estos casos el proceso de refactorización podría no actualizar correctamente las referencias
ambiguas.
Vea también
Tareas
Cómo: Restaurar miniprogramas de refactorización de C#
Otros recursos
Características del editor de código de Visual C#
Desarrollo de aplicaciones con Visual C#
Extraer método
Extract Method es una operación de Refactorización que proporciona una manera sencilla para crear un nuevo método a
partir de un fragmento de código de un miembro existente.
Utilizando Extract Method, se puede crear un nuevo método extrayendo una selección de código de dentro del bloque de
código de un miembro existente. El nuevo método se crea incluyendo el código seleccionado, y el código seleccionado del
miembro existente se reemplaza por una llamada al nuevo método. Convertir un fragmento de código en su propio método
proporciona la capacidad de reorganizar el código rápidamente y con precisión para que sea posible volver a utilizarlo y lograr
una mejor legibilidad.
Extract Method tiene las siguientes ventajas.
Fomenta el uso de mejores métodos de codificación, dando énfasis a métodos discretos y reutilizables.
Recomienda el código autodocumentado a través de una buena organización. Si se utilizan nombres descriptivos, los
métodos de alto nivel se pueden leer como una serie de comentarios.
Fomenta la creación de métodos más detallados para simplificar la sustitución.
Reduce la duplicación del código.
Comentarios
Cuando se utiliza el comando Extraer método, el nuevo método se inserta a continuación del miembro de origen en la misma
clase.
Tipos parciales
Si la clase es un tipo parcial, Extract Method genera el nuevo método inmediatamente después del miembro de origen.
Extract Method determina la firma del nuevo método, creando un método estático si el código incluido en el nuevo método
no hace ninguna referencia a los datos de la instancia.
Parámetros de tipo genérico
Si extrae un método que tiene un parámetro de tipo genérico sin restricciones, el código generado no agregará el modificador
"ref" a dicho parámetro a no ser que se le asigne un valor. Si el método extraído admite tipos de referencia como el argumento
de tipo genérico, deberá agregar manualmente el modificador "ref" al parámetro en la firma del método.
Métodos anónimos
Si intenta extraer parte de un método anónimo que incluye una referencia a una variable local que se declara o a la que se hace
referencia fuera del método anónimo, Visual Studio le advertirá que se pueden producir cambios semánticos. Especialmente,
en aquellos momentos en los que el valor de la variable local se pasa al método anónimo.
Cuando un método anónimo utiliza el valor de una variable local, el valor se obtiene en el momento en que se ejecuta el
método anónimo. Cuando un método anónimo se extrae en otro método, el valor de la variable local se obtiene en el
momento de la llamada al método extraído.
El siguiente ejemplo ilustra este cambio semántico. Si se ejecuta este código, 11 se imprimirá en la consola. Si usa Extraer
método para extraer la región de código que está marcada con comentarios de código en su propio método y, a continuación,
ejecuta el código refactorizado, 10 se imprimirá en la consola.
class Program
{
delegate void D();
D d;
static void Main(string[] args)
{
Program p = new Program();
int i = 10;
/*begin extraction*/
p.d = delegate { Console.WriteLine(i++); };
/*end extraction*/
i++;
p.d();
}
}
Para evitar esta situación, convierta las variables locales que se utilizan en el método anónimo en campos de la clase.
Vea también
Tareas
Cómo: Refactorizar código con Extraer método
Desarrollo de aplicaciones con Visual C#
3. Seleccione Extraer método en el menú Refactorizar. Aparecerá el cuadro de diálogo Extraer método.
También puede presionar CTRL+R, CTRL+M, que es el método abreviado de teclado para mostrar el cuadro de diálogo
Extraer método.
O bien, puede hacer clic con el botón secundario en el código seleccionado, señalar Refactorizar en el menú contextual
y, a continuación, hacer clic en Extraer método para mostrar el cuadro de diálogo Extraer método.
4. Especifique un nombre para el nuevo método en el cuadro de texto Nombre del nuevo método, por ejemplo,
CircleArea. Aparecerá una vista previa de la nueva firma de método en Vista previa de la firma del método.
5. Haga clic en el botón Aceptar.
Ejemplo
Para preparar este ejemplo, cree una aplicación de consola denominada ExtractMethod y, a continuación, reemplace Class1
con el código siguiente. Para obtener más información, vea Aplicación de consola.
class A
{
const double PI = 3.141592;
Vea también
Referencia
Extraer método
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
Cambiar nombre
Rename es una operación de refactorización que ofrece una manera sencilla de cambiar el nombre a los identificadores de los
símbolos de código, como campos, variables locales, métodos, espacios de nombres, propiedades y tipos. Cambiar nombre se
puede utilizar para cambiar los nombres en los comentarios y en las cadenas, además de en las declaraciones y las llamadas de
un identificador.
Nota
Cuando utilice Control de código fuente en Visual Studio, obtenga la última versión de los archivos fuente antes de intentar r
ealizar la operación de refactorización Cambiar nombre.
La operación de refactorización Cambiar nombre está disponible en las características de Visual Studio siguientes:
Caracterí Comportamiento de la refactorización en el entorno de desarrollo
stica
Editor de c En el editor de código, la operación de refactorización Cambiar nombre está disponible cuando se sitúa el cursor en
ódigo la declaración del símbolo de código. Cuando el cursor está en esta posición, puede invocar el comando Cambiar n
ombre; para ello, escriba el método abreviado de teclado, o bien seleccione Cambiar nombre en una etiqueta inte
ligente, en un menú contextual o en el menú Refactorizar. Cuando se selecciona el elemento de menú Cambiar n
ombre, aparece el cuadro de diálogo Cambiar nombre. Para obtener más información, vea
Cambiar nombre (Cuadro de diálogo) y Cómo: Cambiar el nombre de los identificadores.
Vista de cl Cuando se selecciona un identificador en la Vista de clases, la operación de refactorización Cambiar nombre está di
ases sponible en el menú contextual y en el menú Refactorizar.
Examinad Cuando se selecciona un identificador en el Examinador de objetos, la operación de refactorización Cambiar nombr
or de obje e sólo está disponible en el menú Refactorizar.
tos
Cuadrícul En la Cuadrícula de propiedades del Diseñador de Windows Forms, cuando se cambia el nombre de un control s
a de propi e inicia una operación Cambiar nombre para ese control. No aparece el cuadro de diálogo Cambiar nombre.
edades de
l Diseñado
r de Wind
ows Form
s
Explorado En el Explorador de soluciones, el comando Cambiar nombre está disponible en el menú contextual. Si el archivo
r de soluci de código fuente seleccionado contiene una clase cuyo nombre es el mismo que el del archivo, puede utilizar este c
ones omando para cambiar, de una vez, el nombre del archivo de recursos y ejecutar la operación de refactorización Ca
mbiar nombre.
Por ejemplo, si crea una aplicación predeterminada para Windows y luego cambia el nombre de Form1.cs por Test
Form.cs, entonces el nombre del archivo de código fuente Form1.cs cambiará a TestForm.cs y la clase Form1 y toda
s las referencias a ella también recibirán el nuevo nombre TestForm.
Nota
El comando Deshacer (CTRL+Z) únicamente deshará la operación de refactorización Cambiar nombre en el seno
del código, pero no volverá a establecer el nombre original del archivo.
Si el archivo de código fuente seleccionado no contiene una clase cuyo nombre es el mismo que el del archivo, en e
l Explorador de soluciones el comando Cambiar nombre únicamente cambiará el nombre del archivo de recursos y
no ejecutará la operación de refactorización Cambiar nombre.
Operaciones Cambiar nombre
Cuando se ejecuta Rename, el motor de refactorización realiza una operación de cambio de nombre específica para cada
símbolo de código, que se describe en la tabla siguiente.
Símb Operación Cambiar nombre
olo d
e cód
igo
Camp Cambia la declaración y los usos del campo por el nuevo nombre.
o
Méto Cambia el nombre del método y todas las referencias a ese método por el nuevo nombre.
do
Espaci Cambia el nombre del espacio de nombres por el nuevo nombre de la declaración, utilizando instrucciones y nombres c
o de n ompletos.
ombr
es Nota
Al cambiar el nombre de un espacio de nombres, Visual Studio actualiza también la propiedad Default Namespace
en la Página Aplicación del Diseñador de proyectos. Esta propiedad no se puede restablecer seleccionando Deshac
er en el menú Editar. Para restablecer el valor de la propiedad Default Namespace, debe editar la propiedad en el
Diseñador de proyectos.
Tipo Cambia todas las declaraciones y todos los usos del tipo por el nuevo nombre, incluso los constructores y destructores.
Para los tipos parciales, la operación Cambiar nombre se propaga a todas las partes.
Comentarios
Cuando se cambia el nombre de un miembro que implementa o reemplaza, o es implementado o reemplazado por miembros
de otros tipos, Visual Studio muestra un cuadro de diálogo en el que se indica que la operación de cambio de nombre
producirá actualizaciones en cascada. Si hace clic en continuar, el motor de refactorización busca y cambia de nombre de
forma recursiva todos los miembros en tipos base y derivados que mantengan una relación de implementación o sustitución
con el miembro al que se va a cambiar de nombre.
El ejemplo de código siguiente contiene miembros con una relación de implementación o sustitución.
C#
interface IBase
{
void Method();
}
public class Base
{
public void Method()
{ }
public virtual void Method(int i)
{ }
}
public class Derived : Base, IBase
{
public new void Method()
{ }
public override void Method(int i)
{ }
}
public class C : IBase
{
public void Method()
{ }
}
En el ejemplo anterior, al cambiar el nombre de C.Method() se cambia también el nombre de Ibase.Method() porque
C.Method() implementa Ibase.Method(). A continuación, el motor de refactorización determina de forma recursiva que
Ibase.Method() está implementado por Derived.Method() y cambia el nombre de Derived.Method(). El motor de
refactorización no cambia el nombre de Base.Method(), porque Derived.Method() no reemplaza Base.Method(). El motor de
refactorización se detiene aquí a menos que haya activado Cambiar el nombre de las sobrecargas en el cuadro de diálogo
Cambiar nombre.
Si Cambiar el nombre de las sobrecargas está activado, el motor de refactorización cambia el nombre de
Derived.Method(int i) porque sobrecarga Derived.Method(), de Base.Method(int i) porque es reemplazado por
Derived.Method(int i) y de Base.Method() porque es una sobrecarga de Base.Method(int i).
Nota
Al cambiar el nombre de un miembro que se ha definido en un ensamblado al que se hace referencia, aparece un cuadro de
diálogo en el que se explica que ese cambio producirá errores de generación.
Vea también
Tareas
Cómo: Cambiar el nombre de los identificadores
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
Comentarios
Cuando la operación de refactorización Rename busca comentarios y cadenas, se cambia el texto basándose en una simple
coincidencia de cadenas en una operación de búsqueda y sustitución global. Se recomienda elegir Vista previa de los
cambios de referencia si está seleccionada Buscar en los comentarios o Buscar en las cadenas.
Al cambiar el nombre de un espacio de nombres, Visual Studio actualiza también la propiedad Default Namespace en la
Página Aplicación del Diseñador de proyectos. Esta propiedad no se puede restablecer seleccionando Deshacer en el menú
Editar. Para restablecer el valor de la propiedad Default Namespace, debe editar la propiedad en el Diseñador de
proyectos.
Vea también
Tareas
Cómo: Cambiar el nombre de los identificadores
Referencia
Cambiar nombre
Obtener vista previa de cambios (Cuadro de diálogo)
Desarrollo de aplicaciones con Visual C#
Vea también
Referencia
Cambiar nombre
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
3. Presione MAYÚS+ALT+F10 y, a continuación, la FLECHA ABAJO para mostrar el menú de etiquetas inteligentes.
O bien,
Mueva el puntero del mouse sobre el texto de la etiqueta inteligente, para mostrarla. A continuación, mueva el puntero
del mouse sobre la etiqueta inteligente y haga clic en la flecha abajo para mostrar el menú de etiquetas inteligentes.
4. Seleccione la opción de menú Cambiar nombre de '<identificador1> ' a '<identificador2 >', a fin de invocar
Cambiar nombre sin ver una vista previa de los cambios del código. Todas las referencias a <identificador1> se
actualizarán automáticamente a <identificador2>.
O bien,
Seleccione el elemento de menú Cambiar nombre con vista previa, para invocar la operación de refactorización con
una vista previa de los cambios del código. Aparecerá el cuadro de diálogo Obtener vista previa de cambios.
Ejemplo
Para preparar este ejemplo, cree una aplicación de consola denominada RenameIdentifier y, a continuación, reemplace
Class1 con el código siguiente. Para obtener más información, vea Aplicación de consola.
class ProtoClassA
{
// Invoke on 'MethodB'.
public void MethodB(int i, bool b) { }
}
class ProtoClassC
{
void D()
{
ProtoClassA MyClassA = new ProtoClassA();
// Invoke on 'MethodB'.
MyClassA.MethodB(0, false);
}
}
Vea también
Referencia
Cambiar nombre
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
Encapsular campo
La operación de refactorización Encapsular campo permite crear rápidamente una propiedad a partir de un campo existente
y, a continuación, actualizar el código de forma transparente con referencias a la nueva propiedad.
Cuando un campo es public (Referencia de C#), otros objetos tienen acceso directo a dicho campo y pueden modificarlo, no
siendo detectados por el objeto que posee dicho campo. Si encapsula dicho campo a través del uso de
Propiedades (Guía de programación de C#), puede denegar el acceso directo a los campos.
Para crear la nueva propiedad, la operación Encapsular campo cambia el modificador de acceso del campo que desea
encapsular a private (Referencia de C#) y, a continuación, genera los descriptores de acceso get y set de dicho campo. En
algunos casos, sólo se genera un descriptor de acceso get, por ejemplo cuando el campo se declara de sólo lectura.
El motor de refactorización actualiza el código con referencias a la nueva propiedad en las áreas especificadas en la sección
Actualizar referencias del Encapsular campo (Cuadro de diálogo).
Comentarios
La operación Encapsular campo sólo es posible cuando el cursor se coloca en la misma línea que la declaración de campo.
Para las declaraciones que declaran varios campos, Encapsular campo usa la coma como límite entre los campos e inicia la
refactorización en el campo que está más cerca del cursor, en la misma línea que el cursor. También puede especificar qué
campo desea encapsular seleccionando el nombre de dicho campo en la declaración.
Los fragmentos de código de Encapsular campo modelan el código generado por esta operación de refactorización. Los
fragmentos de código se pueden modificar. Para obtener más información, vea Cómo: Administrar fragmentos de código.
Para obtener más información sobre cuándo utilizar los campos y cuándo utilizar las propiedades, vea
Comparación de procedimientos de propiedades y campos.
Vea también
Tareas
Cómo: Refactorizar código con Encapsular campo
Conceptos
Refactorización
Fragmentos de código (C#)
Desarrollo de aplicaciones con Visual C#
Actualizar referencias:
Especifica dónde el motor de refactorización actualizará de manera automática el código con las referencias a la nueva
propiedad.
Opc Descripción
ión
Exte Especifica que cada referencia al campo que está fuera del tipo que lo engloba se reemplazará con una referencia a la n
rnal ueva propiedad. Los usos del campo dentro del tipo que lo engloba siguen siendo los mismos.
Tod Especifica que cada referencia al campo se reemplazará con una referencia a la nueva propiedad.
o
Nota
Encapsular campo no actualizará las referencias al campo dentro de los constructores.
3. Seleccione Encapsular campo en el menú Refactorizar. Aparecerá el Encapsular campo (Cuadro de diálogo).
También puede presionar CTRL+R, CTRL+F, que es el método abreviado de teclado para mostrar el cuadro de diálogo
Encapsular campo.
O bien, puede hacer clic con el botón secundario en el cursor, señalar Refactorizar en el menú contextual y, a
continuación, hacer clic en Encapsular campo para mostrar el cuadro de diálogo Encapsular campo.
4. Especifique la configuración.
5. Presione ENTRAR o haga clic en el botón Aceptar.
6. Si ha seleccionado la opción Vista previa de los cambios de referencia, se abrirá la ventana
Vista previa de los cambios de referencia. Haga clic en el botón Aplicar.
Aparece el siguiente código fuente de los descriptores de acceso get y set en el archivo de código fuente:
set
{
width = value;
}
}
El código del método Main también se actualiza con el nuevo nombre de propiedad Width.
Ejemplo
Para preparar este ejemplo, cree una aplicación de consola denominada EncapsulateFieldExample y, a continuación,
reemplace Class1 con el código siguiente. Para obtener más información, vea Aplicación de consola.
class Square
{
// Select the word 'width' then use Encapsulate Field.
public int width, height;
}
class MainClass
{
public static void Main()
{
Square mySquare = new Square();
mySquare.width = 110;
mySquare.height = 150;
// Output values for width and height.
Console.WriteLine("width = {0}", mySquare.width);
Console.WriteLine("height = {0}", mySquare.height);
}
}
Vea también
Referencia
Encapsular campo
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
Extraer interfaz
Extraer interfaz es una operación de refactorización que ofrece una manera sencilla de crear una nueva interfaz con miembros
originados a partir de una clase, estructura o interfaz existente.
Cuando varios clientes utilizan el mismo subconjunto de miembros de una clase, estructura o interfaz, o cuando varias clases,
estructuras o interfaces tienen un subconjunto de miembros en común, puede resultar de gran utilidad integrar el subconjunto
de miembros en una interfaz. Para obtener más información sobre el uso de interfaces, vea
Interfaces (Guía de programación de C#).
Extraer interfaz genera una interfaz en un nuevo archivo y coloca el cursor al principio del nuevo archivo. Puede especificar qué
miembros se extraerán a la nueva interfaz, el nombre de ésta y el nombre del archivo generado, todo ello en el
Extraer interfaz (Cuadro de diálogo).
Comentarios
Únicamente se puede tener acceso a esta característica cuando el cursor está situado en la clase, la estructura o la interfaz que
contiene los miembros que se desea extraer. Cuando el cursor está en esta posición, invoque la operación de refactorización
Extraer interfaz.
Cuando se invoca Extraer interfaz en una clase o estructura, la lista de bases e interfaces se modifica, a fin de incluir el nombre
de la nueva interfaz. Cuando se invoca Extraer interfaz en una interfaz, la lista de bases e interfaces no se modifica.
Vea también
Tareas
Cómo: Refactorizar código con Extraer interfaz
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
using System;
namespace TopThreeRefactorings
{
interface IProtoA
{
void MethodB(string s);
}
}
Ejemplo
Para preparar este ejemplo, cree una aplicación de consola denominada ExtractInterface y, a continuación, reemplace
Class1 con el código siguiente. Para obtener más información, vea Aplicación de consola.
Vea también
Referencia
Extraer interfaz
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
class ProtoA
{
public static void MethodB()
{
// Invoke on 'i'
int i = 0;
}
}
class ProtoC
{
void MethodD()
{
ProtoA.MethodB();
}
}
Vea también
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
Quitar parámetros
Remove Parameters es un operación de refactorización que proporciona una forma sencilla para quitar parámetros de
métodos, indizadores o delegados. Remove Parameters cambia la declaración; en cualquier ubicación en la que se llame al
miembro, se quitará el parámetro para reflejar la nueva declaración.
La operación Remove Parameters se realiza colocando primero el cursor en un método, indizador o delegado. Cuando el
cursor está en posición, podrá invocar la operación Quitar Parameters si se selecciona en el menú Refactorizar, presionando
el método abreviado de teclado o seleccionando el comando en un menú contextual.
Al invocar al comando Quitar parámetros, aparece el cuadro de diálogo Quitar parámetros. Para obtener más información,
vea Quitar parámetros (Cuadro de diálogo) o Cómo: Quitar parámetros.
Comentarios
Es posible quitar los parámetros de una declaración de método o de una llamada al método. Coloque el cursor en la
declaración de método o en el nombre de delegado e invoque a Quitar parámetros.
Precaución
Quitar parámetros permite eliminar un parámetro al que se hace referencia dentro del cuerpo del miembro, pero no quita la
s referencias a dicho parámetro en el cuerpo del método. Esto puede producir errores de generación en el código. Sin embar
go, puede utilizar el Obtener vista previa de cambios (Cuadro de diálogo) para revisar el código, antes de ejecutar la operació
n de refactorización.
Si un parámetro que se está quitando se modifica durante la llamada a un método, la eliminación del parámetro también
quitará la modificación. Por ejemplo, si se cambia una llamada a un método de:
MyMethod(param1++, param2);
MyMethod(param2);
MyMethod(param1++, param2);
a:
MyMethod(param2);
no se incrementará param1 mediante la operación de refactorización. Se recomienda obtener una vista previa de los cambios
relacionados con la referencia.
Vea también
Tareas
Cómo: Quitar parámetros
Referencia
Quitar parámetros
Obtener vista previa de cambios (Cuadro de diálogo)
Desarrollo de aplicaciones con Visual C#
class A
{
// Invoke on 'A'.
public A(string s, int i) { }
}
class B
{
void C()
{
// Invoke on 'A'.
A a = new A("a", 2);
}
}
Vea también
Referencia
Quitar parámetros
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
Reordenar parámetros
Reordenar parámetros es una operación de refactorización de Visual C# que proporciona una manera sencilla de cambiar el
orden de los parámetros para los métodos, indizadores y delegados. Reordenar parámetros cambia la declaración y, en todas
las ubicaciones donde se llama al miembro, los parámetros se reorganizan para reflejar el nuevo orden.
Para realizar la operación Reordenar parámetros, en primer lugar sitúe el cursor en un método, indizador o delegado. Una vez
colocado el cursor en su lugar, invoque la operación Reordenar parámetros. Para ello, escriba el método abreviado de teclado
o seleccione el comando en el menú contextual.
Cuando invoca Reordenar parámetros, se abre el cuadro de diálogo Reordenar parámetros. Para obtener más información, vea
Reordenar parámetros (Cuadro de diálogo) y Cómo: Reordenar parámetros.
Comentarios
Puede reordenar los parámetros de una declaración de método o una llamada al método. Coloque el cursor en la declaración
de método o delegado, pero no en el cuerpo.
Vea también
Tareas
Cómo: Reordenar parámetros
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
class ProtoClassA
{
// Invoke on 'MethodB'.
public void MethodB(int i, bool b) { }
}
class ProtoClassC
{
void D()
{
ProtoClassA MyClassA = new ProtoClassA();
// Invoke on 'MethodB'.
MyClassA.MethodB(0, false);
}
}
Vea también
Referencia
Reordenar parámetros
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
De forma predeterminada, si ejecuta una operación de refactorización sin realizar una vista previa de los cambios de las
referencias y el programa detecta un error de compilación, el entorno de desarrollo mostrará este cuadro de diálogo de
advertencia.
Si ejecuta una operación de refactorización que tiene activada la opción Vista previa de los cambios de referencia y el
programa detecta un error de compilación, el entorno de desarrollo mostrará el siguiente mensaje de advertencia en la parte
inferior del cuadro de diálogo Obtener vista previa de cambios, en lugar de mostrar el cuadro de diálogo Advertencia de
refactorización:
El proyecto o una de sus dependencias no se genera actualmente. Puede que las referencias no estén actualizadas.
Esta advertencia de refactorización sólo está disponible para las operaciones de refactorización que proporcionan la opción
Vista previa de los cambios de referencia, que está disponible en los siguientes cuadros de diálogo de refactorización:
Cambiar nombre (Cuadro de diálogo)
Encapsular campo (Cuadro de diálogo)
Quitar parámetros (Cuadro de diálogo)
Reordenar parámetros (Cuadro de diálogo)
Muestre este cuadro de diálogo cada vez
Esta opción está seleccionada de forma predeterminada. Si está activada, el cuadro de diálogo Advertencia de
refactorización sigue apareciendo si se detectan errores de compilación durante una operación de refactorización.
Si se desactiva esta casilla de verificación, se deshabilita el cuadro de diálogo de advertencia para futuras operaciones de
refactorización. Si desactiva esta casilla de verificación, para volver a habilitar este cuadro de diálogo de advertencia para
futuras operaciones de refactorización, seleccione la opción Advertir si hay errores de generación al refactorizar en el
Avanzadas, C#/J#, Editor de texto, Opciones (Cuadro de diálogo).
Continuar
Continúa la operación de refactorización actual sin obtener una vista previa de los cambios de las referencias.
Vista previa
Abre el Obtener vista previa de cambios (Cuadro de diálogo) para que pueda obtener una vista previa del código.
Cancelar
Cancela la operación de refactorización actual. No se producirá ningún cambio en el código.
Ejemplo
El ejemplo de código siguiente muestra el lugar donde el motor de refactorización no actualizará las referencias. Si usa la
refactorización para cambiar el nombre example por otro nombre, no se actualizará la referencia de ContainsSyntaxError,
mientras que sí se actualizarán las otras dos referencias.
Vea también
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
class Example
{
private int a;
public Example(int b)
{
a = b;
}
}
Si utiliza la refactorización para cambiar el nombre de a por b, aparece este cuadro de diálogo. La referencia a la variable a,
cuyo nombre ha cambiado, ahora se enlaza al parámetro que se pasa al constructor, en lugar de enlazarse al campo.
Referencias cuya definición pasará a ser el símbolo cuyo nombre ha cambiado
Este tipo de problema de reenlace se produce cuando una referencia que antes no hacía referencia al símbolo cuyo nombre ha
cambiado, ahora sí hace referencia a él. Por ejemplo, considere el siguiente código:
class Example
{
private static void Method(object a)
{
}
private static void OtherMethod(int a)
{
}
static void Main(string[] args)
{
Method(5);
}
}
Si utiliza la refactorización para cambiar el nombre de OtherMethod por Method, aparece este cuadro de diálogo. La referencia
de Main ahora hace referencia al método sobrecargado que acepta un parámetro int en lugar del método sobrecargado que
acepta un parámetro object.
Vea también
Referencia
Obtener vista previa de cambios (Cuadro de diálogo)
Conceptos
Refactorización
Desarrollo de aplicaciones con Visual C#
Para obtener más información sobre los fragmentos de código que de incluyen de manera predeterminada en Visual C#, vea
Fragmentos de código predeterminados.
Vea también
Referencia
Selector de fragmentos de código
Desarrollo de aplicaciones con Visual C#
#region Crea una directiva #region y una directiva #endregion. En cualquier parte.
attribute Crea una declaración para una clase que se deriva de Attribute. Dentro de un espacio de nombres (incluido el es
pacio de nombres global), una clase o una estruct
ura.
exception Crea una declaración de una clase que deriva de una excepción Dentro de un espacio de nombres (incluido el es
(Exception de forma predeterminada). pacio de nombres global), una clase o una estruct
ura.
forr Crea un bucle for que disminuye la variable de bucle después Dentro de un método, un indizador, un descripto
de cada iteración. r de acceso a propiedad o un descriptor de acces
o a evento.
indizador (in Crea una declaración de indizador. Dentro de una clase o una estructura.
dexer)
invoke Crea un bloque que invoca un evento de forma segura. Dentro de un método, un indizador, un descripto
r de acceso a propiedad o un descriptor de acces
o a evento.
iterindex Crea un par de elemento de iteración e indizador "con nombre Dentro de una clase o una estructura.
" mediante una clase anidada.
prop Crea una declaración de propiedad y un campo de apoyo. Dentro de una clase o una estructura.
propg Crea una declaración de propiedad sólo con un descriptor de a Dentro de una clase o una estructura.
cceso "get" y un campo de apoyo.
sim Crea una declaración de método Main static int. Dentro de una clase o una estructura.
svm Crea una declaración de método Main static void. Dentro de una clase o una estructura.
Comentarios
Los accesos directos permiten que IntelliSense pueda rellenar automáticamente los fragmentos de código en el Editor de
código sin utilizar un menú. Para obtener más información, vea Cómo: Utilizar fragmentos de código (C#).
Vea también
Tareas
Cómo: Utilizar fragmentos de código envolventes
Referencia
Selector de fragmentos de código
Conceptos
Fragmentos de código (C#)
Desarrollo de aplicaciones con Visual C#
Puede deshabilitar esta característica; para ello, desactive la propiedad Resaltar con el delimitador automático en el
General, Editor de texto, Opciones (Cuadro de diálogo).
Color de resaltado
Cuando el cursor está situado inmediatamente antes de un delimitador inicial, o justo después del final, aparecen rectángulos
grises que resaltan los dos delimitadores e indicar que existe una asociación entre ellos. Esta característica está disponible para
los pares siguientes:
{} llaves
[] corchetes
() paréntesis
Ejemplo
Para ilustrar los colores de coincidencia de llaves, escriba (no copie y pegue) el código siguiente en el editor de código.
class A
{
public A()
{
if(true)
int x =0;
else
int x =1;
}
}
Configuración de color
La configuración de color se conserva en Valores de configuración de Visual Studio.
Vea también
Referencia
Coincidencia de llaves automática
Desarrollo de aplicaciones con Visual C#
Puede ver los metadatos como origen en el Editor de código o en la ventana Definición de código.
Ver metadatos como origen en el Editor de código
Cuando ejecute el comando Ir a definición para un elemento cuyo código fuente no esté disponible, en el Editor de código
aparecerá un documento con fichas que contiene una vista de los metadatos del elemento, mostrados en forma de origen. En
la ficha del documento aparece el nombre del tipo, seguido por [desde metadatos].
Por ejemplo, si ejecuta el comando Ir a definición para Console, en el Editor de código aparecerán metadatos para Console
en forma de código fuente C# de aspecto similar a su declaración, pero sin implementación.
Ventana de comandos No
Ayuda dinámica (Ventana) No Al presionar la tecla F1, no se muestra la ventana de Ayuda dinámica.
Para obtener más información sobre la ventana Ayuda dinámica, vea
Cómo: Personalizar la Ayuda dinámica o
Cómo: Controlar la Ventana de ayuda dinámica.
Resultados (Ventana) No
Explorador de soluciones Sí El Explorador de soluciones aparece acoplado en el lado derecho del IDE
.
Página de inicio Sí, al iniciar el IDE La Página de inicio muestra artículos de información sobre MSDN RS p
ara Visual C#.
Cuadro de herramientas Sí, cuando se crea una a El Cuadro de herramientas aparece como una ventana contraída que se
plicación de Windows F acopla en el lado izquierdo del IDE.
orms
Teclado
Característica Comportamiento
Teclas de método abreviado Visual C# admite la siguiente configuración de métodos abreviados de teclado:
Teclas de método abreviado predeterminadas de Visual C# 2005
Teclas de método abreviado predeterminadas breves
Teclas de método abreviado predeterminadas Emacs
Teclas de método abreviado predeterminadas de Visual C++ 2.0
Teclas de método abreviado predeterminadas de Visual Studio 6.0
Vea también
Otros recursos
Visual C#
Utilizar el entorno IDE de Visual C#
Entorno de desarrollo de Visual C#
La información siguiente explica las combinaciones de teclas predeterminadas disponibles para la combinación de asignación
de teclado de Visual C# 2005.
Teclas de método abreviado globales, esquema de Visual C# 2005
Teclas de método abreviado para el Diseñador HTML, esquema de Visual C# 2005
Teclas de método abreviado para el Diseñador XML, esquema de Visual C# 2005
Teclas de método abreviado para la manipulación de controles, esquema de Visual C# 2005
Teclas de método abreviado para la depuración, esquema de Visual C# 2005
Teclas de método abreviado para buscar y reemplazar, esquema de Visual C# 2005
Teclas de método abreviado para datos, esquema de Visual C# 2005
Teclas de método abreviado para desplazarse por el texto, esquema de Visual C# 2005
Teclas de método abreviado para la selección de texto, esquema de Visual C# 2005
Teclas de método abreviado para la manipulación de texto, esquema de Visual C# 2005
Teclas de método abreviado para la administración de ventanas, esquema de Visual C# 2005
Teclas de método abreviado de la Ayuda integrada, esquema de Visual C# 2005
Teclas de método abreviado del Examinador de objetos, esquema de Visual C# 2005
Teclas de método abreviado para macros, esquema de Visual C# 2005
Teclas de método abreviado para ventanas de herramientas, esquema de Visual C# 2005
Teclas de método abreviado para proyectos, esquema de Visual C# 2005
Teclas de método abreviado del Editor de imágenes, esquema de Visual C# 2005
Teclas de método abreviado del Editor de cuadros de diálogo, esquema de Visual C# 2005
Teclas de método abreviado para la refactorización, esquema de Visual C# 2005
Teclas de método abreviado del Editor de recursos administrados, esquema de Visual C# 2005
Teclas de método abreviado para fragmentos de código, esquema de Visual C# 2005
Teclas de método abreviado del Diagrama de clase, esquema de Visual C# 2005
Teclas de método abreviado para la ventana Marcadores, esquema de Visual C# 2005
Teclas de método abreviado del Editor de aceleradores y del Editor de cadenas, esquema de Visual C# 2005
Vea también
Tareas
Cómo: Trabajar con combinaciones de teclas de método abreviado
Otros recursos
Teclas de método abreviado
Entorno de desarrollo de Visual C#
Edit.Cycle CTRL + MA Pega un elemento del anillo del Portapapeles en el punto de inserción del archivo y selecciona automát
Clipboard YÚS + V icamente el elemento pegado. Se puede revisar cada elemento del anillo del Portapapeles presionando
Ring repetidamente las teclas de método abreviado.
Edit.Open CTRL + MA Muestra el cuadro de diálogo Abrir archivo, donde se puede seleccionar un archivo para abrirlo.
File YÚS + G
File.Print CTRL + P Muestra el cuadro de diálogo Imprimir, donde se puede seleccionar la configuración de impresora.
File.SaveA CTRL + MA Guarda todos los documentos de la solución actual y todos los archivos del proyecto de archivos exter
ll YÚS + S nos.
View.Back ALT + FLEC Muestra la página anterior en el historial de exploración. Sólo disponible en la ventana Explorador W
ward HA IZQUIER eb.
DA
View.EditL F2 Permite cambiar el nombre del elemento seleccionado en el Explorador de soluciones.
abel
View.For ALT + FLEC Muestra la siguiente página en el historial de exploración. Sólo disponible en la ventana Explorador
ward HA DERECH Web.
A
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Otros recursos
Teclas de método abreviado
Entorno de desarrollo de Visual C#
Format.Con CTRL + L Cuando hay texto seleccionado, muestra el cuadro de diálogo Hipervínculo. Sólo disponible en la
vertToHype vista Diseño.
rlink
Format.Inse CTRL + MAY Muestra el cuadro de diálogo Marcador. Sólo disponible en la vista Diseño.
rtBookmark ÚS + L
Format.Italic CTRL + I Alterna el texto seleccionado entre cursiva y normal. Sólo disponible en la vista Diseño.
Format.Und CTRL + U Alterna el texto seleccionado entre subrayado y normal. Sólo disponible en la vista Diseño.
erline
Layout.Inser CTRL + ALT Agrega una columna a la izquierda de la columna actual en la tabla. Sólo disponible en la vista Dise
tColumntot + FLECHA IZ ño.
heLeft QUIERDA
Layout.Inser CTRL + ALT Agrega una columna a la derecha de la columna actual en la tabla. Sólo disponible en la vista Diseñ
tColumntot + FLECHA DE o.
heRight RECHA
Layout.Inser CTRL + ALT Agrega una fila encima de la fila actual en la tabla. Sólo disponible en la vista Diseño.
tRowAbove + FLECHA AR
RIBA
Layout.Inser CTRL + ALT Agrega una fila debajo de la fila actual en la tabla. Sólo disponible en la vista Diseño.
tRowBelow + FLECHA AB
AJO
Project.Add CTRL + M, CT Agrega un nuevo archivo *.aspx al sitio Web y abre el archivo en el Diseñador HTML. Sólo disponibl
ContentPag RL + C e en la vista Diseño.
e
View.AutoCl CTRL + MAY Reemplaza de forma temporal el comportamiento predeterminado de la etiqueta de cierre por la et
oseTagOver ÚS + PUNTO iqueta actual. Para obtener más información, vea Opciones específicas de etiqueta. Sólo disponible
ride en la vista Código fuente.
View.Details CTRL + MAY Muestra iconos para los elementos HTML que no tienen representación visual, como comentarios, s
ÚS + Q ecuencias de comandos y delimitadores de elementos en posición absoluta. Sólo disponible en la vi
sta Diseño.
View.EditMa CTRL + M, CT Abre el archivo *.master en la vista Código fuente. Sólo disponible en la vista Diseño.
ster RL + M
View.NextVi CTRL + AV P Cambia entre la vista Diseño, la vista Código fuente y la vista Código de servidor en el docume
ew ÁG nto actual. Disponible en todas las vistas.
View.NonVi CTRL + ALT Muestra los símbolos para elementos no gráficos, como elementos div, span, form y script. Sólo dis
sualControl + Q ponible en la vista Diseño.
s
View.ShowS MAYÚS + AL Muestra un menú de etiquetas inteligentes de comandos comunes para los controles de servidor W
martTag T + F10 eb. Sólo disponible en la vista Diseño.
View.ViewD MAYÚS + F7 Cambia a la vista Diseño en el documento actual. Sólo disponible en la vista Código fuente.
esigner
View.ViewM MAYÚS + F7 Cambia a la vista Código fuente en el documento actual. Sólo disponible en la vista Diseño.
arkup
View.Visible CTRL + Q Muestra un borde de 1 píxel alrededor de los elementos HTML que admiten un atributo BORDER es
Borders tablecido en cero. Algunos ejemplos de estos elementos HTML son las tablas, las celdas de tabla y l
as divisiones. Sólo disponible en la vista Diseño.
Window.Pre CTRL + RE P Cambia entre la vista Diseño, la vista Código fuente y la vista Código de servidor en el docume
viousTab ÁG nto actual. Disponible en todas las vistas.
Vea también
Referencia
Diseñador HTML
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Schema.Expand CTRL + SIGNO IGUAL (=) Contrae elementos anidados. Sólo disponible en la vista de esquema del Dise
ñador XML.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Edit.MoveControlDo CTRL + FLECHA ABAJO Desplaza el control seleccionado hacia abajo en incrementos de 8 píxeles e
wnGrid n la superficie de diseño.
Edit.MoveControlLef CTRL + FLECHA IZQUIERDA Desplaza el control a la izquierda en incrementos de 8 píxeles en la superfic
tGrid ie de diseño.
Edit.MoveControlRig CTRL + FLECHA DERECHA Desplaza el control a la derecha en incrementos de 8 píxeles en la superfici
htGrid e de diseño.
Edit.MoveControlUp FLECHA ARRIBA Desplaza el control hacia arriba en incrementos de 1 píxel en la superficie d
e diseño.
Edit.MoveControlUp CTRL + FLECHA ARRIBA Desplaza el control hacia arriba en incrementos de 8 píxeles en la superficie
Grid de diseño.
Edit.SizeControlDow MAYÚS + FLECHA ABAJO Aumenta el alto del control en incrementos de 1 píxel en la superficie de dis
n eño.
Edit.SizeControlDow CTRL + MAYÚS + FLECHA A Aumenta el alto del control en incrementos de 8 píxeles en la superficie de
nGrid BAJO diseño.
Edit.SizeControlLeft MAYÚS + FLECHA IZQUIERD Reduce el ancho del control en incrementos de 1 píxel en la superficie de di
A seño.
Edit.SizeControlLeft CTRL + MAYÚS + FLECHA IZ Reduce el ancho del control en incrementos de 8 píxeles en la superficie de
Grid QUIERDA diseño.
Edit.SizeControlRigh MAYÚS + FLECHA DERECHA Aumenta el ancho del control en incrementos de 1 píxel en la superficie de
t diseño.
Edit.SizeControlRigh CTRL + MAYÚS + FLECHA D Aumenta el ancho del control en incrementos de 8 píxeles en la superficie d
tGrid ERECHA e diseño.
Edit.SizeControlUp MAYÚS + FLECHA ARRIBA Reduce el alto del control en incrementos de 1 píxel en la superficie de dise
ño.
Edit.SizeControlUpG CTRL + MAYÚS + FLECHA A Reduce el alto del control en incrementos de 8 píxeles en la superficie de di
rid RRIBA seño.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Debug.Autos CTRL + D Muestra la ventana Automático para ver los valores de las variables que se hallan en ese mom
, CTRL + ento dentro del ámbito de la línea de ejecución actual, en el procedimiento actual.
A
Debug.BreakAll CTRL + A Detiene temporalmente la ejecución de todos los procesos en una sesión de depuración. Dispon
LT + Inte ible sólo en modo de ejecución.
r
Debug.Breakpoints CTRL + D Muestra el cuadro de diálogo Puntos de interrupción, donde puede agregar y modificar punt
, CTRL + os de interrupción.
B
Debug.CallStack CTRL + D Muestra la ventana Pila de llamadas para mostrar una lista de todos los procedimientos o mar
, CTRL + cos de pila activos correspondientes al subproceso de ejecución actual. Disponible sólo en mod
C o de ejecución.
Debug.Immediate CTRL + D Muestra la ventana Inmediato, donde es posible evaluar expresiones y ejecutar comandos indi
, CTRL + I viduales.
Debug.Locals CTRL + D Muestra la ventana Variables locales para ver las variables y los valores que contienen para ca
, CTRL + da uno de los procedimientos del marco de pila actual.
L
Debug.Memory1 CTRL + A Muestra la ventana Memoria 1 para ver búferes, cadenas y otros datos de gran tamaño que no
LT + M, 1 se ven bien en las ventanas Inspección o Variables.
Debug.Memory2 CTRL + A Muestra la ventana Memoria 2 para ver búferes, cadenas y otros datos de gran tamaño que no
LT + M, 2 se ven bien en las ventanas Inspección o Variables.
Debug.Memory3 CTRL + A Muestra la ventana Memoria 3 para ver búferes, cadenas y otros datos de gran tamaño que no
LT + M, 3 se ven bien en las ventanas Inspección o Variables.
Debug.Memory4 CTRL + A Muestra la ventana Memoria 4 para ver búferes, cadenas y otros datos de gran tamaño que no
LT + M, 4 se ven bien en las ventanas Inspección o Variables.
Debug.Modules CTRL + D Muestra la ventana Módulos, que permite ver los archivos .dll o .exe utilizados por el programa
, CTRL + . En la depuración de varios procesos, puede hacer clic con el botón secundario del mouse y des
M pués hacer clic en Mostrar módulos para todos los programas.
Debug.QuickWatch CTRL + D Muestra el cuadro de diálogo Inspección rápida que contiene el valor actual de la expresión se
, CTRL + leccionada. Disponible sólo en modo de interrupción. Utilice este comando para examinar el val
Q or actual de una variable, propiedad u otra expresión para la que no haya definido una expresió
n de inspección.
Debug.Registers CTRL +D, Muestra la ventana Registros, que presenta el contenido de los registros para depurar aplicacio
CTRL + R nes de código nativo.
Debug.Restart CTRL + Termina una sesión de depuración, vuelve a generar y, a continuación, comienza a ejecutar la ap
MAYÚS licación desde el principio. Disponible en modos de interrupción y ejecución.
+ F5
Debug.RunToCurso CTRL + F En modo de interrupción, reanuda la ejecución del código desde la instrucción actual hasta la in
r 10 strucción seleccionada. El indicador de margen de la línea de ejecución actual aparece en la barr
a indicadora de margen. En modo de diseño, inicia el depurador y ejecuta el código hasta la ubic
ación del cursor.
Debug.ScriptExplor CTRL + A Muestra la ventana Explorador de secuencias de comandos que muestra el conjunto de doc
er LT + N umentos que está depurando. Disponible en modo de ejecución.
Debug.Start F5 Asocia automáticamente el depurador y ejecuta la aplicación desde el proyecto de inicio especifi
cado en el cuadro de diálogo Propiedades de <Proyecto>. Cambia a Continuar si se encuentr
a en modo de interrupción.
Debug.StartWithout CTRL + F Ejecuta el código sin llamar al depurador.
Debugging 5
Debug.StepInto F11 Ejecuta el código una instrucción cada vez, siguiendo la ejecución hasta las llamadas a funciones
.
Debug.StepOut MAYÚS Ejecuta las líneas restantes de una función en la cual se encuentra el punto de ejecución actual.
+ F11
Debug.StepOver F10 Ejecuta la línea siguiente de código, pero no sigue la ejecución a través de ninguna llamada a un
a función.
Debug.StopDebugg MAYÚS Detiene la ejecución de la aplicación actual en el programa. Disponible en modos de interrupció
ing + F5 n y ejecución.
Debug.Threads CTRL + D Muestra la ventana Subprocesos para ver todos los subprocesos del proceso actual e informaci
, CTRL + ón sobre ellos.
T
Debug.ToggleDisas CTRL + D Muestra la información de desensamblaje del archivo de código fuente actual. Disponible sólo e
sembly , CTRL + n modo de interrupción.
D
Debug.Watch CTRL + A Muestra la ventana Inspección1 para ver los valores de expresiones de inspección o variables s
LT + W, 1 eleccionadas.
Debug.Watch2 CTRL + A Muestra la ventana Inspección2 para ver los valores de expresiones de inspección o variables s
LT + W, 2 eleccionadas.
Debug.Watch3 CTRL + A Muestra la ventana Inspección3 para ver los valores de expresiones de inspección o variables s
LT + W, 3 eleccionadas.
Debug.Watch4 CTRL + A Muestra la ventana Inspección4 para ver los valores de expresiones de inspección o variables s
LT + W, 4 eleccionadas.
DebuggerContextM ALT + F9, Quita el punto de interrupción seleccionado. Disponible sólo en la ventana Puntos de interrupci
enus.BreakpointsWi D ón.
ndow.Delete
DebuggerContextM ALT +F9, Muestra la ventana Desensamblador. Disponible sólo en la ventana Puntos de interrupción.
enus. BreakpointsW A
indow.GoToDisasse
mbly
DebuggerContextM ALT + F9, Se desplaza a la ubicación del punto de interrupción seleccionado en el archivo de código. Disp
enus. BreakpointsW S onible sólo en la ventana Puntos de interrupción.
indow.GoToSource
Code
Tools.AttachToProc CTRL + A Muestra el cuadro de diálogo Asociar al proceso, que permite depurar varios programas a la v
ess LT + P ez en una única solución.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Data.InsertColu INSERT Inserta una nueva columna por encima de la columna seleccionada en el conjunto de datos. S
mn ólo disponible en el Editor de DataSet.
Data.StepInto ALT + F5 Modo de depuración de Ir a instrucciones en el objeto de base de datos activo actualmente.
QueryDesigner.C CTRL + T Cancela o detiene la consulta actualmente en ejecución. Sólo disponible en el Diseñador de c
ancelRetrievingD onsultas y vistas.
ata
QueryDesigner.C CTRL +2 Muestra el panel Criterios del Diseñador de consultas y vistas. Sólo disponible en el Diseñ
riteria ador de consultas y vistas.
QueryDesigner. CTRL +1 Muestra el panel Diagrama del Diseñador de consultas y vistas. Sólo disponible en el Dise
Diagram ñador de consultas y vistas.
QueryDesigner. CTRL + G Cuando se ejecuta en el panel Resultados, este comando desplaza el foco a la tira de la herra
GoToRow mientas acoplada en la parte inferior del diseñador. Sólo disponible en el Diseñador de cons
ultas y vistas.
QueryDesigner.J CTRL + MAYÚ Habilita el modo JOIN. Sólo disponible en el Diseñador de consultas y vistas.
oinMode S+J
QueryDesigner.R CTRL +4 Muestra el panel Resultados del Diseñador de consultas y vistas. Sólo disponible en el Dis
esults eñador de consultas y vistas.
QueryDesigner.S CTRL + 3 Muestra el panel SQL del Diseñador de consultas y vistas. Sólo disponible en el Diseñador
QL de consultas y vistas.
View.Datasets CTRL + ALT + Muestra la ventana Conjuntos de datos de informe del Diseñador de informes.
D
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Edit.ClearBookm CTRL + B, CTRL + C Quita todos los marcadores sin nombre del documento actual.
arks
Edit.DocumentE CTRL + FIN Desplaza el punto de inserción a la última línea del documento.
nd
Edit.DocumentSt CTRL + INICIO Desplaza el punto de inserción a la primera línea del documento.
art
Edit.LineDown FLECHA ABAJO Desplaza el punto de inserción una línea hacia abajo.
Edit.LineUp FLECHA ARRIBA Desplaza el punto de inserción una línea hacia arriba.
Edit.NextBookm CTRL + B, CTRL + N Desplaza el punto de inserción a la ubicación del siguiente marcador.
ark
Edit.NextError CTRL + MAYÚS + F1 Se desplaza a la siguiente entrada de error en la ventana Lista de errores, que automát
2 icamente se desplaza a la sección afectada de texto del editor.
Edit.PageDown AV PÁG Se desplaza hacia abajo una pantalla en la ventana del editor.
Edit.PageUp RE PÁG Se desplaza hacia arriba una pantalla en la ventana del editor.
Edit.PreviousBo CTRL + B, CTRL + P Desplaza el punto de inserción a la ubicación del marcador anterior.
okmark
Edit.QuickInfo CTRL + K, CTRL + I Muestra la Información rápida, en función del lenguaje actual.
Edit.ScrollLineD CTRL + FLECHA ABA Desplaza el texto una línea hacia abajo. Disponible sólo al trabajar en los editores de tex
own JO to.
Edit.ScrollLineU CTRL + FLECHA ARRI Desplaza el texto una línea hacia arriba. Disponible sólo al trabajar en los editores de te
p BA xto.
Edit.WordNext CTRL + FLECHA DER Desplaza el punto de inserción una palabra a la derecha.
ECHA
Edit.WordPrevio CTRL + FLECHA IZQ Desplaza el punto de inserción una palabra a la izquierda.
us UIERDA
View.BrowseNex CTRL + MAYÚS + 1 Se desplaza a la definición, declaración o referencia siguiente de un elemento. Disponib
t le en la ventana Examinador de objetos y Vista de clases.
View.BrowsePre CTRL + MAYÚS +2 Se desplaza a la definición, declaración o referencia anterior de un elemento. Disponibl
vious e en la ventana Examinador de objetos y Vista de clases.
View.PopBrowse CTRL + MAYÚS +8 Se desplaza al elemento anterior invocado en el código del archivo actual.
Context
View.ForwardBr CTRL + MAYÚS +7 Se desplaza al elemento siguiente invocado en el código del archivo actual.
owseContext
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Edit.CharLeftExtendCol MAYÚS + ALT + FLECHA IZQU Mueve el cursor un carácter a la izquierda y extiende la selección de col
umn IERDA umna.
Edit.CharRightExtend MAYÚS + FLECHA DERECHA Mueve el cursor un carácter a la derecha y extiende la selección.
Edit.CharRightExtendC MAYÚS + ALT + FLECHA DERE Mueve el cursor un carácter a la derecha y extiende la selección de colu
olumn CHA mna.
Edit.DocumentEndExte CTRL + MAYÚS + FIN Selecciona el texto que hay desde el cursor hasta la última línea del doc
nd umento.
Edit.DocumentStartExt CTRL + MAYÚS + INICIO Selecciona el texto que hay desde el cursor hasta la primera línea del d
end ocumento.
Edit.LineDownExtend MAYÚS + FLECHA ABAJO Extiende la selección del texto una línea hacia abajo, a partir de la ubica
ción del cursor.
Edit.LineDownExtendC MAYÚS + ALT + FLECHA ABAJ Mueve el puntero una línea hacia abajo y extiende la selección de colu
olumn O mna.
Edit.LineEndExtend MAYÚS + FIN Selecciona el texto desde el cursor al final de la línea actual.
Edit.LineEndExtendCol MAYÚS + ALT + FIN Desplaza el cursor al final de la línea y extiende la selección de columna
umn .
Edit.LineStartExtend MAYÚS + INICIO Selecciona texto desde el cursor hasta el inicio de la línea.
Edit.LineStartExtendCo MAYÚS + ALT + INICIO Desplaza el cursor al principio de la línea y extiende la selección de colu
lumn mna.
Edit.LineUpExtend MAYÚS + FLECHA ARRIBA Selecciona texto hacia arriba línea a línea, a partir de la ubicación del cu
rsor.
Edit.LineUpExtendColu MAYÚS + ALT + FLECHA ARRI Mueve el cursor hacia arriba una línea y extiende la selección de colum
mn BA na.
Edit.PageDownExtend MAYÚS + AV PÁG Extiende la selección una página hacia abajo.
Edit.SelectCurrentWor CTRL + MAYÚS + W Selecciona la palabra que contiene el cursor o la palabra a la derecha d
d el cursor.
Edit.SelectToLastGoBa CTRL + SIGNO IGUAL (=) Selecciona el contenido existente entre la ubicación actual del Editor ha
ck sta la ubicación anterior en éste.
Edit.ViewBottomExten CTRL + MAYÚS + AV PÁG Desplaza el cursor a la última línea del documento y extiende la selecci
d ón.
Edit.WordNextExtend CTRL + MAYÚS + FLECHA DE Extiende la selección una palabra hacia la derecha.
RECHA
Edit.WordNextExtendC CTRL + MAYÚS + ALT + FLEC Desplaza el cursor una palabra a la derecha y extiende la selección de c
olumn HA DERECHA olumna.
Edit.WordPreviousExte CTRL + MAYÚS + FLECHA IZQ Extiende la selección una palabra hacia la izquierda.
nd UIERDA
Edit.WordPreviousExte CTRL + MAYÚS + ALT + FLEC Desplaza el cursor una palabra a la izquierda y extiende la selección de
ndColumn HA IZQUIERDA columna.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Edit.CharTra CTRL + T Intercambia los caracteres de ambos lados del cursor. Por ejemplo, AC|BD se vuelve AB|CD. Disponi
nspose ble sólo en editores de texto.
Edit.Collapse CTRL + M, C Oculta la etiqueta HTML seleccionada y muestra puntos suspensivos (. .) en su lugar. Puede ver la et
Tag TRL + T iqueta completa como información sobre herramientas colocando el puntero del mouse sobre los .
. ..
Edit.Collapse CTRL + M, C Determina automáticamente los límites lógicos para crear regiones en el código, como procedimien
ToDefinition TRL + O tos y, a continuación, los oculta.
s
Edit.Comme CTRL + E, C Marca la línea de código actual como comentario, utilizando la sintaxis de comentario correcta para
ntSelection TRL + C el lenguaje de programación.
Edit.DeleteH CTRL + E, C Contrae el espacio en blanco de la selección o elimina el espacio en blanco adyacente hasta el curso
orizontalWhi TRL + \ r si no hay una selección.
tespace
Edit.FormatD CTRL +E, CT Aplica el formato de sangría y espaciado del lenguaje como se ha especificado en el panel Formato
ocument RL + D de dicho lenguaje en la sección Editor de texto del cuadro de diálogo Opciones.
Edit.FormatS CTRL + E, C Aplica sangría correctamente a las líneas seleccionadas de código basándose en las líneas circunda
election TRL + F ntes de código.
Edit.Generat CTRL + K, C Crea una nueva declaración de método para la llamada al método en la que se encuentra el cursor.
eMethodSub TRL + M
Para obtener más información, vea Generar código auxiliar del método.
Edit.HideSele CTRL + M, C Oculta el texto seleccionado. Un icono de señal marca la ubicación del texto oculto en el archivo.
ction TRL + H
Edit.InsertTa TAB Aplica una sangría de un número especificado de espacios a la línea de texto.
b
Edit.LineCut CTRL + L Corta al Portapapeles todas las líneas seleccionadas, o la línea actual si no se ha seleccionado nada.
Edit.LineDele CTRL + MA Elimina todas las líneas seleccionadas o, si no hay nada seleccionado, la línea actual.
te YÚS + L
Edit.LineOpe CTRL + ENT Inserta una nueva línea en blanco encima del cursor.
nAbove RAR
Edit.LineOpe CTRL + MA Inserta una nueva línea en blanco debajo del cursor.
nBelow YÚS + ENTR
AR
Edit.LineTran MAYÚS + A Desplaza la línea que contiene el punto de inserción debajo de la línea siguiente.
spose LT + T
Edit.ListMem CTRL + J Muestra los miembros de la clase actual para la finalización de instrucciones al modificar código.
bers
Edit.OverTyp INSERT Cambia entre los modos de inserción y sobrescritura. Disponible sólo cuando se trabaja en editores
eMode de texto.
Edit.Paramet CTRL + MA Muestra información sobre herramientas acerca del parámetro actual, en función del lenguaje actua
erInfo YÚS + ESPA l. Sólo disponible en la vista Código fuente del Diseñador HTML.
CIO
Edit.PastePar CTRL + MA Pega la información de parámetros previamente copiada en IntelliSense a la ubicación indicada por
ameterTip YÚS + ALT el cursor.
+P
Edit.ToggleAl CTRL + M, C Alterna todas las secciones anteriormente marcadas como texto oculto entre los estados oculto y vi
lOutlining TRL + L sible.
Edit.ToggleO CTRL + M, C Alterna la sección de texto oculto seleccionada actualmente entre los estados oculto y visible.
utliningExpa TRL + M
nsion
Edit.WordTra CTRL + MA Transpone las palabras de cualquier lado del cursor. Por ejemplo, |End Sub se cambiaría a Sub End|.
nspose YÚS + T
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Window.ActivateDo ESC Cierra un menú o cuadro de diálogo, cancela una operación en curso o coloca el foco en la
cumentWindow ventana de documento actual.
Window.MoveToN CTRL + F2 Mueve el puntero a la barra desplegable que se encuentra en la parte superior del editor d
avigationBar e código cuando el editor se encuentra en la vista Código o en la vista Código del Servid
or.
Window.NextDocu CTRL + F6 Recorre en ciclo las ventanas secundarias MDI una a la vez.
mentWindow
Window.NextDocu CTRL + TAB Muestra el Navegador del IDE, con la primera ventana de documento seleccionada.
mentWindowNav
Window.NextTool ALT + F7 Muestra el Navegador del IDE, con la primera ventana de herramientas seleccionada.
WindowNav
Window.PreviousS MAYÚS + F6 Se desplaza al panel anterior de un documento en una vista de paneles de división.
plitPane
Window.PreviousT MAYÚS + ALT Muestra el Navegador del IDE, con la ventana de herramientas anterior seleccionada.
oolWindowNav + F7
Window.ShowEzM CTRL + ALT + Sólo muestra una lista emergente de todos los documentos abiertos.
DIFileList FLECHA ABAJ
O
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Help.HowDoI CTRL + F1, CTRL Muestra la página Cómo correspondiente a la configuración de usuario seleccionada.
+h
Help.NextTop ALT + FLECHA AB Muestra el siguiente tema de la tabla de contenido. Sólo disponible en la ventana de ayuda d
ic AJO el explorador (Web).
O bien,
ALT + FLECHA DE
RECHA
Help.Previous ALT + FLECHA AR Muestra el tema anterior de la tabla de contenido. Sólo disponible en la ventana de ayuda del
Topic RIBA explorador (Web).
OR
ALT + FLECHA IZ
QUIERDA
Help.Search CTRL + F1, CTRL Muestra la página de Ayuda de Visual Studio con la ficha Buscar activa. Esta página permite
+S buscar palabras o frases en la documentación incluida en MSDN.
Help.Searchr CTRL + F1, CTRL Muestra la página de Ayuda de Visual Studio con la ficha Buscar y con el foco en la lista de te
esults +R mas generada por la última búsqueda.
Help.Window MAYÚS + F1 Muestra un tema de la Ayuda que corresponde a la interfaz de usuario actual.
Help
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Valores de configuración de Visual Studio
Entorno de desarrollo de Visual C#
Edit.Quick MAYÚS + ALT Busca el objeto o miembro seleccionado en el archivo y muestra las coincidencias en la ventana Res
FindSymb + F12 ultados de la búsqueda de símbolos.
ol
View.Obje CTRL + ALT + Muestra el Examinador de objetos para ver las clases, las propiedades, los métodos, los eventos y
ctBrowser J las constantes disponibles en los paquetes y bibliotecas de objetos, así como en los procedimientos
del proyecto.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Tools.RecordTempor CTRL + MAYÚS + R Coloca el IDE de Visual Studio en modo de grabación de macros.
aryMacro
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
View.Command CTRL + W, CT Muestra la ventana Comando, que permite escribir comandos que manipulan el entorno de
Window RL + A desarrollo integrado (IDE).
View.Document CTRL + W, CT Muestra la ventana Esquema del documento para ver el esquema plano o jerárquico del do
Outline RL + U cumento actual.
View.FindSymbo CTRL + W, CT
lResults RL + Q
View.ObjectBro CTRL + W, CT
wser RL + J
View.Output CTRL + W, CT Muestra la ventana Resultados para ver los mensajes de estado en tiempo de ejecución.
RL + O
View.PendingCh CTRL + W, CT
eckins RL + G
View.Properties CTRL + W, CT Muestra la ventana Propiedades, que enumera las propiedades y eventos en tiempo de dise
Window RL + P ño del elemento seleccionado actualmente.
View.PropertyPa MAYÚS + F4 Muestra las páginas de propiedades del elemento seleccionado.
ges
View.ServerExpl CTRL + W, CT Muestra el Explorador de servidores, que permite ver y manipular servidores de bases de d
orer RL + L atos, registros de eventos, colas de mensajes, servicios Web y otros servicios del sistema oper
ativo.
View.SolutionEx CTRL + W, CT Muestra el Explorador de soluciones, que enumera los proyectos y archivos de la solución
plorer RL + S actual.
View.TaskList CTRL + W, CT Muestra la ventana Lista de tareas, donde se pueden personalizar, clasificar por categorías y
RL + T administrar tareas, comentarios, accesos directos, advertencias y mensajes de error.
View.Toolbox CTRL + W, CT Muestra el Cuadro de herramientas, que contiene controles y otros elementos que pueden i
RL + X ncluirse o utilizarse en el código.
View.WebBrows CTRL + W, CT Muestra la ventana Explorador Web, que permite ver páginas en Internet.
er RL + W
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Build.Compil CTRL + F7 Crea un archivo objeto que contiene código máquina, directivas del vinculador, secciones, refer
e encias externas y nombres de datos y funciones para el archivo seleccionado.
File.NewFile CTRL + N Muestra el cuadro de diálogo Nuevo archivo, donde puede seleccionar un nuevo archivo para
agregarlo al proyecto actual.
File.OpenPro CTRL + MAYÚS Muestra el cuadro de diálogo Abrir proyecto, donde se pueden agregar proyectos existentes a
ject +O la solución.
Project.AddC MAYÚS + ALT + Muestra el cuadro de diálogo Agregar nuevo elemento y selecciona la plantilla Clase como p
lass C redeterminada.
Project.AddE MAYÚS + ALT + Muestra el cuadro de diálogo Agregar elemento existente, que permite agregar un archivo e
xistingItem A xistente al proyecto actual.
Project.Add CTRL + MAYÚS Muestra el cuadro de diálogo Agregar nuevo elemento, que permite agregar un archivo nue
NewItem + A vo al proyecto actual.
Project.Over CTRL + ALT + IN Permite reemplazar los métodos de clase base en una clase derivada.
ride SERT
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Image.CopyAndOut CTRL + MAYÚS + U Crea una copia de la selección actual y la resalta. Si la selección actual contiene el co
lineSelection lor de fondo, se excluirá si ha seleccionado transparente.
Image.EllipseTool CTRL + P Dibuja una elipse con el ancho de línea y el color seleccionados.
Image.EraserTool CTRL + MAYÚS + I Borra una parte de la imagen (con el color de fondo actual).
Image.LargerBrush CTRL + = Aumenta el tamaño del pincel en un píxel en cada dirección. Para disminuir el tama
ño del pincel, vea Image.SmallerBrush en esta tabla.
Image.LineTool CTRL + L Dibuja una línea recta con el tamaño, la forma y el color seleccionados.
Image.Magnificatio CTRL + M Cambia a la herramienta Aumentar, que permite ampliar secciones específicas de u
nTool na imagen.
Image.Magnify CTRL + MAYÚS + M Alterna entre el aumento actual y un aumento de 1:1.
Image.NewImageTy INSERT Abre el cuadro de diálogo Nuevo tipo de imagen de <dispositivo>, que permite cre
pe ar una imagen para un tipo de imagen diferente.
Image.NextColor CTRL + ] Cambia el color de primer plano de dibujo al siguiente color de la paleta.
O bien,
CTRL + FLECHA DER
ECHA
Image.NextRightCol CTRL + MAYÚS + ] Cambia el color de fondo por el siguiente color de la paleta.
or
O bien,
MAYÚS + CTRL + FL
ECHA DERECHA
Image.PreviousColo CTRL + [ Cambia el color de primer plano de dibujo al color de la paleta anterior.
r
O bien,
CTRL + FLECHA IZQ
UIERDA
Image.PreviousRigh CTRL + MAYÚS + [ Cambia el color de fondo de dibujo al color de la paleta anterior.
tColor
O bien,
MAYÚS + CTRL + FL
ECHA IZQUIERDA
Image.RectangleSel MAYÚS + ALT + S Selecciona una parte rectangular de la imagen para moverla, copiarla o editarla.
ectionTool
Image.RoundedRect ALT + W Dibuja un rectángulo redondeado con el ancho de línea y el color seleccionados.
angleTool
Image.ShowGrid CTRL + ALT + S Muestra u oculta la cuadrícula de píxeles (activa o desactiva la opción Cuadrícula d
e píxelesen la cuadro de diálogo Configuración de cuadrícula).
Image.ShowTileGrid CTRL + MAYÚS + AL Muestra u oculta la cuadrícula de mosaico (activa o desactiva la opción Cuadrícula
T+S de mosaicoen la cuadro de diálogo Configuración de cuadrícula).
Image.SmallBrush CTRL + . (PUNTO) Reduce el tamaño del pincel a un píxel. Vea también Image.LargerBrush y Image.Sm
allerBrush en esta tabla.
Image.SmallBrush CTRL + - (MENOS) Reduce el tamaño del pincel en un píxel en cada dirección. Para volver a ampliar el t
amaño del pincel, vea Image.LargerBrush en esta tabla.
Para obtener información sobre cómo agregar recursos a proyectos administrados, vea Recursos de aplicaciones en la Guía del
desarrollador de .NET Framework. Para obtener información sobre cómo agregar manualmente archivos de recursos a
proyectos administrados, cómo obtener acceso a recursos, cómo mostrar recursos estáticos y cómo asignar cadenas de
recursos a propiedades, vea Tutorial: Adaptar formularios Windows Forms y
Tutorial: Utilizar los recursos de adaptación con ASP.NET.
Requisitos
Ninguno
Vea también
Referencia
Editor de imágenes
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Format.AlignCente MAYÚS + F9 Alinea los centros verticales de los controles seleccionados con el control do
rs minante.
Format.AlignLefts CTRL + MAYÚS + FLECHA I Alinea los bordes izquierdos de los controles seleccionados con el control do
ZQUIERDA minante.
Format.AlignMiddl F9 Alinea los centros horizontales de los controles seleccionados con el control d
es ominante.
Format.AlignRight CTRL + MAYÚS + FLECHA D Alinea los bordes derechos de los controles seleccionados con el control domi
s ERECHA nante.
Format.AlignTops CTRL + MAYÚS + FLECHA A Alinea los bordes superiores de los controles seleccionados con el control do
RRIBA minante.
Format.ButtonBott CTRL + B Coloca los botones seleccionados a lo largo de la parte inferior central del cua
om dro de diálogo.
Format.ButtonRigh CTRL + R Coloca los botones seleccionados en la esquina superior derecha del cuadro d
t e diálogo.
Format.SizeToCont MAYÚS + F7 Cambia el tamaño del control o controles seleccionados para ajustar el texto
ent del título.
Format.SpaceAcro ALT + FLECHA DERECHA Separa de manera uniforme los controles seleccionados en dirección horizont
ss al.
Format.SpaceDow ALT + FLECHA ABAJO Separa de manera uniforme los controles seleccionados en dirección vertical.
n
Format.TabOrder CTRL + D Establece el orden los controles dentro del cuadro de diálogo.
Format.ToggleGui CTRL + G Recorre en ciclo las opciones de no cuadrícula, guías y cuadrícula para la edici
des ón de cuadros de diálogo.
Para obtener información sobre cómo agregar recursos a proyectos administrados, vea Recursos de aplicaciones en la Guía del
desarrollador de .NET Framework. Para obtener información sobre cómo agregar manualmente archivos de recursos a
proyectos administrados, cómo obtener acceso a recursos, cómo mostrar recursos estáticos y cómo asignar cadenas de
recursos a propiedades, vea Tutorial: Adaptar formularios Windows Forms y
Tutorial: Utilizar los recursos de adaptación con ASP.NET.
Vea también
Referencia
Editor de cuadros de diálogo
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Edit.FindAllRef CTRL + K, CTR Muestra la lista de lugares donde se encuentran todas las referencias de símbolos.
erences L+R
Edit.FindInFile CTRL + MAYÚ Muestra la ficha En archivos del cuadro de diálogo Buscar y reemplazar.
s S+F
Edit.FindNextS CTRL + F3 Encuentra la siguiente aparición del texto seleccionado actualmente en el documento.
elected
Edit.FindPrevi CTRL + MAYÚ Encuentra la aparición anterior del texto seleccionado actualmente o la palabra donde se encue
ousSelected S + F3 ntra el punto de inserción.
Edit.GoToFind CTRL + / Coloca el punto de inserción en el cuadro Buscar/Comando de la barra de herramientas Están
Combo dar.
Edit.Increment CTRL + I Inicia la búsqueda incremental. Si se inicia la búsqueda incremental, pero no se escribe ningún c
alSearch arácter, recupera el modelo de búsqueda anterior. Si se encuentra texto, busca la siguiente apari
ción.
Edit.Replace CTRL + H Muestra las opciones de reemplazo de la ficha Rápida del cuadro de diálogo Buscar y reempl
azar.
Edit.ReplaceIn CTRL + MAYÚ Muestra las opciones de reemplazo de la ficha En archivos del cuadro de diálogo Buscar y ree
Files S+H mplazar.
Edit.ReverseIn CTRL + MAYÚ Cambia la dirección de la búsqueda incremental para comenzar al final del archivo y avanzar ha
crementalSear S + I cia el principio.
ch
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Refactor.ExtractI CTRL + R, Muestra el Extraer interfaz (Cuadro de diálogo), que permite crear una nueva interfaz con miemb
nterface CTRL + I ros derivados de una clase, estructura o interfaz existentes.
Refactor.Extract CTRL + R, Muestra el Extraer método (Cuadro de diálogo), que permite crear un nuevo método a partir de u
Method CTRL + M n fragmento de código de un método existente.
Refactor.Promot CTRL + R, Mueve una variable de un uso local a un método, indizador o parámetro de constructor y actualiz
eLocalVariablet CTRL + P a correctamente los sitios de llamada. Para obtener más información, vea
oParameter Promocionar una variable local a parámetro.
Refactor.Remov CTRL + R, Muestra el cuadro de diálogo Quitar parámetros, que quita los parámetros de los métodos, indi
eParameters CTRL + V zadores o delegados cambiando la declaración en cualquier ubicación en la que se llama al miem
bro. Para obtener más información, vea Quitar parámetros.
Refactor.Renam F2 Muestra el Cambiar nombre (Cuadro de diálogo), que permite cambiar el nombre de los identific
e adores para los símbolos de código como campos, variables locales, métodos, espacios de nombr
O bien, es, propiedades y tipos.
CTRL +R, C
TRL + R
Refactor.Reorde CTRL + R, Muestra el Reordenar parámetros (Cuadro de diálogo), que permite cambiar el orden de los pará
rParameters CTRL + O metros de los métodos, indizadores y delegados.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Edit.Remov SUPRIMIR Quita el archivo seleccionado en las vistas Archivos, Imágenes, Iconos y Audio.
e
Edit.Remov CTRL + SUPRI Elimina la fila seleccionada en la vista Otros y la vista Cadenas.
eRow MIR
Resources. CTRL +4 Cambia el Editor de recursos administrados a la vista Audio, que muestra los archivos de sonido
Audio del proyecto actual. Los formatos de los archivos mostrados incluyen .wav, .wma y .mp3.
Resources.F CTRL +5 Cambia el editor de recursos administrados a vista Archivos, que muestra los archivos que no se
iles encuentran en las demás vistas.
Resources.I CTRL + 3 Cambia el Editor de recursos administrados a la vista Iconos, que muestra los archivos de icono (
cons *.ico) del proyecto actual.
Resources.I CTRL +2 Cambia el Editor de recursos administrados a la vista Imágenes, que muestra los archivos de im
mages agen del proyecto actual. Los formatos de archivos mostrados incluyen .bmp, .jpg y .gif.
Resources. CTRL +6 Cambia el Editor de recursos administrados a la vista Otros, que muestra una cuadrícula de confi
Other guración para agregar otros tipos que admiten la serialización de cadenas.
Resources.S CTRL +1 Cambia el Editor de recursos administrados a la vista Cadenas, que muestra cadenas en una cua
trings drícula con columnas para el nombre, valor y comentarios del recurso de cadena.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Recursos en formato de archivo .Resx
Entorno de desarrollo de Visual C#
Edit.Surround CTRL + K, CTRL Muestra el Selector de fragmentos de código, que permite seleccionar un fragmento de código
With +S mediante IntelliSense y ajustar después el fragmento alrededor del texto seleccionado.
Tools.CodeSni CTRL + K, CTRL Muestra el Administrador de fragmentos de código, que permite buscar e insertar fragmentos
ppetsManager + B de código en archivos.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
ClassDiag NUM + ( Expande los nodos contraídos en la ventana Detalles de clase o expande el compartimiento de formas se
ram.Expa signo má leccionadas en el diagrama.
nd s)
Edit.Expa MAYÚS Expande o contrae los tipos base en el compartimiento de formas seleccionadas.
ndCollap + ALT +
seBaseTy B Por ejemplo, si Interfaz1 hereda de Interfaz2, Interfaz3 e Interfaz4, las interfaces parentales se enumeran e
peList n el compartimiento de formas correspondiente a Interfaz1. Con este comando, puede contraer la lista de i
nterfaces heredadas para que sólo se muestre información de resumen sobre el número de interfaces bas
e heredadas por Interfaz1.
Edit.Navi MAYÚS Selecciona el círculo de interfaz para un compartimiento de formas. El círculo aparece en formas que impl
gateToLol + ALT + ementan una o más interfaces.
lipop L
View.Vie ENTRAR Para el elemento seleccionado, abre el archivo correspondiente y coloca el cursor en la ubicación correcta.
wCode
O bien,
F7
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Otros recursos
Trabajar con diagramas de clase
Entorno de desarrollo de Visual C#
Edit.ToggleBoomark CTRL + B, CTRL + T Habilita o deshabilita un marcador en la línea actual del documento.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Entorno de desarrollo de Visual C#
Edit.New INSERT Agrega una nueva entrada a la tabla de cadenas. Sólo disponible en el Editor de cadenas.
String
Edit.Next CTRL + W Muestra el cuadro de mensaje Capturar tecla siguiente, que le indica que presione las teclas que
KeyTyped desea utilizar como métodos abreviados de teclado. Sólo disponible en el Editor de aceleradores.
Vea también
Conceptos
Teclas de método abreviado predeterminadas de Visual C# 2005
Conceptos del lenguaje Visual C#
Migrar a Visual C#
En esta sección se presenta la sintaxis y los conceptos de C# para los programadores que migran desde otros lenguajes de
programación. También contiene la documentación de referencia del Ayudante para la conversión del lenguaje Java, que se
puede utilizar para convertir código fuente de Java en código fuente de C#.
En esta sección
C# para desarrolladores de Java
Compara la sintaxis y construcción del lenguaje C# y del lenguaje Java.
Convertir aplicaciones de Java a Visual C#
Describe el Ayudante para la conversión del lenguaje Java, una herramienta para trasladar los proyectos de Java a Visual C#.
C# para los desarrolladores de C++
Compara el lenguaje C# con algunas características del lenguaje C++.
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Visual C#
Introducción a Visual C#
Conceptos del lenguaje Visual C#
package Acme;
import java.io.*;
class Customer
{
...
}
namespace Acme
{
class Customer
{
// ...
}
}
Tenga en cuenta que las directivas using se pueden colocar dentro de una declaración de espacio de nombres, en cuyo caso
esos espacios de nombres importados forman parte del espacio de nombres contenedor.
Java no permite varios paquetes en el mismo archivo de código fuente. Sin embargo, C# permite varios espacios de nombres
en un solo archivo .cs, como se muestra a continuación:
C#
namespace AcmeAccounting
{
public class GetDetails
{
// ...
}
}
namespace AcmeFinance
{
public class ShowDetails
{
// ...
}
}
Los nombres completos pueden ser largos y difíciles de manejar, en cuyo caso puede utilizar la palabra clave using para
especificar un nombre corto, o un alias, que haga el código más legible.
En el código siguiente, se crea un alias para hacer referencia al código escrito por una compañía ficticia:
C#
using DataTier = Acme.SQLCode.Client;
class OutputSales
{
static void Main()
{
int sales = DataTier.GetSales("January");
System.Console.WriteLine("January's Sales: {0}", sales);
}
}
Observe que en la sintaxis de WriteLine, con {x} en la cadena de formato, la x denota la posición en la lista de argumentos en la
que se va a insertar el valor. Si el método GetSales devolvió 500, el resultado de la aplicación sería el siguiente:
January's Sales: 500
Directivas de preprocesamiento
Al igual que C y C++, C# incluye directivas de preprocesamiento que ofrecen la posibilidad de omitir condicionalmente
secciones de archivos de código fuente, informar de errores y condiciones de advertencia y delimitar regiones características
del código fuente. El término "directivas de preprocesamiento" sólo se utiliza con el fin de mantener la coherencia con los
lenguajes de programación C y C++, puesto que C# no incluye un paso de preprocesamiento independiente. Para obtener más
información, vea Directivas de preprocesador de C#.
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
decimal Decimal Tipo preciso fraccionario o integral, que puede representar números 128 ±1.0 × 10e−28 a ±7.9 × 10e28
decimales con 29 dígitos significativos
Dado que C# representa todos los tipos de datos primitivos como objetos, es posible llamar a un método de objeto de un tipo
de datos primitivo. Por ejemplo:
C#
static void Main()
{
int i = 10;
object o = i;
System.Console.WriteLine(o.ToString());
}
Esto se logra con la ayuda de las conversiones automáticas boxing y unboxing. Para obtener más información, vea
Conversión boxing y unboxing (Guía de programación de C#).
Constantes
Java y C# proporcionan la capacidad para declarar una variable cuyo valor se especifica en tiempo de compilación y no se
puede cambiar en tiempo de ejecución. Java utiliza el modificador de campo final para declarar este tipo de variable, mientras
que C# utiliza la palabra clave const. Además de const, C# proporciona la palabra clave readonly para declarar variables a las
que se puede asignar un valor una vez en tiempo de ejecución, ya sea en la instrucción de declaración o en otra parte del
constructor. Después de la inicialización, el valor de una variable readonly no puede cambiar. Un escenario en el que las
variables readonly son útiles es cuando los módulos que se han compilado independientemente tienen que compartir datos
como un número de versión. Si el módulo A se actualiza y se vuelve a compilar con un nuevo número de versión, el módulo B
se puede inicializar con ese nuevo valor constante sin tener que volver a compilarlo.
Enumeraciones
Las enumeraciones se utilizan para agrupar constantes con nombres en forma similar a la forma en que se utilizan en C y C++;
no están disponibles en Java. En el ejemplo siguiente se define una enumeración Color sencilla.
C#
public enum Color
{
Green, //defaults to 0
Orange, //defaults to 1
Red, //defaults to 2
Blue //defaults to 3
}
También se pueden asignar valores integrales a las enumeraciones, tal como se muestra en la siguiente declaración de
enumeración:
C#
public enum Color2
{
Green = 10,
Orange = 20,
Red = 30,
Blue = 40
}
En el siguiente ejemplo de código se llama al método GetNames del tipo Enum para mostrar las constantes disponibles para
una enumeración. Luego, asigna un valor a una enumeración y muestra el valor.
C#
class TestEnums
{
static void Main()
{
System.Console.WriteLine("Possible color choices: ");
Resultado
Possible color choices:
Green
Orange
Red
Blue
Favorite Color is Blue
Favorite Color value is 3
Cadenas
Los tipos de cadena en Java y C# denotan un comportamiento similar con leves diferencias. Ambos tipos de cadena son
inmutables, lo que significa que los valores de las cadenas no se pueden cambiar una vez que se han creado las cadenas. En
ambos casos, los métodos que parecen modificar el contenido real de una cadena crean en realidad una nueva cadena que se
devolverá como resultado, dejando la cadena original sin cambios. El proceso de comparación de los valores de cadena es
diferente en C# y Java. Para comparar los valores de cadena en Java, los desarrolladores deben llamar al método equals de un
tipo string, mientras que el operador == compara los tipos de referencia de forma predeterminada. En C#, los desarrolladores
pueden utilizar los operadores == o != para comparar directamente valores de cadena. Aunque una cadena es un tipo de
referencia en C#, los operadores == y != compararán, en forma predeterminada, los valores de las cadenas en lugar de las
referencias.
Como en Java, los desarrolladores de C# no deben usar el tipo string para concatenar cadenas con el fin de evitar la
sobrecarga de crear nuevas clases de cadenas cada vez que se concatene la cadena. En su lugar, los desarrolladores pueden
utilizar la clase StringBuilder, que es funcionalmente equivalente a la clase StringBuffer de Java.
Literales de cadena
C# proporciona la posibilidad de evitar el uso de secuencias de escape como "\t" para la ficha o "\" para los caracteres de barra
diagonal inversa dentro de las constantes de cadena. Para ello, simplemente declare la cadena textual mediante el símbolo @
para preceder la asignación del valor de cadena. Los siguientes ejemplos muestran cómo utilizar los caracteres de escape y
cómo asignar literales de cadena:
C#
static void Main()
{
//Using escaped characters:
string path1 = "\\\\FileShare\\Directory\\file.txt";
System.Console.WriteLine(path1);
La siguiente es una lista de conversiones implícitas entre los tipos de datos de .NET Framework:
Tipo de origen Tipo de destino
Byte short, ushort, int, uint, long, ulong, float, double o decimal
Float double
Puede convertir el tipo de expresiones que desee convertir explícitamente usando la misma sintaxis que en Java:
C#
long long2 = 5483;
int int2 = (int)long2; //explicit conversion
Float sbyte, byte, short, ushort, int, uint, long, ulong, char o decimal
Double sbyte, byte, short, ushort, int, uint, long, ulong, char o decimal
Decimal sbyte, byte, short, ushort, int, uint, long, ulong, char, float o double
Si cambia el valor de una de estas variables, la otra no se verá afectada de forma natural. Por ejemplo, si tiene una expresión
como la siguiente, aún no existe ninguna conexión entre las variables:
C#
int k = i;
Es decir, si cambia el valor de i, k permanecerá con el valor que tenía i en el momento de la asignación.
C#
i = 30;
System.Console.WriteLine(i.ToString()); // 30
System.Console.WriteLine(k.ToString()); // 10
Sin embargo, los tipos de referencia actúan de forma diferente. Por ejemplo, podría declarar dos variables de la siguiente
forma:
C#
Employee ee1 = new Employee();
Employee ee2 = ee1;
Ahora, puesto que las clases son tipos de referencia de C#, ee1 se conoce como referencia a Employee. La primera de las dos
líneas anteriores crea una instancia de Employee en memoria y define ee1 para que haga referencia a ella. Así, cuando se
establece ee2 para que sea igual a ee1, el primero contiene un duplicado de la referencia a la clase de la memoria. Si ahora
cambia las propiedades de ee2, las propiedades de ee1 reflejan estos cambios, ya que ambas apuntan al mismo objeto de la
memoria, tal como aparece a continuación:
Java requiere que esas conversiones se realicen manualmente. Los tipos de datos primitivos se pueden convertir en objetos de
clases contenedoras construyendo esos objetos o aplicando la conversión boxing. De igual manera, los valores de los tipos de
datos primitivos se pueden extraer de los objetos de las clases contenedoras llamando a un método adecuado de estos
objetos, o realizar una conversión unboxing. Para obtener más información acerca de las conversiones boxing y unboxing, vea
Conversión boxing (Guía de programación de C#) o Conversión unboxing (Guía de programación de C#).
Vea también
Referencia
Tipos de datos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Visual C#
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
Multiplicativo */%
Sumatorio +-
Igualdad == !=
XOR lógico ^
OR lógico |
OR condicional ||
Condicional ?:
El único operador de Java no disponible en C# es el operador de desplazamiento (>>>). Este operador está presente en Java
debido a la ausencia de variables sin signo en ese lenguaje, para los casos en que se requiere el desplazamiento a la derecha
para insertar un uno (1) en los bits más significativos.
C# admite variables sin signo y, por consiguiente, sólo necesita el operador >> estándar. Este operador genera resultados
diferentes, lo que depende de si el operando está con o sin signo. Desplazar a la derecha un número sin signo inserta un 0 en
el bit más significativo, mientras que desplazar a la derecha un número con signo copia el bit más significativo anterior.
Operadores Checked y Unchecked
Las operaciones aritméticas producirán desbordamiento si el resultado es demasiado grande para el número de bits asignados
al tipo de datos en uso. Ese desbordamiento se puede comprobar u omitir en una operación aritmética integral dada con las
palabras clave checked y unchecked. Si se trata de una expresión constante que utiliza checked, se genera un error en
tiempo de compilación.
El siguiente es un ejemplo simple que muestra el uso de estos operadores:
C#
class TestCheckedAndUnchecked
{
static void Main()
{
short a = 10000;
short b = 10000;
En este código, el operador unchecked evita el error en tiempo de compilación que, de lo contrario, se produciría por la
instrucción siguiente:
C#
short d = unchecked((short)(10000 * 10000)); // unchecked
La siguiente expresión utiliza el operador unchecked de manera predeterminada, por lo que el valor produce un
desbordamiento pero no lo comunica:
C#
short c = (short)(a * b); // unchecked by default
Con el operador checked, se puede exigir que se compruebe el desbordamiento de la expresión en tiempo de ejecución:
C#
short e = checked((short)(a * b)); // checked - run-time error
Al asignar los primeros dos valores a d y c se produce un desbordamiento, que no se comunica, con un valor de -7936 cuando
se ejecuta el programa, pero al intentar multiplicar el valor por e con checked(), el programa producirá una excepción
OverflowException.
Nota
También puede controlar si desea comprobar el desbordamiento aritmético en un bloque de código con el modificador de c
ompiladores de línea de comandos (/checked) o directamente en Visual Studio por cada proyecto.
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
case "move":
//...
goto case "delete";
case "del":
case "remove":
case "delete":
//...
break;
default:
//...
break;
}
}
Bucles foreach
C# introduce un nuevo tipo de bucle denominado bucle foreach, que es similar a For Each de Visual Basic. El bucle foreach
permite la iteración a través de cada elemento en una clase contenedora, como una matriz, que admite la interfaz IEnumerable.
El código siguiente muestra el uso de la instrucción foreach para obtener el contenido de una matriz:
C#
static void Main()
{
string[] arr= new string[] {"Jan", "Feb", "Mar"};
C#
do
{
// statements
}
while(condition); // Don't forget the trailing ; in do...while loops
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
Si se aplica un modificador readonly a un campo estático, se debe inicializar en el constructor estático de la clase.
Vea también
Referencia
Modificadores de acceso (Guía de programación de C#)
Constantes (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
El parámetro de matriz de cadena, que contiene todos los argumentos de la línea de comandos pasados, funciona igual que en
Java. Así, args[0] especifica el primer parámetro de línea de comandos, args[1] denota el segundo parámetro, etc. A
diferencia de C++, la matriz args no contiene el nombre del archivo EXE.
Otros métodos
Cuando se pasan parámetros a un método, se pueden pasar por valor o por referencia. Los parámetros de valor simplemente
toman el valor de cualquier variable para utilizarlo en el método. Por lo tanto, el valor de variable en el código de llamada no
se ve afectado por las acciones realizadas en los parámetros de un método.
Sin embargo, los parámetros de referencia apuntan a una variable declarada en el código de llamada; por lo tanto, los métodos
modificarán el contenido de esa variable cuando se pase por referencia.
Pasar por referencia
En Java y C#, los parámetros de método que hacen referencia a un objeto siempre se pasan por referencia, mientras que los
parámetros de tipo de datos primitivos se pasan por valor.
En C#, todos los parámetros se pasan por valor de manera predeterminada. Para pasarlos por referencia, se necesita
especificar una de las palabras clave ref u out. La diferencia entre estas dos palabras clave radica en la inicialización de los
parámetros. Un parámetro ref se debe inicializar antes de su utilización, mientras que un parámetro out no debe inicializarse
explícitamente sin que antes se haya pasado por referencia y se haya omitido cualquier valor anterior.
La palabra clave ref
Especifique esta palabra clave en un parámetro cuando desee que el método llamado cambie permanentemente el valor de las
variables utilizadas como parámetros. De esta manera, en lugar de pasar el valor de una variable utilizada en la llamada, se
pasa una referencia a la propia variable. Entonces el método funciona en la referencia, de modo que los cambios realizados al
parámetro durante la ejecución del método se conservan en la variable original utilizada como parámetro para el método.
El código siguiente muestra un ejemplo de esto en el método Add, donde el segundo parámetro int se pasa por referencia con
la palabra clave ref:
C#
class TestRef
{
private static void Add(int i, ref int result)
{
result += i;
return;
}
El resultado de este sencillo ejemplo demuestra que los cambios realizados al parámetro resultante se reflejan en la variable
total, utilizada en la llamada al método Add :
Original value of 'total': 20
Value after calling Add(): 30
Esto se debe a que el parámetro resultante hace referencia a la ubicación de memoria real que ocupa la variable total en el
código de llamada. Una propiedad de una clase no es una variable; por lo tanto, no se puede utilizar directamente como
parámetro ref.
La palabra clave ref debe preceder al parámetro cuando se llama al método, al igual que en la declaración de método.
La palabra clave out
La palabra clave out tiene un efecto muy similar a la palabra clave ref. Las modificaciones realizadas a un parámetro declarado
que utiliza out serán visibles fuera del método. Las dos diferencias con respecto a ref son que todo valor inicial de un
parámetro out se omite dentro del método y que un parámetro out se debe asignar durante la ejecución del método:
C#
class TestOut
{
private static void Add(int i, int j, out int result)
{
// The following line would cause a compile error:
// System.Console.WriteLine("Initial value inside method: {0}", result);
result = i + j;
return;
}
En este caso, el tercer parámetro para el método Add se declara con la palabra clave out y las llamadas al método también
necesitan la palabra clave out para ese parámetro. El resultado será:
Original value of 'total': 20
Value after calling Add(): 110
Por lo tanto, en resumen, utilice la palabra clave ref cuando desee que un método modifique una variable existente y utilice la
palabra clave out, para devolver un valor generado dentro del método. Generalmente, esto se utiliza junto con el valor que el
método devuelve cuando éste genera más de un valor resultante para el código de llamada.
Vea también
Referencia
Main() y argumentos de línea de comandos (Guía de programación de C#)
Pasar parámetros (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
En el ejemplo anterior, el método Average se declara con un parámetro params de matriz de tipo integer, lo que permite
llamarlo con cualquier número de argumentos. El resultado se muestra a continuación:
Average of List One (5, 10, 15, ): 10
Average of List Two (5, 10, 15, 20, 25, 30, ): 17.5
Se puede especificar un parámetro params de tipo Object si se desea permitir parámetros indeterminados de diferentes tipos.
Vea también
Referencia
Pasar matrices como parámetros (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
A menudo, la propiedad tendrá el mismo nombre que el miembro interno al que tiene acceso, pero con una letra mayúscula
inicial, por ejemplo, Name en el caso anterior o el miembro interno tendrá un prefijo _. Observe también el parámetro implícito
denominado value que se utiliza en el descriptor de acceso set; éste tiene el tipo de la variable miembro subyacente.
De hecho, los descriptores de acceso se representan en forma interna como métodos get_X() y set_X() para mantener la
compatibilidad con los lenguajes basados en .NET Framework, que no admiten descriptores de acceso. Una vez que una
propiedad está definida, es muy fácil obtener o establecer su valor:
C#
class TestAnimal
{
static void Main()
{
Animal animal = new Animal();
animal.Species = "Lion"; // set accessor
System.Console.WriteLine(animal.Species); // get accessor
}
}
Si una propiedad sólo tiene un descriptor de acceso get, es una propiedad de sólo lectura. Si sólo tiene un descriptor de acceso
set, es una propiedad de sólo escritura. Si tiene ambos, es una propiedad de lectura y escritura.
Vea también
Referencia
Propiedades (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
class TestCustomer
{
static void Main()
{
Customer c1 = new Customer(); //using the default constructor
c1.ID = 100;
c1.Name = "Robert";
Resultado
Cuando se compila y ejecuta el código anterior, el resultado muestra que las variables struct se inicializan de manera
predeterminada. La variable int se inicializa en 0 y la variable string se inicializa en una cadena vacía:
Struct values before initialization:
ID = 0, Name =
Struct values after initialization:
ID = 100, Name = Robert
Vea también
Tareas
Ejemplo Structs
Conceptos
Guía de programación de C#
Estructuras (Guía de programación de C#)
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
Una vez que se declara una matriz, se utiliza la palabra clave new para establecer su tamaño, como en Java. En el ejemplo
siguiente se declara la referencia de la matriz:
C#
int[] arr;
arr = new int[5]; // create a 5 element integer array
A continuación, se tiene acceso a los elementos de una matriz unidimensional mediante una sintaxis idéntica a la de Java. Los
índices de matriz de C# también se basan en cero. La sintaxis siguiente obtiene acceso al último elemento de la matriz anterior:
C#
System.Console.WriteLine(arr[4]); // access the 5th element
Inicialización
Los elementos de la matriz de C# se pueden inicializar en el momento de su creación mediante la misma sintaxis que Java:
C#
int[] arr2Lines;
arr2Lines = new int[5] {1, 2, 3, 4, 5};
A diferencia de Java, el número de inicializadores de C# debe coincidir exactamente con el tamaño de la matriz. Puede utilizar
esta función para declarar e inicializar una matriz de C# en una sola línea:
C#
int[] arr1Line = {1, 2, 3, 4, 5};
Matrices escalonadas
Tanto C# como Java admiten la creación de matrices escalonadas o no rectangulares, en las que cada fila contiene un número
diferente de columnas. Por ejemplo, la siguiente matriz escalonada tiene cuatro entradas en la primera fila y tres en la segunda:
C#
int[][] jaggedArray = new int[2][];
jaggedArray[0] = new int[4];
jaggedArray[1] = new int[3];
Matrices multidimensionales
Con C#, se pueden crear matrices multidimensionales normales que son como una matriz de valores del mismo tipo. Mientras
Java y C# admiten matrices escalonadas, C# también admite matrices multidimensionales o matrices de matrices.
Declare una matriz rectangular multidimensional mediante la siguiente sintaxis:
C#
int[,] arr2D; // declare the array reference
float[,,,] arr4D; // declare the array reference
Dado que las matrices se basan en cero, esta línea establece el elemento de la quinta columna de la cuarta fila en 906.
Inicialización
Se pueden crear, configurar e inicializar matrices multidimensionales en una instrucción única a través de uno de los métodos
siguientes:
C#
int[,] arr4 = new int [2,3] { {1,2,3}, {4,5,6} };
int[,] arr5 = new int [,] { {1,2,3}, {4,5,6} };
int[,] arr6 = { {1,2,3}, {4,5,6} };
La clase System.Array
En .NET Framework, las matrices se implementan como instancias de la clase Array. Esta clase proporciona varios métodos
útiles, como Sort y Reverse.
En el ejemplo siguiente se muestra lo fácil que es trabajar con estos métodos. En primer lugar, se invierten los elementos de
una matriz mediante el método Reverse y, a continuación, se ordenan con el método Sort:
C#
class ArrayMethods
{
static void Main()
{
// Create a string array of size 5:
string[] employeeNames = new string[5];
// Read 5 employee names from user:
System.Console.WriteLine("Enter five employee names:");
for(int i=0; i<employeeNames.Length; i++)
{
employeeNames[i]= System.Console.ReadLine();
}
// Print the array in original order:
System.Console.WriteLine("\nArray in Original Order:");
foreach(string employeeName in employeeNames)
{
System.Console.Write("{0} ", employeeName);
}
Vea también
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
public int X
{
get { return x; }
set { x = value; }
}
public int Y
{
get { return y; }
set { y = value; }
}
}
Una nueva clase, denominada ColorCoOrds, se deriva de la clase CoOrds del siguiente modo:
C#
public class ColorCoOrds : CoOrds
Luego, ColorCoOrds hereda todos los campos y métodos de la clase base, a la cual se pueden agregar nuevos campos y
métodos para proporcionar características adicionales en la clase derivada, según sea necesario. En este ejemplo, se agrega un
miembro privado y descriptores de acceso para agregar color a la clase:
C#
public class ColorCoOrds : CoOrds
{
private System.Drawing.Color screenColor;
El constructor de la clase derivada llama implícitamente al constructor de la clase base o la superclase, en terminología de Java.
En caso de herencia, se llama a todos los constructores de clase base antes que a los constructores de la clase derivada en el
orden en que las clases aparecen en la jerarquía de clases.
Convertir un tipo a una clase base
Como en Java, no se puede utilizar una referencia a una clase base para tener acceso a los miembros y métodos de una clase
derivada, aunque la referencia de la clase base pueda contener una referencia válida a un objeto del tipo derivado.
Implícitamente, se puede hacer referencia a una clase derivada con una referencia al tipo derivado:
C#
ColorCoOrds color1 = new ColorCoOrds();
CoOrds coords1 = color1;
En este código, la referencia de clase base, coords1, contiene una copia de la referencia color1.
La palabra clave base
Se puede tener acceso a los miembros de clase base en una subclase incluso cuando los miembros de base se reemplazan en
la superclase utilizando la palabra clave base. Por ejemplo, puede crear una clase derivada que contenga un método con la
misma firma que la clase base. Si se precede ese método con la palabra clave new, se indica que se trata de un método
totalmente nuevo que pertenece a la clase derivada. También se podría proporcionar un método para tener acceso al método
original de la clase base con la palabra clave base.
Por ejemplo, supongamos que la clase base CoOrds tuviera un método denominado Invert() que intercambia las
coordenadas x e y. Se podría proporcionar un sustituto para este método en la clase derivada ColorCoOrds con un código
como éste:
C#
public new void Invert()
{
int temp = X;
X = Y;
Y = temp;
screenColor = System.Drawing.Color.Gray;
}
Como se puede observar, este método intercambia x e y, luego establece el color del punto en gris. Se podría proporcionar
acceso a la implementación base para este método creando otro método en ColorCoOrds, como el de este ejemplo:
C#
public void BaseInvert()
{
base.Invert();
}
A continuación, se invoca el método base en un objeto ColorCoOrds mediante una llamada al método BaseInvert().
C#
ColorCoOrds color1 = new ColorCoOrds();
color1.BaseInvert();
Recuerde que se obtendría el mismo efecto si se asignara una referencia de la clase base a una instancia de ColorCoOrds y, a
continuación, se tuviera acceso a sus métodos:
C#
CoOrds coords1 = color1;
coords1.Invert();
public CoOrds()
{
x = 0;
y = 0;
}
Luego, podría cambiar la clase ColorCoOrds para utilizar uno de los constructores disponibles mediante la palabra clave base:
C#
public class ColorCoOrds : CoOrds
{
public System.Drawing.Color color;
public ColorCoOrds() : base ()
{
color = System.Drawing.Color.Red;
}
class TestCounters
{
static void Main()
{
CountClass counter1 = new CountClass(1);
CountClass counter100 = new Count100Class(1);
Cuando se ejecuta este código, se observa que el constructor de la clase derivada utiliza el cuerpo del método proporcionado
en la clase base, lo que permite inicializar el recuento de miembros sin duplicar el código. Éste es el resultado:
Count in base class = 2
Count in derived class = 101
Clases abstractas
Una clase abstracta declara uno o más métodos o propiedades como abstractos. La clase que declara dichos métodos no les
proporciona una implementación, aunque una clase abstracta también puede contener métodos no abstractos, es decir,
métodos para los que se ha proporcionado una implementación. No se puede crear directamente una instancia de una clase
abstracta; sólo se puede crear una instancia de una clase derivada. Estas clases derivadas deben proporcionar
implementaciones para todos los métodos y propiedades abstractos, mediante la palabra clave override, a menos que el
miembro derivado se declare abstracto.
El ejemplo siguiente declara una clase abstracta Employee. También se crea una clase derivada denominada Manager, que
proporciona una implementación del método abstracto Show() definido en la clase Employee:
C#
public abstract class Employee
{
protected string name;
class TestEmployeeAndManager
{
static void Main()
{
// Create an instance of Manager and assign it to a Manager reference:
Manager m1 = new Manager("H. Ackerman");
m1.Show();
Este código invoca la implementación del método Show() proporcionado por la clase Manager e imprime el nombre del
empleado en pantalla. Éste es el resultado:
Name : H. Ackerman
Name : M. Knott
Interfaces
Una interfaz es un tipo de clase esqueleto que contiene firmas de método pero no incluye ninguna implementación de método.
De esta manera, las interfaces son como clases abstractas que contienen sólo métodos abstractos. Las interfaces de C# son
muy similares a las de Java y funcionan de manera muy similar.
Todos los miembros de una interfaz son públicos por definición y una interfaz no puede contener constantes, campos
(miembros de datos privados), constructores, destructores ni ningún tipo de miembro estático. El compilador generará un
error si se especifica un modificador para los miembros de una interfaz.
Las clases se pueden derivar de una interfaz para implementar esa interfaz. Estas clases derivadas deben proporcionar
implementaciones para todos los métodos de la interfaz, a menos que la clase derivada se declare abstracta.
Una interfaz se declara de forma idéntica en Java. En una definición de interfaz, una propiedad indica sólo su tipo y si es de
sólo lectura, sólo escritura o de lectura y escritura únicamente por medio de las palabras clave get y set. La interfaz siguiente
declara una propiedad de sólo lectura:
C#
public interface ICDPlayer
{
void Play(); // method signature
void Stop(); // method signature
Una clase se puede heredar de esta interfaz utilizando dos puntos, en lugar de la palabra clave implements de Java. La clase
que se implementa debe proporcionar definiciones para todos los métodos y cualquier descriptor de acceso de la propiedad
necesario, del siguiente modo:
C#
public class CDPlayer : ICDPlayer
{
private int currentTrack = 0;
Si una clase implementa más de una interfaz donde hay ambigüedad en los nombres de los miembros, se resuelve utilizando
el calificador completo del nombre de la propiedad o método. Es decir, la clase derivada puede resolver el conflicto si se utiliza
el nombre completo del método para indicar a qué interfaz pertenece, como en ICDPlayer.Play().
Vea también
Referencia
Herencia (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
Para obtener más información sobre los delegados, vea Delegados (Guía de programación de C#).
Los eventos, al igual que los métodos, tienen una firma que incluye un nombre y una lista de parámetros. Esta firma se define
mediante un tipo de delegado, por ejemplo:
Es común hacer que el primer parámetro se refiera al origen del evento y que el segundo parámetro sea el objeto que contiene
los datos relacionados con el evento. Sin embargo, el lenguaje C# no requiere ni exige este diseño; una firma de evento puede
ser la misma que cualquier firma de delegado válida, siempre y cuando devuelva un valor void.
Un evento se puede declarar utilizando la palabra clave event como este ejemplo:
Para desencadenar el evento, defina el método que se va a invocar cuando el evento se provoca como en este ejemplo:
Para provocar un evento, llame al delegado y pase los parámetros relacionados con el evento. A continuación, el delegado
llamará a todos los controladores que se hayan agregado al evento. Cada evento puede tener más de un controlador asignado
para recibir el evento. En este caso, el evento llama automáticamente a cada receptor. Provocar un evento requiere sólo una
llamada al evento sin tener en cuenta el número de receptores.
Si desea que una clase reciba un evento, suscríbala a ese evento agregándole el delegado mediante el operador +=, por
ejemplo:
Para cancelar la suscripción a un evento, quite el delegado del evento utilizando al operador -=, por ejemplo:
Para obtener más información sobre eventos, vea Eventos (Guía de programación de C#).
Nota
En C# 2.0, los delegados pueden encapsular métodos con nombre y métodos anónimos. Para obtener más información sobr
e los métodos anónimos, vea Métodos anónimos (Guía de programación de C#).
Ejemplo
El ejemplo siguiente define un evento con tres métodos asociados a él. Cuando se desencadena el evento, los métodos se
ejecutan. A continuación, se quita un método del evento y se desencadena de nuevo el evento.
class TestEvent
{
// Declare the event implemented by MyEventHandler.
public event MyEventHandler TriggerIt;
// Declare a method that triggers the event:
public void Trigger()
{
TriggerIt();
}
// Declare the methods that will be associated with the TriggerIt event.
public void MyMethod1()
{
System.Console.WriteLine("Hello!");
}
public void MyMethod2()
{
System.Console.WriteLine("Hello again!");
}
public void MyMethod3()
{
System.Console.WriteLine("Good-bye!");
}
static void Main()
{
// Create an instance of the TestEvent class.
TestEvent myEvent = new TestEvent();
// Unsuscribe from the the event by removing the handler from the event:
myEvent.TriggerIt -= new MyEventHandler(myEvent.MyMethod2);
System.Console.WriteLine("\"Hello again!\" unsubscribed from the event.");
// Trigger the new event:
myEvent.Trigger();
}
}
Resultado
Hello!
Hello again!
Good-bye!
"Hello again!" unsubscribed from the event.
Hello!
Good-bye!
Vea también
Referencia
event (Referencia de C#)
delegate (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
Todas las sobrecargas de operador son métodos estáticos de la clase. También tenga en cuenta que si sobrecarga el operador
de igualdad (==), también debe sobrecargar el operador de desigualdad (!=). Los operadores < y >, y los operadores < = y >
= también se deberían sobrecargar en pares.
La lista completa de operadores que se pueden sobrecargar es la siguiente:
Operadores unarios: +, -, !, ~, ++, --, true, false
Operadores binarios: +, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, <=
El ejemplo de código siguiente crea una clase ComplexNumber que sobrecarga los operadores + y -:
C#
public class ComplexNumber
{
private int real;
private int imaginary;
Esta clase permite crear y manipular dos números complejos con código de la manera siguiente:
C#
class TestComplexNumber
{
static void Main()
{
ComplexNumber a = new ComplexNumber(10, 12);
ComplexNumber b = new ComplexNumber(8, 9);
ComplexNumber sum = a + b;
System.Console.WriteLine("Complex Number sum = {0}", sum.ToString());
ComplexNumber difference = a - b;
System.Console.WriteLine("Complex Number difference = {0}", difference.ToString());
}
}
Como se muestra en el programa, los operadores más y menos se pueden utilizar ahora casi intuitivamente en objetos que
pertenecen a la clase ComplexNumber. Éste es el resultado que se obtendría:
Complex Number a = 10 + 12i
Complex Number b = 8 + 9i
Complex Number sum = 18 + 21i
Complex Number difference = 2 + 3i
Java no admite la sobrecarga de operadores, aunque internamente sobrecarga el operador + para la concatenación de
cadenas.
Vea también
Tareas
Ejemplo Operator Overloading
Referencia
Operadores sobrecargables (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
Puede crear clases de excepción propias que deriven de Exception. Por ejemplo, el siguiente código crea una clase
InvalidDepartmentException que se podría producir, por ejemplo, si el departamento dado para un nuevo Employee no es
válido. El constructor de clase para la excepción definida por el usuario llama al constructor de la clase base con la palabra
clave base, que envía un mensaje adecuado:
C#
public class InvalidDepartmentException : System.Exception
{
public InvalidDepartmentException(string department) : base("Invalid Department: " + de
partment)
{
}
}
C# no admite excepciones controladas. En Java, éstas se declaran con la palabra clave throws para especificar que un método
puede producir un tipo particular de excepción que el código de llamada debe controlar.
Vea también
Referencia
Excepciones y control de excepciones (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
Los indizadores se habilitan definiendo una propiedad con la firma siguiente, por ejemplo, en la definición de clase:
C#
public string this [int index] //indexer
A continuación, se proporcionan los métodos get y set como se haría para una propiedad normal. Estos descriptores de acceso
son los que especifican a qué miembro interno se hace referencia cuando se utiliza el indizador.
En el siguiente ejemplo, se crea una clase denominada Department que utiliza indizadores para tener acceso a los empleados
de ese departamento, representados internamente como una matriz de cadenas:
C#
public class Department
{
private string name;
private const int MAX_EMPLOYEES = 10;
private string[] employees = new string[MAX_EMPLOYEES]; //employee array
A continuación, puede crear una instancia de esta clase y tener acceso a ella como se muestra en el ejemplo de código
siguiente:
C#
class TestDepartment
{
static void Main()
{
Department sales = new Department("Sales");
sales[0] = "Nikki";
sales[1] = "Becky";
El resultado es:
The sales team is Nikki and Becky
Agregar el atributo WebMethod provoca que .NET Framework se ocupe automáticamente del intercambio de XML/SOAP
necesario para llamar a esta función. Al llamar a este servicio Web, se recupera el valor siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">7:26 PM</string>
En el ejemplo siguiente, la clase Employee se marca como serializable al agregar el atributo SerializableAttribute. Mientras el
campo Salary esté marcado como público, no se serializará puesto que está marcado con el atributo NonSerializedAttribute.
C#
[System.Serializable()]
public class Employee
{
public int ID;
public string Name;
[System.NonSerialized()] public int Salary;
}
Para obtener más información, vea Crear atributos personalizados (Guía de programación de C#).
Delegados
Los lenguajes como C++, Pascal y otros admiten el concepto de punteros a función, que le permiten seleccionar a qué función
desea llamar en tiempo de ejecución.
Java no proporciona ninguna construcción con la funcionalidad de puntero a función, pero C# sí lo permite. A través del uso de
la clase Delegate, una instancia de delegate encapsula un método que es una entidad a la que se puede llamar.
En el caso de los métodos de instancia, el delegado consta de una instancia de la clase contenedora y un método en la
instancia. En los métodos estáticos, una entidad a la que se puede llamar consta de una clase y un método estático en la clase.
Así, se puede utilizar un delegado para invocar una función de cualquier objeto y los delegados se orientan a objetos, tienen
seguridad de tipos y son seguros.
Hay tres pasos para definir y utilizar los delegados:
Declaración
Creación de instancias
Invocación
Los delegados se declaran con la siguiente sintaxis:
C#
delegate void Del1();
Este delegado se puede utilizar posteriormente para hacer referencia a cualquier función que devuelve un valor void y no toma
ningún argumento.
Asimismo, a fin de crear un delegado para cualquier función que tome un parámetro de cadena y devuelva un valor long,
utilizaría la sintaxis siguiente:
C#
delegate long Del2(string s);
A continuación, podría asignar este delegado a cualquier método con esta firma, como:
C#
Del2 d; // declare the delegate variable
d = DoWork; // set the delegate to refer to the DoWork method
Invocar delegados
Invocar un delegado es bastante sencillo. Simplemente sustituya el nombre de la variable de delegado para el nombre de
método. Esto invoca el método Add con los valores 11 y 22, y devuelve un resultado de tipo long que se asigna a la variable
sum:
C#
Del operation; // declare the delegate variable
operation = Add; // set the delegate to refer to the Add method
long sum = operation(11, 22); // invoke the delegate
class TestMathClass
{
delegate long Del(int i, int j); // declare the delegate type
Resultado
11 + 22 = 33
30 * 40 = 1200
Una instancia de delegado debe contener una referencia de objeto. El ejemplo anterior soluciona esto al declarar los métodos
como estáticos, lo que significa que no hay necesidad de especificar una referencia de objeto. Sin embargo, si un delegado
hace referencia a un método de instancia, se debe proporcionar la referencia de objeto del modo siguiente:
C#
Del operation; // declare the delegate variable
MathClass m1 = new MathClass(); // declare the MathClass instance
operation = m1.Add; // set the delegate to refer to the Add method
En este ejemplo, Add y Multiply son métodos de instancia de MathClass. Si los métodos de MathClass no se declaran como
estáticos, se los invoca a través del delegado mediante una instancia de MathClass, de la forma siguiente:
C#
public class MathClass
{
public long Add(int i, int j) // not static
{
return (i + j);
}
Resultado
Este ejemplo proporciona el mismo resultado que el ejemplo anterior, en el que los métodos se declararon como estáticos.
11 + 22 = 33
30 * 40 = 1200
Delegados y eventos
.NET Framework también utiliza delegados en gran medida para las tareas de control de eventos, como un evento de clic de un
botón en una aplicación para Windows o Web. Mientras que el control de eventos de Java se realiza generalmente
implementando clases de agente de escucha personalizadas, los desarrolladores de C# pueden aprovechar los delegados para
el control de eventos. event se declara como un campo con un tipo de delegado, sólo que la palabra clave event precede a la
declaración del evento. Los eventos generalmente se declaran como public, pero se permite cualquier modificador de
accesibilidad. En el ejemplo siguiente se muestra la declaración de delegate y event.
C#
// Declare the delegate type:
public delegate void CustomEventHandler(object sender, System.EventArgs e);
Los delegados de evento son de multidifusión, lo que significa que pueden guardar referencias a más de un método de control
de eventos. Un delegado actúa como remitente de eventos de la clase que provoca el evento y mantiene una lista de los
controladores registrados para el evento. En el ejemplo siguiente se muestra cómo suscribir varias funciones a un evento. La
clase EventClass contiene el delegado, el evento y un método para invocar el evento. Tenga en cuenta que un evento sólo se
puede invocar desde la clase que lo declaró. La clase TestEvents se puede suscribir luego al evento mediante el operador += y
la suscripción se puede cancelar con el operador -=. Cuando se llama al método InvokeEvent, éste desencadena el evento y las
funciones que se hayan suscrito al evento se desencadenarán en forma sincrónica, como se muestra en el ejemplo siguiente.
C#
public class EventClass
{
// Declare the delegate type:
public delegate void CustomEventHandler(object sender, System.EventArgs e);
class TestEvents
{
private static void CodeToRun(object sender, System.EventArgs e)
{
System.Console.WriteLine("CodeToRun is executing");
}
System.Console.WriteLine("First Invocation:");
ec.InvokeEvent();
System.Console.WriteLine("\nSecond Invocation:");
ec.InvokeEvent();
}
}
Resultado
First Invocation:
CodeToRun is executing
MoreCodeToRun is executing
Second Invocation:
CodeToRun is executing
Vea también
Tareas
Ejemplo de delegados
Conceptos
Guía de programación de C#
Delegados (Guía de programación de C#)
Eventos (Guía de programación de C#)
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
int *p = &i;
System.Console.WriteLine("*p = " + *p);
System.Console.WriteLine("Address of p = {0:X2}\n", (int)p);
}
unsafe
{
int *p = &i;
System.Console.WriteLine("*p = " + *p);
System.Console.WriteLine("Address of p = {0:X2}\n", (int)p);
}
}
static void Main()
{
PointyMethod();
StillPointy();
}
}
En este código, el método PointyMethod() completo está marcado como no seguro porque declara y utiliza punteros. El
método StillPointy() marca un bloque de código como no seguro porque este bloque una vez más utiliza punteros.
La palabra clave fixed
En código seguro, el recolector de elementos no utilizados tiene bastante libertad para mover un objeto durante su duración
con la misión de organizar y condensar recursos libres. Sin embargo, si el código utiliza punteros, este comportamiento puede
producir fácilmente resultados inesperados; por lo tanto, puede indicar al recolector de elementos no utilizados que no mueva
determinados objetos mediante la instrucción fixed.
En el código siguiente se muestra la palabra clave fixed, que se utiliza para garantizar que el sistema no mueva una matriz
durante la ejecución de un bloque de código en el método PointyMethod(). Observe que fixed sólo se utiliza dentro de código
no seguro:
C#
class TestFixed
{
public static void PointyMethod(char[] array)
{
unsafe
{
fixed (char *p = array)
{
for (int i=0; i<array.Length; i++)
{
System.Console.Write(*(p+i));
}
}
}
}
static void Main()
{
char[] array = { 'H', 'e', 'l', 'l', 'o' };
PointyMethod(array);
}
}
Vea también
Tareas
Ejemplo de código no seguro
Conceptos
Guía de programación de C#
Código no seguro y punteros (Guía de programación de C#)
Otros recursos
Lenguaje de programación C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
Compilar el código
Si utiliza Visual C#, puede compilar y ejecutar el código en un paso único presionando F5. Si utiliza la línea de comandos y su
archivo se denomina "Hello.cs", invoque el compilador de C# del modo siguiente:
csc Hello.cs
Para obtener más información
Para obtener más información sobre la creación de una aplicación de consola, vea Crear aplicaciones de consola (Visual C#).
Para obtener más información sobre las clases de consola de .NET Framework, vea:
Clase Console, métodos WriteLine y ReadLine.
Opciones del compilador de C#, por categoría.
Lo nuevo en el lenguaje y el compilador de C# 2.0
Para obtener más información sobre la conversión automatizada de Java a C#, vea
What's New in Java Language Conversion Assistant.
Vea también
Referencia
Main() y argumentos de línea de comandos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
class TestFileIO
{
static void Main()
{
string fileName = "test.txt"; // a sample file name
// Delete the file if it exists.
if (System.IO.File.Exists(fileName))
{
System.IO.File.Delete(fileName);
}
Secciones relacionadas
Entre las clases de .NET Framework que son útiles para crear, leer y escribir en secuencias, se incluyen las clases StreamReader
y StreamWriter. Otras clases de .NET Framework útiles para controlar y procesar archivos incluyen:
Las clases FileAccess y FileAttribute.
Las clases Directory, DirectoryInfo, Path, FileInfo y DriveInfo.
Las clases BinaryReader y BinaryWriter.
Las clases StringReader y StringWriter.
Las clases TextReader y TextWriter
Las clases XmlReader y XmlWriter.
La clase ToBase64Transform.
Las clases FileStream, BufferedStream y MemoryStream.
Para obtener más información sobre la conversión automatizada de Java a C#, vea
Lo nuevo en el Ayudante para la conversión del lenguaje Java 3.0.
Para obtener más información sobre seguridad de .NET Framework, vea NET Security.
Vea también
Conceptos
Guía de programación de C#
E/S de archivos asincrónica
Otros recursos
C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
En C#, si se utiliza .NET Framework, no es necesario cargar controladores ODBC ni JDBC para tener acceso a la base de datos.
Sólo hay que establecer la cadena de conexión para el objeto de conexión a bases de datos, de la siguiente forma:
C#
static string connectionString = "Initial Catalog=northwind;Data Source=(local);Integrated
Security=SSPI;";
static SqlConnection cn = new SqlConnection(connectionString);
Para obtener más información sobre el controlador ODBC para bases de datos Oracle, vea ODBC Driver for Oracle. Para
obtener información adicional sobre el proveedor OLE DB para bases de datos DB2, vea
Microsoft Host Integration Server 2000 Developer's Guide y
Administration and Management of Data Access Using the OLE DB Provider for DB2.
Microsoft® SQL Server™ 2000 Driver for JDBC es un controlador JDBC de tipo 4, que proporciona acceso a SQL Server
2000 a través de cualquier subprograma, aplicación o servidor de aplicaciones habilitado para Java.
Ejemplo de lectura de bases de datos de Java
En Java, para realizar una operación de lectura de bases de datos, se puede utilizar un objeto ResultSet creado por el método
executeQuery del objeto Statement. El objeto ResultSet contiene los datos devueltos por la consulta. A continuación, puede
recorrer en iteración el objeto ResultSet para obtener acceso a los datos.
El ejemplo siguiente proporciona el código Java que se va a leer en una base de datos.
Connection c;
try
{
Class.forName (_driver);
c = DriverManager.getConnection(url, user, pass);
}
catch (Exception e)
{
// Handle exceptions for DriverManager
// and Connection creation:
}
try
{
Statement stmt = c.createStatement();
ResultSet results = stmt.executeQuery(
"SELECT TEXT FROM dba ");
while(results.next())
{
String s = results.getString("ColumnName");
// Display each ColumnName value in the ResultSet:
}
stmt.close();
}
catch(java.sql.SQLException e)
{
// Handle exceptions for executeQuery and getString:
}
Asimismo, para realizar una operación de escritura en la base de datos, se crea un objeto Statement a partir del objeto
Connection. El objeto Statement tiene métodos para ejecutar consultas SQL y actualizaciones en una base de datos. Las
actualizaciones y consultas se encuentran en una cadena que contiene el comando SQL de una operación de escritura que se
utilizó en el método executeUpdate del objeto Statement para devolver un objeto ResultSet.
Ejemplo de lectura de bases de datos de C#
En C#, mediante .NET Framework, el acceso a los datos se simplifica aún más a través del conjunto de clases proporcionado
por ADO.NET, que admite el acceso a bases de datos con los controladores ODBC, así como también, a través de proveedores
OLE DB. Las aplicaciones de C# pueden interactuar con bases de datos SQL para la lectura, escritura y búsqueda de datos
mediante clases ADO.NET de .NET Framework y a través de Microsoft Data Access Component (MDAC). El espacio de nombres
y las clases System.Data.SqlClient de .NET Framework facilitan aún más el acceso a las bases de datos de SQL Server.
En C#, para realizar una operación de lectura de la base de datos, puede utilizar una conexión, un comando y una tabla de
datos. Por ejemplo, para conectarse a una base de datos de SQL Server con el espacio de nombres System.Data.SqlClient,
puede utilizar lo siguiente:
Una clase SqlConnection.
Una consulta, como una clase SqlCommand.
Un conjunto de resultados, como una clase DataTable.
.NET Framework proporciona DataAdapter, que reúne estos tres objetos, de la siguiente forma:
El objeto SqlConnection se establece mediante la propiedad de conexión del objeto DataAdapter.
La consulta que se ejecutará se especifica con la propiedad SelectCommand de DataAdapter.
El objeto DataTable se crea utilizando el método Fill del objeto DataAdapter. El objeto DataTable contiene los datos
del conjunto de resultados devueltos por la consulta. Puede recorrer en iteración el objeto DataTable para tener acceso
a las filas de datos usando la colección de filas.
Para compilar y ejecutar el código, necesita lo que se indica a continuación; de lo contrario, se produce un error en la línea
databaseConnection.Open(); y se produce una excepción.
namespace DataAccess
{
using System.Data;
using System.Data.SqlClient;
class DataAccess
{
//This is your database connection:
static string connectionString = "Initial Catalog=northwind;Data Source=(local);Int
egrated Security=SSPI;";
static SqlConnection cn = new SqlConnection(connectionString);
if (recordsAffected > 0)
{
foreach (DataRow dr in dataTable.Rows)
{
System.Console.WriteLine(dr[0]);
}
}
}
catch (SqlException e)
{
string msg = "";
for (int i=0; i < e.Errors.Count; i++)
{
msg += "Error #" + i + " Message: " + e.Errors[i].Message + "\n";
}
System.Console.WriteLine(msg);
}
finally
{
if (cn.State != ConnectionState.Closed)
{
cn.Close();
}
}
}
}
}
La clase Component, que es un objeto con representación gráfica, generalmente se extiende y los métodos heredados se
utilizan o se reemplazan, por ejemplo, el método paint de un componente Shape en el código que se muestra.
import java.awt.*;
import javax.swing.*;
El usuario se puede registrar a fin de escuchar un evento de acción de un componente para controlar eventos. Por ejemplo,
cuando se presiona y se suelta un botón, AWT envía una instancia de ActionEvent a ese botón al llamar a processEvent en el
botón. El método processEvent del botón recibe todos los eventos del botón; pasa un evento de acción al llamar a su propio
método processActionEvent. El último método pasa el evento de acción a cualquier agente de escucha de la acción que
registró un interés en eventos de acción generados por este botón.
C#
En C#, el espacio de nombres y clases System.Windows.Forms de .NET Framework proporciona un completo conjunto de
componentes para el desarrollo de formularios Windows Forms. Por ejemplo, el código siguiente utiliza Label, Button y
MenuStrip.
Ejemplo de C#
Simplemente derive de la clase Form, del modo siguiente:
C#
public partial class Form1 : System.Windows.Forms.Form
En el código siguiente se muestra cómo agregar una etiqueta, un botón y un menú a un formulario.
C#
namespace WindowsFormApp
{
public partial class Form1 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.MenuStrip menu1;
public Form1()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
Al igual que en Java, en C# se puede registrar para escuchar un evento de un componente. Por ejemplo, cuando se presiona y
suelta un botón, el motor en tiempo de ejecución envía un evento Click a cualquier agente de escucha que haya registrado un
interés en el evento Click de este botón.
C#
private void button1_Click(object sender, System.EventArgs e)
{
}
Puede utilizar el código siguiente a fin de registrar button1_Click para controlar el evento Click de una instancia de Button
denominada button1.
C#
// this code can go in InitializeComponent()
button1.Click += button1_Click;
Para obtener más información, vea Crear aplicaciones Web ASP.NET (Visual C#).
Para obtener más información sobre la conversión automatizada de Java a C#, vea
Lo nuevo en el Ayudante para la conversión del lenguaje Java 3.0.
Para obtener más información sobre las clases de Forms, vea Controles de formularios Windows Forms por función y
System.Windows.Forms.
Vea también
Conceptos
Guía de programación de C#
Diseñar una interfaz de usuario (Visual C#)
Otros recursos
C# para desarrolladores de Java
Conceptos del lenguaje Visual C#
2. Cree el descriptor de implementación de Apache SOAP. Éste puede ser similar al descriptor mostrado:
<dd:service xmlns:dd="http://xml.apache.org/xml-soap/deployment"
id="urn:HelloWorld">
<dd:provider type="java"
scope="Application"
methods="sayHelloWorld">
</dd:provider>
<dd:faultListener>org.apache.soap.server.DOMFaultListener</dd:faultListener>
<dd:mappings />
</dd:service>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {
[WebMethod]
public string HelloWorld() {
return "Hello World";
}
The following operations are supported. For a formal definition, please review the Ser
vice Description.
HelloWorld
3. Haga clic en el vínculo HelloWorld para llamar al método HelloWorld de Service1. El resultado es:
SOAP 1.1
...
SOAP 1.2
...
HTTP POST
...
4. Haga clic en el botón Invocar para llamar al método HelloWorld de Service1. El resultado es:
El objeto DataTable se crea utilizando el método Fill del objeto DataAdapter. El objeto DataTable contiene los datos del
conjunto de resultados devueltos por la consulta. Se puede recorrer en iteración el objeto DataTable para obtener acceso a las
filas de datos usando la colección Rows.
El código siguiente muestra cómo tener acceso a las filas de una tabla en una base de datos de SQL Server CE (SQLCE) de un
dispositivo móvil.
C#
namespace DataAccessCE
{
using System.Data;
using System.Data.SqlServerCe;
class DataAccessCE
{
public static string connectionString = "";
public static SqlCeConnection cn = null;
public static SqlCeDataAdapter da = null;
public static DataTable dt = new DataTable();
Programación sólida
Para compilar y ejecutar el código, necesita lo que se indica a continuación; de lo contrario, se produce un error en la línea
da.Fill(dt); y se produce una excepción.
Vea también
Referencia
Dispositivos inteligentes
SqlConnection
SqlCommand
Conceptos
Guía de programación de C#
DataSet de ADO.NET
Otros recursos
C# para desarrolladores de Java
Desarrollo de dispositivos inteligentes
Utilizar DataSets en ADO.NET
ADO.NET for the Java Programmer
Conceptos del lenguaje Visual C#
Controles ActiveX
De forma similar a Java Beans, un control ActiveX es un componente y corresponde a un "objeto OLE" y un objeto COM
(Modelo de objetos componentes). Un control ActiveX, en la forma más simple, es un objeto COM que admite la interfaz
IUnknown. Los controles ActiveX representan la arquitectura principal para desarrollar componentes de software
programables que pueden reutilizarse en varios contenedores diferentes, que incluyen desde Internet Explorer hasta
herramientas de programación de software y herramientas de productividad para el usuario final. Para obtener más
información sobre los controles ActiveX, vea:
Introduction to ActiveX
Packaging ActiveX Controls
Using ActiveX Controls to Automate Your Web
Designing Secure ActiveX Controls
Using ActiveX Controls with Windows Forms in Visual Studio .NET
Depurar un control ActiveX
Aplicaciones de instalación e implementación
Visual Studio proporciona plantillas para proyectos de instalación e implementación para equipos de escritorio, Web y
dispositivos inteligentes. Una versión diferente del entorno de desarrollo puede admitir la instalación e implementación para
algunos o todos los tipos de aplicación de C# en equipos de escritorio, Web y dispositivos móviles. Para obtener más
información al respecto, vea:
Implementar aplicaciones de .NET Framework.
Distribuir aplicaciones para dispositivos
Instalación de la aplicación en el dispositivo
Walkthrough: Generating Custom CAB files for Device projects
Cabinet Packaging: Internet Explorer Code Download and the Java Package Manager
Temas relacionados
Fundamentos de las operaciones de red de .NET Framework
Fundamentos de las aplicaciones de Windows Forms
Lo nuevo en el Ayudante para la conversión del lenguaje Java 3.0
Ejemplos de .NET Framework
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Migrar a Visual C#
Ejemplos de código de C# para desarrolladores de Java
Lenguaje de programación C# para desarrolladores de Java
Introducción a Visual C#
Utilizar el entorno IDE de Visual C#
Referencia del Ayudante para la conversión del lenguaje Java
Vea también
Referencia
Modificadores de línea de comandos
Otros recursos
Convertir aplicaciones de Java a Visual C#
Conversión de varios tipos de aplicaciones de Java
Referencia del Ayudante para la conversión del lenguaje Java
Nota
Los cuadros de diálogo y comandos de menú que verá en Visual Studio pueden variar con respecto a los descritos en la Ayu
da en función de su edición o configuración activa. Para cambiar la configuración, elija Importar y exportar configuracion
es en el menú Herramientas. Para obtener más información, vea Valores de configuración de Visual Studio.
7. En la página Especificar un directorio para el nuevo proyecto, especifique el nombre y el directorio del nuevo
proyecto que se va a crear.
8. En la página Inicie la conversión, haga clic en Siguiente.
Proyectos en lenguaje Java
Para convertir un proyecto en lenguaje Java
1. Inicie Visual Studio.
2. En el menú Archivo, elija Abrir y haga clic en Convertir.
3. Seleccione Ayudante para la conversión del lenguaje Java y haga clic en Aceptar.
4. En la página Archivos de código fuente, haga clic en Directorio que contiene los archivos de proyecto.
5. En la página Seleccione el directorio de origen, haga clic en Examinar.
6. Busque el proyecto correcto y selecciónelo.
Nota
No verá los archivos en el directorio que seleccione, pero se convertirán todos los archivos .jav y .java que haya en el m
ismo. El Ayudante para la conversión del lenguaje Java omitirá la mayoría de los archivos no pertinentes, pero las carpe
tas de origen deben limpiarse antes de comenzar la conversión.
7. Agregue cualquier otro archivo necesario para su proyecto en el segundo cuadro de texto.
8. En la página Configurar el nuevo proyecto, especifique lo siguiente:
Nombre del proyecto que se va a crear.
Tipo de resultados del proyecto.
9. En la página Especificar un directorio para el nuevo proyecto, especifique el nombre y el directorio del nuevo
proyecto que se va a crear.
10. En la página Inicie la conversión, haga clic en Siguiente.
11. Corrija el código que no se pueda convertir de forma automática. Para obtener más información, vea
Actualizar manualmente código no convertido.
Vea también
Tareas
Actualizar manualmente código no convertido
Asistente para el Ayudante para la conversión del lenguaje Java
Solución de problemas: coincidencia de páginas de códigos
Referencia
Convertir (Cuadro de diálogo)
Modificadores de línea de comandos
Conceptos
Ayudante para la conversión del lenguaje Java
Referencia del Ayudante para la conversión del lenguaje Java
Para obtener acceso al asistente para el Ayudante para la conversión del lenguaje Java
1. En el menú Archivo, elija Abrir y haga clic en Convertir.
2. Haga clic en Ayudante para la conversión del lenguaje Java y en Aceptar.
Nota de seguridad Por motivos de seguridad, debería revisar el código C# convertido desde Java utilizando la
herramienta Ayudante para la conversión del lenguaje Java. El código Java no seguro se convierte en código C# no
seguro. Además, la herramienta no migra el código de ciertas clases de Java, incluidas algunas relacionadas con la
seguridad como, por ejemplo, la autenticación. En estos casos, el informe de actualización indica el código que no se ha
migrado. Es importante revisar el informe e intentar solucionar los problemas de seguridad.
Vea también
Tareas
Convertir proyectos de Visual J++ o en lenguaje Java a Visual C#
Actualizar manualmente código no convertido
Conceptos
Ayudante para la conversión del lenguaje Java
Referencia del Ayudante para la conversión del lenguaje Java
Puede alojar controles de usuario Web convertidos en un explorador igual que haría con un subprograma. Los controles
alojados se declaran en páginas HTML con la etiqueta OBJECT, en lugar de con la etiqueta APPLET. Utilice el atributo classid
para identificar el control mediante la especificación de la ruta de acceso al control y el nombre completo del mismo separado
por el signo de número (#), tal como se muestra en el siguiente ejemplo:
Para que el control se muestre correctamente, el archivo .dll que contiene el control debe estar ubicado en el mismo directorio
virtual que la página Web que lo muestra, o bien, estar instalado en la memoria caché de ensamblados global.
Clases de soporte
Para convertir la funcionalidad del proyecto original que no está disponible en Visual C#, el Ayudante para la conversión del
lenguaje Java crea clases de soporte (también llamadas administradores) que duplican la funcionalidad original. Las clases de
soporte a veces son sustancialmente diferentes, desde el punto de vista arquitectónico, de las clases que emulan. Aunque se
intente conservar la arquitectura original de su aplicación en el proyecto convertido, el objetivo principal de estas clases de
soporte es duplicar la funcionalidad original.
Informe de conversión
Podría haber algún código en su proyecto que no pudo convertirse automáticamente. Después de ejecutar el asistente para el
Ayudante para la conversión del lenguaje Java, puede ver el informe de conversión que detalla todos los errores, advertencias
y problemas encontrados durante el proceso de conversión. El código no convertido se anota en el código del nuevo proyecto
mediante comentarios etiquetados con UPGRADE_TODO. Los comentarios de conversión pueden verse en la Lista de tareas.
Cada comentario de conversión contiene un enlace al tema de Ayuda que explica cómo convertir el código de forma manual.
Para obtener más información, vea Actualizar manualmente código no convertido.
Nota de seguridad
Debe revisar cualquier código de C# convertido de Java utilizando la herramienta Ayudante para la conversión del lenguaje J
ava para evitar problemas de seguridad. Cualquier código Java no seguro se convierte en código C# no seguro. Además, la h
erramienta no migra el código de ciertas clases Java, incluyendo algunas relacionadas con la seguridad, por ejemplo, la auten
ticación. En estos casos, el informe de la actualización indica el código que no se ha migrado. Es importante revisar el inform
e y solucionar cualquier problema de seguridad.
Vea también
Tareas
Convertir proyectos de Visual J++ o en lenguaje Java a Visual C#
Actualizar manualmente código no convertido
Otros recursos
Convertir aplicaciones de Java a Visual C#
Referencia del Ayudante para la conversión del lenguaje Java
UPGRADE_NOTE Código que puede mostrar diferente comportamiento al del código original.
También podría haber errores de compilación que deberán corregirse antes de compilar la aplicación. Cada comentario
contiene una breve descripción del problema y un enlace al tema de la Ayuda que explica cómo convertir el código.
Nota
Los cuadros de diálogo y comandos de menú podrían variar con respecto a los descritos en la Ayuda en función de la edición
o de la configuración activa. Para cambiar su configuración, elija Importar y exportar configuraciones en el menú Herra
mientas. Para obtener más información, vea Valores de configuración de Visual Studio.
Japonés EUC-JP
Coreano EUC-KR
Para utilizar una codificación concreta, debe tener instalado el soporte correspondiente. Por ejemplo, para utilizar la
codificación GB18030 en un equipo con Windows 2000 Server, deberá descargar e instalar el paquete de soporte GB18030.
Vea la documentación del sistema para ver información detallada. Cuando utilice el modificador de codificación, todos los
archivos del proyecto deberán tener la misma codificación.
Si está utilizando un sistema de codificación incompatible con JLCA, es posible que pierda los caracteres que no se pueda
convertir. En algunos casos, puede perderse algún archivo.
Vea también
Conceptos
Cambiar codificación de respuesta
Referencia del Ayudante para la conversión del lenguaje Java
/ProjectType Especifica el tipo de proyecto. Las opciones son EXE, WinExe, Library y ASP.NET. El valor predeterminado es
WinExe.
/ContextPath Especifica la ruta de acceso del contexto que se va a reemplazar por la raíz virtual.
/JDK Especifica la biblioteca JDK que se va a utilizar para la conversión. Las opciones son VJ y J2EE.
En ambos casos, el parámetro charset es una cadena que representa la codificación de la solicitud que se desea descodificar.
En .NET Framework, este código es innecesario porque ASP.NET realiza automáticamente la descodificación con los
parámetros establecidos en el archivo Web.xml, como se muestra en el siguiente ejemplo.
Ejemplo
<globalization requestEncoding="euc-jp" responseEncoding="euc-jp"/>
Cuando se convierten las aplicaciones Web, se puede quitar el código de Java convertido que realiza esta función porque ya no
es necesario.
Vea también
Otros recursos
Convertir aplicaciones Web
Referencia del Ayudante para la conversión del lenguaje Java
Vea también
Otros recursos
Convertir aplicaciones Web
Referencia del Ayudante para la conversión del lenguaje Java
Sustitución de vínculos
El Ayudante para la conversión del lenguaje Java sustituye todos los vínculos para que funcionen con la estructura de
directorios convertida. En esta sección se supone que la estructura de directorios está definida en
Diferencias en la estructura de directorios en aplicaciones Web.
Las direcciones URL y cómo cambiarlas
Existen básicamente tres tipos de direcciones URL:
Direcciones URL absolutas con información de dominio
http://www.example.com/servlet/pack1/Servlet1
http://www.example.com/page.jsp
/servlet/pack1/Servlet1
/directory/page2.jsp
pack1.Servlet1
page3.jsp
La dirección URL que utiliza un cliente para el acceso a una aplicación Web tiene el formato siguiente:
http://hoststring/ContextPath/resource
Si el vínculo contiene el token de servlet y el nombre completo de un servlet, el token de token se elimina y los puntos (.) del
nombre completo se cambian por barras inclinadas (/). Si el vínculo al servlet es relativo, la referencia se modifica de modo
que incluya VROOT y la estructura de directorios del servlet convertida.
Ejemplo
Dirección URL original
http://hoststring/ContextPath/servlet/com.ais.servlets.Servlet1
com.ais.servlets.Servlet1
Si el token de servlet va seguido por un nombre de servlet que se encuentra en el archivo Web.xml, se inserta en el vínculo el
nombre completo del servlet.
Ejemplo
XML original
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.ais.servlets.Servlet1</servlet-class>
</servlet>
Si el nombre de la aplicación Web va seguido de un patrón definido en la asignación del servlet del archivo Web.xml, se
determina entonces el nombre del servlet y se inserta en el vínculo. El patrón puede contener caracteres comodín (*).
Ejemplo
XML original
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.ais.servlets.Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/*.asp</url-pattern>
</servlet-mapping>
El Ayudante para la conversión de lenguaje Java no convierte los vínculos que se calculan en tiempo de ejecución. En su lugar,
debe cambiar el código manualmente para generar los vínculos ASP.NET adecuados. Esto se aplica a los casos siguientes:
Vínculos con las expresiones <%=%>, jsp:forward, jsp:include o jsp:execute y con las etiquetas HTML <a href> y <form
action>, donde el valor del parámetro de dirección URL se calcula en tiempo de ejecución.
Cualquier método javax.servlet cuyos parámetros representen una ruta de acceso a un recurso Web, por ejemplo, el
método Response.redirect donde se calcula el valor del parámetro de dirección URL en tiempo de ejecución.
Ejemplo
Código original en lenguaje Java
<jsp:include page="<%=value%>">
Vea también
Conceptos
Diferencias en la estructura de directorios en aplicaciones Web
Otros recursos
Convertir aplicaciones Web
Referencia del Ayudante para la conversión del lenguaje Java
JSP original
<%taglib uri="/MYTEST" prefix="myTag"%>
Vea también
Otros recursos
Convertir aplicaciones Web
Referencia del Ayudante para la conversión del lenguaje Java
Tag WCBase
IterationTag WCIterationBase
BodyTag WCBodyBase
BodyTagSupport WCBodyImpl
TagSupport WCIterationImpl
Vea también
Otros recursos
Convertir aplicaciones Web
Referencia del Ayudante para la conversión del lenguaje Java
El ejemplo de código siguiente muestra cómo utilizar el constructor de la clase System.Web.UI.WebControls.WebControl para
crear un elemento TextArea de HTML y que aparezca en una página de formularios Web Forms:
<font face="Courier New" size="2" color="#000080">
<%@ Page Language="C#" %>
<html>
<head>
<script runat="server">
void Button1_Click(Object sender, EventArgs e)
{
WebControl wc = new WebControl(HtmlTextWriterTag.Textarea);
PlaceHolder1.Controls.Add(wc);
}
</script>
</head>
<body>
<form runat="server">
<h3>WebControl Constructor Example</h3>
<p>
<asp:PlaceHolder id="PlaceHolder1" runat="Server" />
<br>
<asp:Button id="Button1" Text="Click to create a new TextArea" OnClick="Button1_Click" runa
t="Server" />
<p>
</form>
</body>
</html>
Utilice el método WriteBeginTag para escribir cualquier espaciado de tabulación y la etiqueta de apertura del elemento HTML
especificado en la secuencia de salida HtmlTextWriter.
Este método no escribe el carácter de cierre (>) de la etiqueta HTML para que se puedan agregar atributos HTML al elemento.
Utilice la constante TagRightChar para cerrar la etiqueta. Utilice WriteBeginTag con la constante SelfClosingTagEnd cuando
escriba elementos HTML de autocierre.
Este método lo utilizan los controles de servidor personalizados que no permiten la asignación de atributos o etiquetas y que
representan los elementos HTML de la misma manera para cada solicitud.
HtmlTextWriterTag myTag;
myTag = HtmlTextWriterTag.Area;
Vea también
Referencia
System.Web
HtmlTextWriter
WebControl
Referencia del Ayudante para la conversión del lenguaje Java
Supports Supported
Required Required
RequiresNew RequiresNew
Durante la conversión, el Ayudante para la conversión del lenguaje Java intenta determinar el atributo de transacción de .NET
Framework que es más representativo para un componente, basándose en los atributos de transacción especificados en el
descriptor de implementación de EJB y en el número de veces que se asocia cada uno con un método de EJB. Si el atributo de
transacción de EJB que se especifica para un método no es equivalente al atributo de transacción de .NET Framework
seleccionado para el componente, se genera una advertencia en el código Visual C#. Busque estos mensajes de advertencia.
Configuración de seguridad
Mediante programación o a través del explorador de Servicios de componentes, se debe establecer la configuración de
seguridad de .NET Framework siguiente:
Autorización
Nivel de seguridad
Nivel de autenticación
Nivel de representación
Es necesario habilitar Authorization para realizar comprobaciones de seguridad. Establezca las propiedades de clase
System.EnterpriseServices.ApplicationAccessControlAttribute para habilitar la comprobación de seguridad. Estas propiedades
se utilizan para configurar el resto de los valores (seguridad, autenticación y niveles de representación).
Se puede forzar Security en el nivel de proceso, o en el nivel de proceso y de componente. La enumeración
System.EnterpriseServices.AccessChecksLevelOption define las opciones siguientes:
Application
ApplicationComponent
Cuando las comprobaciones de seguridad sólo se realizan en el nivel de proceso, los valores de seguridad basada en funciones
se omiten y se deshabilitan en los niveles de interfaz, componente y método. Establezca las aplicaciones convertidas en el nivel
de seguridad ApplicationComponent.
El nivel de Authentication controla la manera en que se autentican las identidades de usuario respecto de una aplicación de
.NET Framework. Utilice uno de los siguientes valores de la enumeración System.EnterpriseServices.AuthenticationOption:
System.EnterpriseServices.AuthenticationOption.None
Connect
Call
Packet
Integrity
Privacy
El nivel de autenticación predeterminado es Packet. En este nivel se autentica cada paquete que viene de un usuario.
Establezca las aplicaciones convertidas en el nivel de autenticación Packet.
Impersonation hace referencia a cómo se difunde la identidad de seguridad de un cliente cuando obtiene acceso a otra
aplicación o a los recursos protegidos de la aplicación original. Así, un servidor puede suplantar a un cliente hasta cierto punto.
La enumeración System.EnterpriseServices.ImpersonationLevelOption proporciona las opciones siguientes:
Anonymous
Default
Delegate
Identify
Impersonate
El nivel de representación predeterminado para las aplicaciones de .NET Framework es Impersonate. Este nivel permite que
un servidor actúe como el cliente. Sin embargo, el servidor no podrá obtener acceso en nombre del cliente a los objetos o
recursos ubicados en otros equipos. Establezca las aplicaciones convertidas en el nivel Impersonate.
Problemas
JLCA convierte proyectos de EJB en aplicaciones COM. Si la carpeta del archivo de origen de EJB contiene un archivo JAR y un
archivo Ejb-jar.xml de descriptor de implementación, en el proyecto convertido se generan dos aplicaciones porque también se
analiza el descriptor de implementación que incluye el archivo JAR.
Al convertir un EJB, se realiza un intento para asignar un atributo de transacción de .NET a su componente con servicio. Si
globalmente se asignan atributos de transacción diferentes a las interfaces locales y remotas de un EJB, no se asignará ningún
atributo de transacción de .NET. Tampoco se asignará ningún atributo de transacción de .NET cuando se haya asignado
globalmente un atributo de transacción a una interfaz y la otra interfaz tenga asignados únicamente métodos específicos. Las
asignaciones de atributos de transacción de métodos específicos sólo se utilizarán para determinar el atributo de transacción
de .NET en el caso de que no existan asignaciones globales de atributos de transacción. Dado que los componentes con
servicio de .NET controlan los atributos de transacción de manera diferente a como lo hace el lenguaje Java, revise los valores y
realice cualquier ajuste necesario.
Durante la conversión se agrega la comprobación de seguridad predeterminada, lo que quizás no sea necesario en su
proyecto. Si su código fuente de Java establece o excluye unos métodos específicos para las funciones de seguridad, revise los
valores después de la conversión.
Vea también
Referencia
System.EnterpriseServices
Referencia del Ayudante para la conversión del lenguaje Java
Cuestiones de seguridad
En .NET Framework, el nivel de seguridad predeterminado para la comunicación distribuida (interacción remota) es low. Esto
afecta al paso del tipo de objeto definido por el usuario a los métodos remotos. Para obtener más información, vea
Cómo: Establecer el nivel de seguridad para servicios remotos.
Vea también
Referencia
System.Runtime.Remoting
Conceptos
Conversión de aplicaciones que utilizan JNDI
Referencia del Ayudante para la conversión del lenguaje Java
El ejemplo siguiente muestra cómo utilizar una dirección URL de Microsoft SQL Server:
Código de Visual J++ original
String dbUrl = "jdbc:microsoft:sqlserver://MySQLServer:1433; DatabaseName=pubs";
Connection c = "DriverManager.getConnection(dbUrl, username, pwd);
Los conjuntos de resultados actualizables y desplazables no se convierten de forma fiable. Aunque se proporciona una clase de
soporte, será necesario algún ajuste manual. Si su aplicación depende en gran medida de dichos conjuntos de resultados,
utilice la clase System.Data.DataView o System.Data.DataTable, en lugar de la clase System.Data.OleDb.OleDbDataReader, a la
que se convierten automáticamente.
Los tipos de datos Clob y Blob se convierten en matrices de caracteres y bytes, respectivamente, que tienen un
comportamiento diferente y pueden utilizar más memoria. El código convertido obtiene los datos secuencialmente y crea la
matriz. Es recomendable escribir la secuencia de datos en un archivo de disco. También se puede utilizar la clase
System.Data.OracleClient.OracleLob, utilizada para representar el tipo de datos Large Object Binary en un servidor de Oracle.
Algunos tipos de datos nuevos como STRUCT, ARRAY o los tipos definidos por el usuario no se admiten en .NET Framework.
La clase System.Data.OracleClient.OracleBFile administrada funciona con el tipo de datos BFile de Oracle.
Los tipos de datos de acceso son específicos del tipo de base de datos. Todo el código JDBC se convierte en tipos OLEDB
porque los controladores OLEDB están disponibles para la mayoría de las bases de datos. En algunos casos, es recomendable
cambiar esto después de la conversión para obtener mejor rendimiento o compatibilidad. Otros adaptadores de datos
disponibles en .NET Framework son ODBC, SQL y Oracle.
No se asignan DataSources; sin embargo, en algunos casos OleDbConnection o cualquier otra clase de conexión de cliente
bajo el espacio de nombres System.Data puede utilizarse para representar parte de la funcionalidad. Las funciones de registro
de la interfaz javax.sql.DataSource pueden implementarse mediante la clase System.Diagnostics.EventLog.
El paquete javax.sql no se convierte de forma fiable. Las interfaces en ese paquete deben ser implementadas por
controladores de otros fabricantes.
La interfaz Driver y la clase DriverManager han quedado en desuso, por lo que ya no son necesarias. Algunos de sus
métodos pueden convertirse, pero son innecesarios.
Vea también
Referencia
System.Data.OleDb
System.Data.SqlClient
System.Data.Odbc
DataAdapter
DataTable
OleDbDataReader
Conceptos
Descripción de agrupación de conexiones
Uso de agrupación de conexiones
Referencia del Ayudante para la conversión del lenguaje Java
Ejemplos de javax.swing
El siguiente ejemplo muestra cómo utilizar los extensores para proporcionar propiedades a los controles mediante la interfaz
System.ComponentModel.IExtenderProvider:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Globalization;
namespace Extenders
{
[ProvideProperty("MyString", typeof(Control))]
public class UserControl1 : System.Windows.Forms.UserControl, IExtenderProvider
{
private System.ComponentModel.Container components = null;
public UserControl1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
private void InitializeComponent()
{
this.Name = "UserControl1";
this.Size = new System.Drawing.Size(170, 160);
}
#endregion
[Browsable(true)]
public String GetMyString(Control control)
{
return "This is my string.";
}
public void SetMyString(Control container, String value)
{
}
public bool CanExtend(Object control)
{
return true;
}
}
}
El siguiente ejemplo muestra cómo implementar el control y generación de eventos definidos por el usuario:
namespace EventSample
{
using System;
using System.ComponentModel;
//Class that contains the data for
//the alarm event. Derives from System.EventArgs.
public class AlarmEventArgs : EventArgs
{
private readonly bool snoozePressed;
private readonly int nrings;
public AlarmEventArgs(bool snoozePressed, int nrings)
{
this.snoozePressed = snoozePressed;
this.nrings = nrings;
}
//The NumRings property returns the number of rings
//that the alarm clock has sounded when the alarm event
//is generated.
public int NumRings
{
get { return nrings;
}
}
//The SnoozePressed property indicates whether the snooze
//button is pressed on the alarm when the alarm event is generated.
public bool SnoozePressed
{
get {return snoozePressed;}
}
//The AlarmText property that contains the wake-up message.
public string AlarmText
{
get
{
if (snoozePressed)
{
return ("Wake up! Snooze time is over.");
}
else
{
return ("Wake Up!");
}
}
}
}
//Delegate declaration.
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
//The Alarm class that raises the alarm event.
public class AlarmClock
{
private bool snoozePressed = false;
private int nrings = 0;
private bool stop = false;
//The Stop property indicates whether the
//alarm should be turned off.
public bool Stop
{
get {return stop;}
set {stop = value;}
}
//The SnoozePressed property indicates whether the snooze
//button is pressed on the alarm when the alarm event is
//generated.
public bool SnoozePressed
{
get {return snoozePressed;}
set {snoozePressed = value;}
}
//The event member that is of type AlarmEventHandler.
public event AlarmEventHandler Alarm;
//The protected OnAlarm method raises the event by invoking
//the delegates. The sender is always this, the current instance
//of the class.
protected virtual void OnAlarm(AlarmEventArgs e)
{
if (Alarm != null)
{
//Invokes the delegates.
Alarm(this, e);
}
}
//This alarm clock does not have
//a user interface.
//To simulate the alarm mechanism, it has a loop
//that raises the alarm event at every iteration
//with a time delay of 300 milliseconds,
//if snooze is not pressed. If snooze is pressed,
//the time delay is 1000 milliseconds.
public void Start()
{
for (;;)
{
nrings++;
if (stop)
{
break;
}
else if (snoozePressed)
{
System.Threading.Thread.Sleep(1000);
{
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
else
{
System.Threading.Thread.Sleep(300);
AlarmEventArgs e = new AlarmEventArgs(snoozePressed, nrings);
OnAlarm(e);
}
}
}
}
//The WakeMeUp class that has a method AlarmRang that handles the
//alarm event.
public class WakeMeUp
{
public void AlarmRang(object sender, AlarmEventArgs e)
{
Console.WriteLine(e.AlarmText +"\n");
if (!(e.SnoozePressed))
{
if (e.NumRings % 10 == 0)
{
Console.WriteLine("Let alarm ring? Enter Y");
Console.WriteLine(" Press Snooze? Enter N");
Console.WriteLine(" Stop Alarm? Enter Q");
String input = Console.ReadLine();
if (input.Equals("Y") ||input.Equals("y")) return;
else if (input.Equals("N") || input.Equals("n"))
{
((AlarmClock)sender).SnoozePressed = true;
return;
}
else
{
((AlarmClock)sender).Stop = true;
return;
}
}
}
else
{
Console.WriteLine(" Let alarm ring? Enter Y");
Console.WriteLine(" Stop alarm? Enter Q");
String input = Console.ReadLine();
if (input.Equals("Y") || input.Equals("y")) return;
else
{
((AlarmClock)sender).Stop = true;
return;
}
}
}
}
//The driver class that hooks up the event handling method of
//WakeMeUp to the alarm event of an Alarm object using a delegate.
//In a forms-based application, the driver class is the
//form.
public class AlarmDriver
{
public static void Main (string[] args)
{
//Instantiates the event receiver.
WakeMeUp w= new WakeMeUp();
//Instantiates the event source.
AlarmClock clock = new AlarmClock();
//Connects the AlarmRang method to the Alarm event.
clock.Alarm += new AlarmEventHandler(w.AlarmRang);
clock.Start();
}
}
}
El siguiente ejemplo muestra cómo utilizar la propiedad DataSource de un control para emular características del modelo.
Vea también
Conceptos
Conversión de aplicaciones Java Swing
Mensajes de error del Ayudante para la conversión del lenguaje Java
Ejemplo de com.ms.wfc.data.Connection
com.ms.wfc.data.Connection example
En el siguiente ejemplo se utilizan los métodos de com.ms.wfc.data.Connection:
1. Se agrega una referencia a la biblioteca Microsoft ActiveX Data Objects (ADO) 2.7 (Adodb.dll).
2. Se crea una conexión a la base de datos con el objeto Connection (clase ConnectionClass).
Se llama al método ConnectionClass.Open.
El parámetro Provider indica el proveedor OLE DB de Jet 4, mientras que el parámetro Data Source señala la ubicación
física de la base de datos.
Vea también
Otros recursos
ADO API Reference
Referencia del Ayudante para la conversión del lenguaje Java
El método Main se declara en C# de forma diferent Main() y argumentos de línea de comandos (Guía de programación de C#)
e a la función main en C++. En C#, se pone en may
úsculas y siempre es static. Además, la funcionalid
ad del procesamiento de los argumentos de la línea
de comandos es mucho más sólida en C#.
En C#, los parámetros de los métodos no pueden te Error del compilador CS0241
ner valores predeterminados. Utilice sobrecargas d
e métodos para obtener ese efecto.
Para obtener más información sobre las comparaciones entre palabras clave en C# y en otros lenguajes de programación, vea
Equivalentes del lenguaje. Para obtener información sobre la estructura general de las aplicaciones de C#, vea
Estructura general de un programa de C# (Guía de programación de C#).
Vea también
Conceptos
Guía de programación de C#
Administración de elementos en proyectos
Utilizar el Explorador de soluciones
Desarrollo de aplicaciones con Visual C#
Ejemplos
Cómo crear un cliente de aplicación de consola
Ejemplo de parámetros de la línea de comandos
Vea también
Otros recursos
Escribir aplicaciones con Visual C#
Desarrollo de aplicaciones con Visual C#
Guía de programación de C#
En esta sección se ofrece información detallada sobre las principales características del lenguaje C# y sobre las características
accesibles para C# a través de .NET Framework.
Secciones Idioma
Dentro de un programa de C#
Main() y argumentos de línea de comandos (Guía de programación de C#)
Tipos de datos (Guía de programación de C#)
Matrices (Guía de programación de C#)
Cadenas (Guía de programación de C#)
Instrucciones, expresiones y operadores (Guía de programación de C#)
Objetos, clases y estructuras (Guía de programación de C#)
Propiedades (Guía de programación de C#)
Indizadores (Guía de programación de C#)
Delegados (Guía de programación de C#)
Eventos (Guía de programación de C#)
Genéricos (Guía de programación de C#)
Iteradores (Guía de programación de C#)
Espacios de nombres (Guía de programación de C#)
Tipos que aceptan valores NULL (Guía de programación de C#)
Código no seguro y punteros (Guía de programación de C#)
Comentarios de documentación XML (Guía de programación de C#)
Secciones Plataforma
Dominios de aplicación (Guía de programación de C#)
Ensamblados y Caché de ensamblados global (Guía de programación de C#)
Atributos (Guía de programación de C#)
Clases de colección (Guía de programación de C#)
Excepciones y control de excepciones (Guía de programación de C#)
Interoperabilidad (Guía de programación de C#)
Subprocesamiento (Guía de programación de C#)
Rendimiento (Guía de programación de C#)
Reflexión (Guía de programación de C#)
Archivos DLL de C# (Guía de programación de C#)
Seguridad (Guía de programación de C#)
Vea también
Otros recursos
Referencia de C#
Visual C#
Guía de programación de C#
Dentro de un programa de C#
La sección trata la estructura general de un programa de C# e incluye el ejemplo estándar "Hello, World!".
En esta sección
Hello World, su primer programa (Guía de programación de C#)
Estructura general de un programa de C# (Guía de programación de C#)
Secciones relacionadas
Introducción a Visual C#
Migrar a Visual C#
Guía de programación de C#
Referencia de C#
Ejemplos de Visual C#
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1 Introducción
Vea también
Conceptos
Guía de programación de C#
Guía de programación de C#
Los caracteres // convierten el resto de la línea en un comentario. Un bloque de texto también se puede convertir en
comentario si se coloca entre los caracteres /* y */, por ejemplo:
C#
/* A "Hello World!" program in C#.
This program displays the string "Hello World!" on the screen. */
El método Main
Cualquier programa en C# debe contener un método Main, en el cual se inicia y se termina la ejecución. Este método es donde
se crean objetos y se ejecutan otros métodos.
El método Main es un método estático que reside dentro de una clase o una estructura. En el ejemplo "Hello World!", se
encuentra en una clase denominada Hello. Declare el método Main de una de las maneras siguientes:
Puede devolver void:
C#
static void Main()
{
//...
}
O bien
C#
static int Main(string[] args)
{
//...
return 0;
}
El parámetro del método Main es una matriz de tipo string que representa los argumentos de la línea de comandos utilizados
para llamar al programa. Observe que, a diferencia de C++, esta matriz no incluye el nombre del archivo ejecutable (exe).
Para obtener más información sobre cómo utilizar los argumentos de la línea de comandos, vea el ejemplo de
Main() y argumentos de línea de comandos (Guía de programación de C#) y
Cómo: Crear y utilizar archivos DLL de C# (Guía de programación de C#).
Entrada y salida
Los programas de C# utilizan normalmente los servicios de entrada y salida que ofrece la biblioteca en tiempo de ejecución de
.NET Framework. La instrucción System.Console.WriteLine("Hello World!"); utiliza el método WriteLine, que es uno de los
métodos de salida de la clase Console de la biblioteca en tiempo de ejecución. Muestra el parámetro cadena en la secuencia de
salida estándar seguido por una nueva línea. Otros métodos de Console se utilizan para otras operaciones de entrada y salida.
Si incluye la directiva using System; al principio del programa, puede utilizar directamente las clases y métodos de System sin
escribir el nombre completo. Por ejemplo, puede llamar en su lugar Console.WriteLine, sin especificar
System.Console.Writeline:
C#
using System;
C#
Console.WriteLine("Hello World!");
Para obtener más información sobre métodos de entrada y salida, vea System.IO.
Compilación y ejecución
El programa "Hello World!" se puede compilar creando un proyecto en el Entorno de desarrollo integrado (IDE) de Visual
Studio, o bien mediante la línea de comandos. Utilice el símbolo del sistema de Visual Studio o ejecute vsvars32.bat para
incluir el conjunto de herramientas de Visual C# en la ruta de acceso del símbolo del sistema.
Para compilar el programa desde la línea de comandos:
Cree el archivo de código fuente mediante cualquier editor de texto y guárdelo con un nombre como Hello.cs. Los
archivos de código fuente de C# utilizan la extensión .cs.
Para invocar el compilador, ejecute el comando:
csc Hello.cs
Para obtener más información sobre el compilador de C# y sus opciones, vea Opciones del compilador de C#.
Vea también
Referencia
Dentro de un programa de C#
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Referencia de C#
Guía de programación de C#
struct YourStruct
{
}
interface IYourInterface
{
}
enum YourEnum
{
}
namespace YourNestedNamespace
{
struct YourStruct
{
}
}
class YourMainClass
{
static void Main(string[] args)
{
//Your program starts here...
}
}
}
Secciones relacionadas
Para obtener más información:
Clases (Guía de programación de C#)
Estructuras (Guía de programación de C#)
Espacios de nombres (Guía de programación de C#)
Interfaces (Guía de programación de C#)
Delegados (Guía de programación de C#)
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.2 Estructura del programa
9.1 Unidades de compilación (espacios de nombres)
Vea también
Referencia
Dentro de un programa de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Ejemplos de Visual C#
Guía de programación de C#
Información general
El método Main es el punto de entrada del programa, donde se inicia y finaliza el control.
Se declara dentro de una clase o una estructura. Debe ser estático y no debería ser público. (En el ejemplo anterior, recibe
el acceso predeterminado de privado.)
Puede tener un tipo de valor devuelto void o int.
El método Main se puede declarar con o sin parámetros.
Los parámetros se pueden leer como argumentos de la línea de comandos indizados basados en cero.
A diferencia de C y C++, el nombre del programa no se trata como el primer argumento de la línea de comandos.
En esta sección
Argumentos de línea de comandos (Guía de programación de C#)
Cómo: Mostrar argumentos de línea de comandos (Guía de programación de C#)
Cómo: Obtener acceso a argumentos de línea de comandos mediante Foreach (Guía de programación de C#)
Valores devueltos de Main() (Guía de programación de C#)
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.1 Hello World
Vea también
Referencia
Dentro de un programa de C#
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Guía de programación de C#
C#
static void Main(string[] args)
El parámetro del método Main es una matriz de tipo String que representa los argumentos de la línea de comandos.
Normalmente se utiliza la propiedad Length para comprobar si existen argumentos; por ejemplo:
C#
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
return 1;
}
También se pueden convertir los argumentos de tipo string en tipos numéricos mediante la clase Convert el método Parse.
Por ejemplo, la instrucción siguiente convierte la cadena en un número long utilizando el método Parse en la clase Int64:
Igualmente, es posible usar el método ToInt64 de la clase Convert para lograr el mismo objetivo:
C#
public class Functions
{
public static long Factorial(int n)
{
if (n < 0) { return -1; } //error result - undefined
if (n > 256) { return -2; } //error result - input is too big
if (n == 0) { return 1; }
C#
class MainClass
{
static int Main(string[] args)
{
// Test if input arguments were supplied:
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
System.Console.WriteLine("Usage: Factorial <num>");
return 1;
}
try
{
// Convert the input arguments to numbers:
int num = int.Parse(args[0]);
Resultado
The Factorial of 3 is 6.
Comentarios
A continuación se muestran dos ejecuciones de ejemplo del programa en las que se supone que el nombre del programa es
Factorial.exe.
Ejecución nº 1:
Escriba la siguiente línea de comandos:
Factorial 10
Para obtener más ejemplos sobre cómo utilizar los argumentos de la línea de comandos, vea el ejemplo de
Cómo: Crear y utilizar archivos DLL de C# (Guía de programación de C#).
Vea también
Tareas
Cómo: Mostrar argumentos de línea de comandos (Guía de programación de C#)
Cómo: Obtener acceso a argumentos de línea de comandos mediante Foreach (Guía de programación de C#)
Referencia
Main() y argumentos de línea de comandos (Guía de programación de C#)
Valores devueltos de Main() (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Ejemplo
Este ejemplo muestra los argumentos de la línea de comandos pasados a una aplicación de línea de comandos. El resultado
mostrado es para la primera entrada de la tabla anterior.
C#
class CommandLine
{
static void Main(string[] args)
{
// The Length property provides the number of array elements
System.Console.WriteLine("parameter count = {0}", args.Length);
Resultados
parameter count = 3
Arg[0] = [a]
Arg[1] = [b]
Arg[2] = [c]
Vea también
Tareas
Cómo: Obtener acceso a argumentos de línea de comandos mediante Foreach (Guía de programación de C#)
Referencia
Main() y argumentos de línea de comandos (Guía de programación de C#)
Valores devueltos de Main() (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
C#
class CommandLine2
{
static void Main(string[] args)
{
System.Console.WriteLine("Number of command line parameters = {0}", args.Length);
Resultados
Number of command line parameters = 3
John
Paul
Mary
Vea también
Tareas
Cómo: Mostrar argumentos de línea de comandos (Guía de programación de C#)
Referencia
foreach, in (Referencia de C#)
Main() y argumentos de línea de comandos (Guía de programación de C#)
Valores devueltos de Main() (Guía de programación de C#)
Array
System.Collections
Conceptos
Guía de programación de C#
Guía de programación de C#
Si no se va a utilizar el valor que devuelve el método Main, entonces devolver void permite crear un código un poco más
simple. Sin embargo, devolver un entero permite que el programa relacione información de estado con otros programas o
secuencias de comandos que invocan al ejecutable. En el ejemplo siguiente se muestra cómo utilizar el valor que devuelve
Main.
Ejemplo
En este ejemplo, se utiliza un archivo de proceso por lotes para ejecutar un programa y probar el valor que devuelve la función
Main. Cuando un programa se ejecuta en Windows, cualquier valor que devuelva la función Main se almacena en una variable
de entorno denominada ERRORLEVEL. Al inspeccionar la variable ERRORLEVEL, los archivos de proceso por lotes pueden
determinar en consecuencia el resultado de la ejecución. Tradicionalmente, un valor devuelto de cero indica una ejecución
correcta. El programa que se muestra a continuación es un programa muy simple que devuelve un valor de cero desde la
función Main.
C#
class MainReturnValTest
{
static int Main()
{
//...
return 0;
}
}
Dado que este ejemplo utiliza un archivo de proceso por lotes, es mejor compilar el código desde la línea de comandos, como
se muestra en Cómo: Establecer variables de entorno.
Luego, se utiliza un archivo de proceso por lotes para invocar al ejecutable que resulta del ejemplo de código anterior. Puesto
que el código devuelve un valor de cero, el archivo de proceso por lotes creará un informe de operación correcta, pero si el
código anterior se cambia para que devuelva un valor distinto de cero y luego se vuelve a compilar, la ejecución posterior del
archivo de proceso por lotes indicará un error.
rem test.bat
@echo off
MainReturnValueTest
@if "%ERRORLEVEL%" == "0" goto good
:fail
echo Execution Failed
echo return value = %ERRORLEVEL%
goto end
:good
echo Execution Succeded
echo return value = %ERRORLEVEL%
goto end
:end
Vea también
Tareas
Cómo: Mostrar argumentos de línea de comandos (Guía de programación de C#)
Cómo: Obtener acceso a argumentos de línea de comandos mediante Foreach (Guía de programación de C#)
Referencia
Main() y argumentos de línea de comandos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Guía de programación de C#
Una conversión de tipos invoca de forma explícita al operador de conversión de un tipo a otro. En la conversión de tipos se
producirá un error si no se ha definido ninguno de estos operadores. Puede escribir operadores de conversión personalizados
para convertir entre los tipos definidos por el usuario. Para obtener más información sobre la definición de un operador de
conversión, vea explicit (Referencia de C#) e implicit (Referencia de C#).
Ejemplo
El siguiente programa convierte explícitamente un tipo double en un tipo int. El programa no se compilará sin el operador de
conversión de tipo.
C#
class Test
{
static void Main()
{
double x = 1234.7;
int a;
a = (int)x; // cast double to int
System.Console.WriteLine(a);
}
}
Resultado
1234
Rendimiento
Con relación a las asignaciones simples, las conversiones boxing y unboxing son procesos que consumen muchos recursos.
Cuando se aplica la conversión boxing a un tipo de valor, se debe asignar y construir un objeto completamente nuevo. En
menor grado, la conversión de tipos requerida para aplicar la conversión unboxing también es costosa. Para obtener más
información, vea Rendimiento (Guía de programación de C#).
Secciones relacionadas
Para obtener más información:
Conversión Boxing
Conversión Unboxing
Tipos de referencia
Tipos de valor
El resultado de esta instrucción es crear una referencia de objeto o en la pila que hace referencia a un valor del tipo int en el
montón. Este valor es una copia del valor del tipo de valor asignado a la variable i. La diferencia entre las dos variables, i y o,
se muestra en la siguiente ilustración.
Conversión Boxing
También es posible realizar la conversión boxing de manera explícita, tal como se muestra en el ejemplo siguiente, pero ésta
nunca es necesaria:
C#
int i = 123;
object o = (object)i; // explicit boxing
Ejemplo
Este ejemplo convierte una variable de entero i a un objeto o mediante conversión boxing. A continuación, el valor
almacenado en la variable i se cambia de 123 a 456. El ejemplo muestra que el tipo de valor original y el objeto empaquetado
usan ubicaciones de memoria independientes y, por consiguiente, pueden almacenar valores diferentes.
C#
class TestBoxing
{
static void Main()
{
int i = 123;
object o = i; // implicit boxing
i = 456; // change the contents of i
Resultados
The value-type value = 456
The object-type value = 123
Para que la conversión Unboxing de tipos de valores sea correcta en tiempo de ejecución, el elemento al que se aplica debe ser
una referencia a un objeto creado previamente mediante la conversión Boxing de una instancia de dicho tipo de valor. Si se
intenta aplicar la conversión unboxing a null o a una referencia a un tipo de valor incompatible, producirá una excepción
InvalidCastException.
Ejemplo
El ejemplo siguiente muestra un caso de conversión unboxing no válida y la excepción InvalidCastExceptionresultante. Si se
utiliza try y catch, se muestra un mensaje de error cuando se produce el error.
C#
class TestUnboxing
{
static void Main()
{
int i = 123;
object o = i; // implicit boxing
try
{
int j = (short)o; // attempt to unbox
System.Console.WriteLine("Unboxing OK.");
}
catch (System.InvalidCastException e)
{
System.Console.WriteLine("{0} Error: Incorrect unboxing.", e.Message);
}
}
}
Resultado
Specified cast is not valid. Error: Incorrect unboxing.
Si cambia la instrucción:
int j = (short) o;
a:
int j = (int) o;
Vea también
Conceptos
Guía de programación de C#
Conversión boxing y unboxing (Guía de programación de C#)
Conversión boxing (Guía de programación de C#)
Guía de programación de C#
// Alternative syntax
int[] array3 = { 1, 2, 3, 4, 5, 6 };
// Set the values of the first array in the jagged array structure
jaggedArray[0] = new int[4] { 1, 2, 3, 4 };
}
}
La clase System.Array proporciona muchos otros métodos y propiedades útiles para ordenar, buscar y copiar matrices.
Ejemplo
En este ejemplo se utiliza la propiedad Rank para mostrar el número de dimensiones de una matriz.
C#
class TestArraysClass
{
static void Main()
{
// Declare and initialize an array:
int[,] theArray = new int[5, 10];
System.Console.WriteLine("The array has {0} dimensions.", theArray.Rank);
}
}
Resultado
The array has 2 dimensions.
Vea también
Referencia
Matrices unidimensionales (Guía de programación de C#)
Matrices multidimensionales (Guía de programación de C#)
Matrices escalonadas (Guía de programación de C#)
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Guía de programación de C#
Esta matriz contiene elementos desde array[0] hasta array[4]. El operador new se utiliza para crear la matriz e inicializar sus
elementos con valores predeterminados. En este ejemplo, todos los elementos de la matriz se inicializan con cero.
Una matriz que almacena elementos de cadena se puede declarar del mismo modo. Por ejemplo:
C#
string[] stringArray = new string[6];
Inicialización de matrices
Es posible inicializar una matriz en el momento de su declaración, en cuyo caso, no es necesario el especificador de rango ya
que éste viene dado por el número de elementos de la lista de inicialización. Por ejemplo:
C#
int[] array1 = new int[5] { 1, 3, 5, 7, 9 };
Una matriz de cadena se puede inicializar del mismo modo. A continuación, se muestra una declaración de una matriz de
cadena en la que cada elemento de la matriz se inicializa con el nombre de un día de la semana:
C#
string[] weekDays = new string[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
Cuando se inicializa una matriz en el momento de su declaración, se pueden utilizar los siguientes métodos abreviados:
C#
int[] array2 = { 1, 3, 5, 7, 9 };
string[] weekDays2 = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
Es posible declarar una variable de matriz sin inicializarla, pero se debe utilizar el operador new al asignar una matriz a esta
variable. Por ejemplo:
C#
int[] array3;
array3 = new int[] { 1, 3, 5, 7, 9 }; // OK
//array3 = {1, 3, 5, 7, 9}; // Error
El resultado de esta instrucción depende de si SomeType es un tipo de valor o un tipo de referencia. Si es un tipo de valor, la
instrucción genera una matriz de 10 instancias del tipo SomeType. Si SomeType es un tipo de referencia, la instrucción crea una
matriz de 10 elementos, cada uno de los cuales se inicializa con una referencia nula.
Para obtener más información sobre los tipos de valor y los tipos de referencia, vea Tipos (Referencia de C#).
Vea también
Referencia
Matrices multidimensionales (Guía de programación de C#)
Matrices escalonadas (Guía de programación de C#)
Array
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Guía de programación de C#
Inicialización de matrices
La matriz se puede inicializar en la declaración como se muestra en el ejemplo siguiente:
C#
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
int[, ,] array3D = new int[,,] { { { 1, 2, 3 } }, { { 4, 5, 6 } } };
Si opta por declarar una variable de matriz sin inicializarla, deberá utilizar el operador new para asignar una matriz a la
variable. Por ejemplo:
C#
int[,] array5;
array5 = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // OK
//array5 = {{1,2}, {3,4}, {5,6}, {7,8}}; // Error
El ejemplo de código siguiente inicializa las variables de matriz con el valor predeterminado (salvo las matrices escalonadas):
C#
int[,] array6 = new int[10, 10];
Vea también
Referencia
Matrices unidimensionales (Guía de programación de C#)
Matrices escalonadas (Guía de programación de C#)
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Guía de programación de C#
Para poder utilizar jaggedArray, se deben inicializar sus elementos. Los elementos se pueden inicializar de la siguiente manera:
C#
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[4];
jaggedArray[2] = new int[2];
Cada elemento es una matriz unidimensional de enteros. El primer elemento es una matriz de 5 enteros, el segundo es una
matriz de 4 enteros y el tercero es una matriz de 2 enteros.
También se pueden utilizar inicializadores para rellenar los elementos de la matriz con valores, en cuyo caso no es necesario
especificar el tamaño de la matriz: Por ejemplo:
C#
jaggedArray[0] = new int[] { 1, 3, 5, 7, 9 };
jaggedArray[1] = new int[] { 0, 2, 4, 6 };
jaggedArray[2] = new int[] { 11, 22 };
Puede utilizar el formulario abreviado siguiente. Observe que no se puede omitir el operador new de la inicialización de
elementos ya que no existe una inicialización predeterminada para los elementos:
C#
int[][] jaggedArray3 =
{
new int[] {1,3,5,7,9},
new int[] {0,2,4,6},
new int[] {11,22}
};
Una matriz escalonada es una matriz de matrices y por consiguiente sus elementos son tipos de referencia y se inicializan en
null.
El acceso a elementos individuales de la matriz se realiza como en los siguientes ejemplos:
C#
// Assign 77 to the second element ([1]) of the first array ([0]):
jaggedArray3[0][1] = 77;
Es posible combinar matrices multidimensionales con matrices escalonadas. A continuación, se muestra la declaración e
inicialización de una matriz escalonada unidimensional que contiene dos elementos de matriz bidimensionales de diferentes
tamaños:
C#
int[][,] jaggedArray4 = new int[3][,]
{
new int[,] { {1,3}, {5,7} },
new int[,] { {0,2}, {4,6}, {8,10} },
new int[,] { {11,22}, {99,88}, {0,9} }
};
Puede obtener acceso a los elementos individuales como se indica en este ejemplo, que muestra el valor del elemento [1,0]
de la primera matriz (valor 5):
C#
System.Console.Write("{0}", jaggedArray4[0][1, 0]);
El método Length devuelve el número de matrices contenido en la matriz escalonada. Por ejemplo, suponiendo que ha
declarado la matriz anterior, esta línea:
C#
System.Console.WriteLine(jaggedArray4.Length);
devolverá un valor de 3.
Ejemplo
En este ejemplo, se genera una matriz cuyos elementos son también matrices. Cada uno de los elementos de la matriz tiene un
tamaño diferente.
C#
class ArrayTest
{
static void Main()
{
// Declare the array of two elements:
int[][] arr = new int[2][];
Resultados
Element(0): 1 3 5 7 9
Element(1): 2 4 6 8
Vea también
Referencia
Matrices unidimensionales (Guía de programación de C#)
Matrices multidimensionales (Guía de programación de C#)
Array
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Guía de programación de C#
Con matrices multidimensionales, se puede utilizar el mismo método para recorrer los elementos, por ejemplo:
C#
int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } };
foreach (int i in numbers2D)
{
System.Console.Write("{0} ", i);
}
Sin embargo, con matrices multidimensionales, utilizar un bucle for anidado proporciona más control sobre los elementos de
la matriz.
Vea también
Referencia
Matrices unidimensionales (Guía de programación de C#)
Matrices multidimensionales (Guía de programación de C#)
Matrices escalonadas (Guía de programación de C#)
Array
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Guía de programación de C#
Asimismo, es posible inicializar y pasar una matriz en una sola operación. Por ejemplo:
C#
PrintArray(new int[] { 1, 3, 5, 7, 9 });
Ejemplo 1
En el siguiente ejemplo, una matriz de cadena se inicializa y se pasa como parámetro al método PrintArray, el cual muestra
los elementos de la matriz:
C#
class ArrayClass
{
static void PrintArray(string[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
System.Console.Write(arr[i] + "{0}", i < arr.Length - 1 ? " " : "");
}
System.Console.WriteLine();
}
Resultado 1
Sun Mon Tue Wed Thu Fri Sat
Asimismo, es posible inicializar y pasar una matriz en una sola operación. Por ejemplo:
C#
PrintArray(new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } });
Ejemplo 2
En el siguiente ejemplo, una matriz bidimensional de cadena se inicializa y se pasa como parámetro al método PrintArray, el
cual muestra los elementos de la matriz:
C#
class ArrayClass2D
{
static void PrintArray(int[,] arr)
{
// Display the array elements:
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 2; j++)
{
System.Console.WriteLine("Element({0},{1})={2}", i, j, arr[i, j]);
}
}
}
static void Main()
{
// Pass the array as a parameter:
PrintArray(new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } });
}
}
Resultado 2
Element(0,0)=1
Element(0,1)=2
Element(1,0)=3
Element(1,1)=4
Element(2,0)=5
Element(2,1)=6
Element(3,0)=7
Element(3,1)=8
Vea también
Referencia
Matrices unidimensionales (Guía de programación de C#)
Matrices multidimensionales (Guía de programación de C#)
Matrices escalonadas (Guía de programación de C#)
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Guía de programación de C#
Al igual que todos los parámetros ref, un parámetro ref de tipo de matriz debe asignarlo el llamador. Por consiguiente, no es
necesario que lo asigne el destinatario. Un parámetro ref de un tipo de matriz puede cambiar como resultado de la llamada.
Por ejemplo, a la matriz se le puede asignar el valor null o se puede inicializar con otra matriz. Por ejemplo:
C#
static void TestMethod2(ref int[] arr)
{
arr = new int[10]; // arr initialized to a different array
}
Los dos ejemplos siguientes muestran la diferencia entre out y ref cuando se utilizan para pasar matrices a métodos.
Ejemplo 1
En este ejemplo, la matriz theArray se declara en el llamador (el método Main) y se inicializa en el método FillArray. A
continuación, los elementos de la matriz se devuelven al método que realizó la llamada y se muestran.
C#
class TestOut
{
static void FillArray(out int[] arr)
{
// Initialize the array:
arr = new int[5] { 1, 2, 3, 4, 5 };
}
Resultado 1
Array elements are:
1 2 3 4 5
Ejemplo 2
En este ejemplo, la matriz theArray se inicializa en el llamador (el método Main) y se pasa al método FillArray mediante el
parámetro ref. Algunos de los elementos de la matriz se actualizan en el método FillArray. A continuación, los elementos de
la matriz se devuelven al método que realizó la llamada y se muestran.
C#
class TestRef
{
static void FillArray(ref int[] arr)
{
// Create the array on demand:
if (arr == null)
{
arr = new int[10];
}
// Fill the array:
arr[0] = 1111;
arr[4] = 5555;
}
Resultado 2
Array elements are:
1111 2 3 4 5555
Vea también
Referencia
Matrices unidimensionales (Guía de programación de C#)
Matrices multidimensionales (Guía de programación de C#)
Matrices escalonadas (Guía de programación de C#)
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Guía de programación de C#
s1 += s2;
System.Console.WriteLine(s1); // outputs "orangered"
s1 = s1.Substring(2, 5);
System.Console.WriteLine(s1); // outputs "anger"
Los objetos de cadena son inmutables, lo que significa que no se pueden cambiar una vez creados. Los métodos que actúan
sobre las cadenas, devuelven los nuevos objetos de cadena. En el ejemplo anterior, cuando el contenido de s1 y s2 se
concatenan para formar una sola cadena, las dos cadenas que contienen "orange" y "red" no se modifican. El operador +=
crea una nueva cadena que contiene el contenido combinado. Como resultado, s1 ahora hace referencia a una cadena
totalmente diferente. Todavía existe una cadena que sólo contiene "orange" , pero deja de hacerse referencia a ella cuando se
concatena s1.
Nota
Tenga cuidado cuando cree referencias a cadenas. Si crea una referencia a una cadena y después "modifica" la cadena, la refe
rencia seguirá señalando al objeto original y no al nuevo objeto que se creó cuando se modificó la cadena. Esta situación peli
grosa se ilustra en el código siguiente:
string s1 = "Hello";
string s2 = s1;
s1 += " and goodbye.";
Console.WriteLine(s2); //outputs "Hello"
Dado que las modificaciones en las cadenas implican la creación de nuevos objetos de tipo string, por motivos de rendimiento,
la concatenación de un gran número de cadenas u otro tipo de manipulación de las cadenas debe realizarse con la clase
StringBuilder, como se muestra a continuación:
C#
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("one ");
sb.Append("two ");
sb.Append("three");
string str = sb.ToString();
equivale a:
Hello
World!
Si desea incluir una barra diagonal inversa, ésta debe estar precedida de otra barra diagonal inversa. La cadena siguiente:
C#
string filePath = "\\\\My Documents\\";
equivale a:
\\My Documents\
El símbolo @
El símbolo @ indica al constructor de cadena que debe omitir caracteres de escape y saltos de línea. Las dos cadenas siguientes
son, por consiguiente, idénticas:
C#
string p1 = "\\\\My Documents\\My Files\\";
string p2 = @"\\My Documents\My Files\";
ToString()
Al igual que todos los objetos derivados de Object, las cadenas proporcionan el método ToString, que convierte un valor en
una cadena. Este método se puede utilizar para convertir valores numéricos en cadenas de la siguiente manera:
C#
int year = 1999;
string msg = "Eve was born in " + year.ToString();
System.Console.WriteLine(msg); // outputs "Eve was born in 1999"
También es posible copiar los caracteres en una matriz de caracteres, tal como se muestra a continuación:
C#
string s4 = "Hello, World";
char[] arr = s4.ToCharArray(0, s4.Length);
Comparaciones
La manera más simple de comparar dos cadenas es utilizar los operadores == y !=, que realizan una comparación con
distinción entre mayúsculas y minúsculas.
C#
string color1 = "red";
string color2 = "green";
string color3 = "red";
if (color1 == color3)
{
System.Console.WriteLine("Equal");
}
if (color1 != color2)
{
System.Console.WriteLine("Not equal");
}
Los objetos String también tienen un método CompareTo() que devuelve un valor entero, basado en si una cadena es menor
que (<) o mayor que (>) otra. Al comparar las cadenas, se utiliza el valor Unicode, y las minúsculas tienen un valor menor que
las mayúsculas.
C#
string s7 = "ABC";
string s8 = "abc";
if (s7.CompareTo(s8) > 0)
{
System.Console.WriteLine("Greater-than");
}
else
{
System.Console.WriteLine("Less-than");
}
Para buscar una cadena dentro de otra, utilice IndexOf(). IndexOf() devuelve -1 si la cadena de búsqueda no se encuentra; en
caso contrario devuelve el índice de la primera posición de la cadena, con base cero.
C#
string s9 = "Battle of Hastings, 1066";
System.Console.WriteLine(s9.IndexOf("Hastings")); // outputs 10
System.Console.WriteLine(s9.IndexOf("1967")); // outputs -1
Este código genera cada palabra en una línea separada de la siguiente forma:
The
cat
sat
on
the
mat.
string s = "";
Por el contrario, una cadena nula no hace referencia a una instancia de un objeto System.String y cualquier intento de llamar
a un método en una cadena nula produce una excepción NullReferenceException. Sin embargo, puede utilizar cadenas nulas en
operaciones de concatenación y comparación con otras cadenas. Los ejemplos siguientes muestran algunos casos en los que
se hace referencia a una cadena nula y no se produce una excepción:
Utilizar StringBuilder
La clase StringBuilder crea un búfer de cadena que proporciona el mejor rendimiento si el programa realiza una gran
manipulación de cadenas. La cadena StringBuilder también permite reasignar los caracteres individuales, algo que el tipo de
datos de cadena integrado no admite. Por ejemplo, este código cambia el contenido de una cadena sin crear una nueva cadena:
C#
System.Text.StringBuilder sb = new System.Text.StringBuilder("Rat: the ideal pet");
sb[0] = 'C';
System.Console.WriteLine(sb.ToString());
System.Console.ReadLine();
En este ejemplo, se utiliza un objeto StringBuilder para crear una cadena a partir de un conjunto de tipos numéricos:
C#
class TestStringBuilder
{
static void Main()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
// Create a string composed of numbers 0 - 9
for (int i = 0; i < 10; i++)
{
sb.Append(i.ToString());
}
System.Console.WriteLine(sb); // displays 0123456789
Vea también
Tareas
Cómo: Buscar cadenas mediante expresiones regulares (Guía de programación de C#)
Cómo: Buscar cadenas mediante los métodos String (Guía de programación de C#)
Cómo: Analizar cadenas con el método Split (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Analizar cadenas
Guía de programación de C#
Resultados
Original text: 'one two three:four,five six seven'
7 words in text:
one
two
three
four
five
six
seven
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Cadenas (Guía de programación de C#)
Expresiones regulares de .NET Framework
Programación de .NET en C++
Guía de programación de C#
Resultados
'A silly sentence used for silly purposes.'
starts with 'a silly'? False
starts with 'a silly'? True (ignore case)
ends with '.'? True
between two 'silly' words: 'silly sentence used for '
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Cadenas (Guía de programación de C#)
Guía de programación de C#
Resultados
cow over the moon (match for 'cow' found)
Betsy the Cow (match for 'cow' found)
cowering in the corner (match for 'cow' found)
no match here
El código siguiente es una aplicación de consola que utiliza expresiones regulares para validar el formato de cada cadena de
una matriz. La validación requiere que cada cadena tenga la forma de un número de teléfono en el que tres grupos de dígitos
se separan por guiones. Los dos primeros grupos contienen tres dígitos, y el tercero, cuatro. Esto se logra con la expresión
regular ^\\d{3}-\\d{3}-\\d{4}$. Para obtener más información, vea Elementos del lenguaje de expresiones regulares.
C#
class TestRegularExpressionValidation
{
static void Main()
{
string[] numbers =
{
"123-456-7890",
"444-234-22450",
"690-203-6578",
"146-893-232",
"146-839-2322",
"4007-295-1111",
"407-295-1111",
"407-2-5555",
};
if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern))
{
System.Console.WriteLine(" - valid");
}
else
{
System.Console.WriteLine(" - invalid");
}
}
}
}
Resultados
123-456-7890 - valid
444-234-22450 - invalid
690-203-6578 - valid
146-893-232 - invalid
146-839-2322 - valid
4007-295-1111 - invalid
407-295-1111 - valid
407-2-5555 - invalid
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Cadenas (Guía de programación de C#)
Guía de programación de C#
Aunque aparecen cuatro cadenas en el código (las tres cadenas que se combinan y la cadena final que contiene las otras tres),
se crean cinco cadenas en total porque las dos primeras se combinan primero y crean una cadena que contiene "one two". La
tercera se anexa separadamente para formar la cadena final almacenada en str.
Alternativamente, la clase StringBuilder se puede utilizar para agregar cada cadena a un objeto que, a continuación, crea la
cadena final en un paso. Esta estrategia se muestra en el ejemplo siguiente.
Ejemplo
En el código siguiente se utiliza el método Append de la clase StringBuilder para combinar tres cadenas sin el efecto de
encadenamiento del operador +.
C#
class StringBuilderTest
{
static void Main()
{
string two = "two";
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Cadenas (Guía de programación de C#)
Guía de programación de C#
Resultados
The quick brown fox jumped over the fence
The quick brown cat jumped over the fence
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Cadenas (Guía de programación de C#)
Guía de programación de C#
Las instrucciones de C# a menudo contienen expresiones. Una expresión de C# es un fragmento de código que contiene un
valor literal, un nombre simple o un operador y sus operandos. Las expresiones más comunes, cuando se evalúan, producen
un valor literal, una variable, una propiedad de objeto o un acceso a indizador de objeto. Cada vez que se identifica una
variable, propiedad de objeto o acceso a indizador de objeto desde una expresión, el valor de dicho elemento se utiliza como
valor de la expresión. En C#, una expresión puede colocarse en cualquier lugar donde se requiera un valor u objeto, siempre y
cuando la expresión evalúe finalmente el tipo requerido.
Algunas expresiones se evalúan como espacio de nombres, tipo, grupo de métodos o acceso de eventos. Estas expresiones de
propósito especial sólo son válidas en determinados momentos, generalmente como parte de una expresión más grande y
producirán un error del compilador si se utilizan en forma inadecuada.
Secciones relacionadas
Tipos de instrucciones (Referencia de C#)
Expresiones (Guía de programación de C#)
Operadores (Guía de programación de C#)
Especificación del lenguaje C#
Para obtener más información, vea las siguientes secciones de Especificación del lenguaje C#.
1.5 Instrucciones
7 Expresiones
8 Instrucciones
Vea también
Conceptos
Guía de programación de C#
Guía de programación de C#
Para obtener más información sobre literales, vea Tipos (Referencia de C#).
En el ejemplo anterior, tanto i como s son nombres simples que identifican variables locales. Cuando esas variables se utilizan
en una expresión, el valor de la variable se recupera y se utiliza para la expresión. Por ejemplo, en el código siguiente, cuando
se llama a DoWork, el método recibe el valor 5 de forma predeterminada y no es posible tener acceso a la variable var:
C#
int var = 5;
DoWork(var);
Expresiones de invocación
En el ejemplo de código siguiente, la llamada a DoWork es otro tipo de expresión, denominada expresión de invocación.
C#
DoWork(var);
Específicamente, llamar a un método es una expresión de invocación de método. Una invocación de método requiere el
nombre del método, ya sea un nombre como en el ejemplo anterior o el resultado de otra expresión, seguido de paréntesis y
los parámetros del método. Para obtener más información, vea Métodos (Guía de programación de C#). Una invocación de
delegado utiliza el nombre de un delegado y los parámetros de método entre paréntesis. Para obtener más información, vea
Delegados (Guía de programación de C#). Las invocaciones de método e invocaciones de delegado se evalúan como el valor
que devuelve el método, si devuelve alguno. Los métodos que devuelven un valor nulo no se pueden utilizar en lugar de un
valor en una expresión.
Comentarios
Siempre que se identifica un acceso a una variable, propiedad de objeto o indizador de objeto desde una expresión, el valor de
ese elemento se utiliza como valor de la expresión. Una expresión se puede colocar en cualquier parte de C# donde se requiera
un valor u objeto, siempre que la expresión finalmente se evalúe como el tipo requerido.
Vea también
Referencia
Métodos (Guía de programación de C#)
Operadores (Guía de programación de C#)
Tipos de datos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Delegados (Guía de programación de C#)
Guía de programación de C#
La instrucción de C# siguiente contiene dos operadores binarios, cada uno con dos operandos. El operador de asignación, =,
tiene el entero y y la expresión 2 + 3 como operandos. La propia expresión 2 + 3 contiene el operador de suma y utiliza los
valores enteros 2 y 3 como operandos:
C#
y = 2 + 3;
Un operando puede ser una expresión válida de cualquier tamaño, compuesta por una cantidad cualquiera de otras
operaciones.
Los operadores de una expresión se evalúan en un orden concreto conocido como prioridad de operadores. La tabla siguiente
divide a los operadores en categorías basadas en el tipo de operación que realizan. Las categorías se muestran en orden de
prioridad.
Principal x.y, f(x), a[x], x++, x--, new, typeof, checked, unchecked
Aritméticos: multiplicativos *, /, %
Aritméticos: aditivos +, -
Igualdad ==, !=
Asignación =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
Cuando dos operadores con la misma prioridad están presentes en una expresión, se evalúan según su asociatividad. Los
operadores que son asociativos por la izquierda se evalúan en orden de izquierda a derecha. Por ejemplo, x * y / z se evalúa
como (x * y) / z. Los operadores que son asociativos por la derecha se evalúan en orden de derecha a izquierda. Los
operadores de asignación y el operador terciario (?:) son asociativos por la derecha. Todos los otros operadores binarios son
asociativos por la izquierda. Sin embargo, el estándar de C# no especifica cuándo se ejecuta la parte "fija" de una instrucción de
incremento en una expresión. Por ejemplo, el resultado del código de ejemplo siguiente es 6:
C#
int num1 = 5;
num1++;
System.Console.WriteLine(num1);
Por consiguiente, no se recomienda el último ejemplo. Los paréntesis se pueden utilizar para envolver una expresión y hacer
que esa expresión sea evaluada antes que cualquier otra. Por ejemplo, 2 + 3 * 2 normalmente darían 8 como resultado. Esto
es porque los operadores multiplicativos tienen prioridad sobre los operadores aditivos. Escribir la expresión (2 + 3 ) * 2 da
como resultado 10, ya que ésta indica al compilador de C# que el operador de adición (+) se debe evaluar antes que el
operador de multiplicación (*).
Se puede cambiar el comportamiento de los operadores con las estructuras y cargas personalizadas. Este proceso se denomina
sobrecarga de operadores. Para obtener más información, vea Operadores sobrecargables (Guía de programación de C#).
Secciones relacionadas
Para obtener más información, vea Palabras clave de operadores (Referencia de C#) y Operadores de C#.
Vea también
Referencia
Instrucciones, expresiones y operadores (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
==, !=, <, >, <=, >= Los operadores de comparación se pueden sobrecargar (pero vea la nota que aparece a continuaci
ón de esta tabla).
&&, || Los operadores lógicos condicionales no se pueden sobrecargar, pero se evalúan mediante & y |, l
os cuales sí se pueden sobrecargar.
() El operador de conversión explícita de tipos no se puede sobrecargar, pero se pueden definir nuev
os operadores de conversión (vea explicit e implicit).
+=, -=, *=, /=, %=, &=, |=, Los operadores de asignación no se pueden sobrecargar, pero +=, por ejemplo, se evalúa con +, el
^=, <<=, >>= cual sí se puede sobrecargar.
Sobrecargar un operador en una clase personalizada requiere la creación de un método en la clase con la firma correcta. El
método se debe denominar "operador X", donde X es el nombre o símbolo del operador que se va a sobrecargar. Los
operadores unarios tienen un parámetro y los operadores binarios tienen dos. En cada caso, un parámetro debe tener el
mismo tipo que la clase o estructura que declara el operador, como se muestra en el siguiente ejemplo:
C#
public static Complex operator +(Complex c1, Complex c2)
return temp;
}
}
public static explicit operator Digit(byte b) // explicit byte to digit conversion ope
rator
{
Digit d = new Digit(b); // explicit conversion
System.Console.WriteLine("conversion occurred");
return d;
}
}
class TestExplicitConversion
{
static void Main()
{
try
{
byte b = 3;
Digit d = (Digit)b; // explicit conversion
}
catch (System.Exception e)
{
System.Console.WriteLine("{0} Exception caught.", e);
}
}
}
Resultado 1
conversion occurred
Ejemplo 2
Description
En este ejemplo se muestra un operador de conversión implícita mediante la definición de un operador de conversión que
deshace lo que hizo el ejemplo anterior: convierte una clase de valor denominada Digit en el tipo integral Byte. Dado que
cualquier dígito se puede convertir en Byte, no hay ninguna necesidad de obligar a los usuarios a que definan la conversión.
C#
struct Digit
{
byte value;
class TestImplicitConversion
{
static void Main()
{
Digit d = new Digit(3);
byte b = d; // implicit conversion -- no cast needed
}
}
Resultado 2
conversion occurred
Vea también
Conceptos
Guía de programación de C#
Operadores de conversión (Guía de programación de C#)
Otros recursos
Referencia de C#
Guía de programación de C#
Resultados
10
Conversion not yet implemented
Programación eficaz
En el ejemplo anterior, la instrucción:
C#
binary = (BinaryNumeral)(int)roman;
realiza una conversión de un RomanNumeral a un BinaryNumeral. Como no existe una conversión directa de RomanNumeral
a BinaryNumeral, se utiliza una conversión explícita de un RomanNumeral a un int, y otra conversión explícita para
convertir de un int a un BinaryNumeral.
Además, la instrucción
C#
roman = binary;
realiza una conversión de un BinaryNumeral a un RomanNumeral. Como RomanNumeral define una conversión implícita
desde BinaryNumeral, no se requiere ninguna conversión explícita.
Vea también
Conceptos
Guía de programación de C#
Operadores de conversión (Guía de programación de C#)
Otros recursos
Referencia de C#
Guía de programación de C#
// Override the ToString() method to display a complex number in the traditional format
:
public override string ToString()
{
return (System.String.Format("{0} + {1}i", real, imaginary));
}
}
class TestComplex
{
static void Main()
{
Complex num1 = new Complex(2, 3);
Complex num2 = new Complex(3, 4);
// Add two Complex objects through the overloaded plus operator:
Complex sum = num1 + num2;
// Print the numbers and the sum using the overriden ToString method:
System.Console.WriteLine("First complex number: {0}", num1);
System.Console.WriteLine("Second complex number: {0}", num2);
System.Console.WriteLine("The sum of the two numbers: {0}", sum);
}
}
Resultados
First complex number: 2 + 3i
Second complex number: 3 + 4i
The sum of the two numbers: 5 + 7i
Vea también
Referencia
Operadores de C#
operator (Referencia de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
En este código, sólo existe un objeto, pero hay varias referencias a ese objeto: a y b. Como ambas hacen referencia al mismo
objeto, tienen la igualdad de referencia. Si dos objetos tienen igualdad de referencia, también tienen igualdad de valor, pero la
igualdad de valor no garantiza la igualdad de referencia.
Para comprobar la igualdad de referencia, utilice ReferenceEquals. Para comprobar la igualdad de valor, utilice Equals o Equals.
Reemplazar Equals
Equals es un método virtual que permite que cualquier clase reemplace su implementación. Toda clase que representa un
valor (básicamente cualquier tipo de valor) o un conjunto de valores como un grupo, por ejemplo una clase de números
complejos, debe reemplazar Equals. Si el tipo implementa IComparable, deberá reemplazar Equals.
La nueva implementación de Equals debe seguir todas las garantías de Equals:
x.Equals(x) devuelve true.
x.Equals(y) devuelve el mismo valor que y.Equals(x).
si (x.Equals(y) && y.Equals(z)) devuelve true, x.Equals(z) devuelve true.
Las invocaciones sucesivas de x.Equals(y) devuelven el mismo valor siempre que no se modifiquen los objetos a los que
se hace referencia mediante x e y.
x.Equals(null) devuelve false.
La nueva implementación de Equals no debe producir excepciones. Se recomienda que toda clase que reemplaza Equals
también reemplace System.Object.GetHashCode. También se recomienda que además de implementar Equals (objeto),
cualquier clase implemente también Equals (tipo) para su propio tipo con el fin de mejorar el rendimiento. Por ejemplo:
C#
class TwoDPoint : System.Object
{
public readonly int x, y;
Cualquier clase derivada que puede llamar a Equals en la clase base debe hacerlo antes de finalizar su comparación. En el
siguiente ejemplo, Equals llama a la clase base Equals, la cual busca un parámetro nulo y compara el tipo del parámetro con
el tipo de la clase derivada. Esto deja a la implementación de Equals en la clase derivada la tarea de comprobar el nuevo
campo de datos declarado en la clase derivada:
C#
class ThreeDPoint : TwoDPoint
{
public readonly int z;
public ThreeDPoint(int x, int y, int z)
: base(x, y)
{
this.z = z;
}
Reemplazar el operador ==
De forma predeterminada, el operador == prueba la igualdad de referencia al determinar si las dos referencias indican el
mismo objeto, de manera que no es necesario que los tipos de referencias implementen el operador == para obtener esta
funcionalidad. Cuando un tipo es inmutable, es decir, cuando los datos contenidos en la instancia no pueden cambiarse, la
sobrecarga del operador == para comparar la igualdad de valor en lugar de la igualdad de referencia puede ser útil porque,
como objetos inmutables, se pueden considerar iguales siempre y cuando tengan el mismo valor. No se recomienda
reemplazar el operador == en tipos no inmutables.
Las implementaciones del operador sobrecargado == no deben producir excepciones. Cualquier tipo que sobrecargue el
operador == también debe sobrecargar el operador !=. Por ejemplo:
C#
//add this code to class ThreeDPoint as defined previously
//
public static bool operator ==(ThreeDPoint a, ThreeDPoint b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
Nota
Un error común en las sobrecargas del operador == es utilizar (a == b), (a == null) o (b == null) para comprobar la igu
aldad de referencia. Por el contrario, esto produce una llamada al operador sobrecargado ==, lo que origina un bucle infinito
. Utilice ReferenceEquals o convierta el tipo a Object, para evitar el bucle.
Vea también
Referencia
Instrucciones, expresiones y operadores (Guía de programación de C#)
Operadores (Guía de programación de C#)
Operadores sobrecargables (Guía de programación de C#)
Operador == (Referencia de C#)
Operador () (Referencia de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
El nivel de acceso precede a la palabra clave class. En este caso, se utiliza public, que significa que cualquiera puede crear
objetos a partir de esta clase. El nombre de la clase sigue a la palabra clave class. El resto de la definición es el cuerpo de clase,
donde se definen el comportamiento y los datos. Los campos, propiedades, métodos y eventos de una clase se conocen
colectivamente como miembros de clase.
Crear objetos
Aunque se utilizan a veces de forma intercambiable, una clase y un objeto son cosas diferentes. Una clase define un tipo de
objeto, pero no es propiamente un objeto. Un objeto es una entidad concreta basada en una clase y, a veces, se denomina
instancia de una clase.
Los objetos se pueden crear con la palabra clave new seguida del nombre de la clase en la que se basará el objeto, de la
manera siguiente:
C#
Customer object1 = new Customer();
Cuando se crea una instancia de una clase, una referencia al objeto se vuelve a pasar al programador. En el ejemplo anterior,
object1 es una referencia a un objeto basado en Customer. Esta referencia hace referencia el nuevo objeto, pero no contiene
los datos del propio objeto. De hecho, se puede crear una referencia a objeto sin crear un objeto:
C#
Customer object2;
No se recomienda la creación de referencias a objetos como ésta, que no hace referencia a un objeto, porque al intentar el
acceso a un objeto a través de esa referencia se producirá un error en tiempo de ejecución. Sin embargo, este tipo de
referencia se puede crear para hacer referencia a un objeto, ya sea creando un nuevo objeto o asignándola a un objeto
existente, de la forma siguiente:
C#
Customer object3 = new Customer();
Customer object4 = object3;
Este código crea dos referencias a objeto que se refieren al mismo objeto. Por consiguiente, los cambios realizados en el objeto
a través de object3 se reflejarán en los usos posteriores de object4. El hecho de que las clases se conozcan como tipos de
referencia se debe a que se hace referencia a los objetos basados en clases por referencia.
Herencia de clase
La herencia se realiza a través de una derivación, lo que significa que una clase se declara utilizando una clase base de la cual
hereda los datos y el comportamiento. Una clase base se especifica anexando dos puntos y el nombre de la clase base a
continuación del nombre de la clase derivada, del modo siguiente:
C#
public class Manager : Employee
{
// Employee fields, properties, methods and events are inherited
// New Manager fields, properties, methods and events go here...
}
Cuando una clase declara una clase base, todos los miembros de clase definidos para la clase base también pasan a formar
parte de la nueva clase. Dado que una clase base se puede heredar de otra clase, que a su vez se heredó de otra clase y así
sucesivamente, una clase puede provenir de varias clases base.
Ejemplo
En el ejemplo siguiente, se define una clase pública que contiene un campo único, un método y un método especial
denominado constructor. Para obtener más información, vea Constructores (Guía de programación de C#). Luego se crean
instancias de la clase con la palabra clave new.
C#
public class Person
{
// Field
public string name;
// Constructor
public Person()
{
name = "unknown";
}
// Method
public void SetName(string newName)
{
name = newName;
}
}
class TestPerson
{
static void Main()
{
Person person1 = new Person();
System.Console.WriteLine(person1.name);
person1.SetName("John Smith");
System.Console.WriteLine(person1.name);
}
}
Resultado
unknown
John Smith
Casi todas las estructuras comparten la misma sintaxis que las clases, aunque están más limitadas que éstas:
Dentro de una declaración de estructura, los campos no se pueden inicializar a menos que se declaren como constantes o
estáticos.
Una estructura no puede declarar un constructor predeterminado (es decir, un constructor sin parámetros) ni un
destructor.
El compilador crea y destruye automáticamente copias de estructuras, de modo que un constructor y destructor
predeterminados son innecesarios. De hecho, el compilador implementa el constructor predeterminado asignando a todos los
campos sus valores predeterminados (vea Tabla de valores predeterminados (Referencia de C#)). Las estructuras no pueden
heredar de clases u otras estructuras.
Las estructuras son tipos de valor; cuando un objeto se crea a partir de una estructura y se asigna a una variable, la variable
contiene el valor completo de la estructura. Cuando se copia una variable que contiene una estructura, todos los datos se
copian y cualquier modificación a la nueva copia no cambia los datos de la copia antigua. Como las estructuras no utilizan
referencias, no tienen identidad; no existe ninguna forma de distinguir entre dos instancias de un tipo de valor con los mismos
datos. En C#, todos los tipos de valor derivan inherentemente de ValueType, que hereda de Object.
El compilador puede convertir tipos de valor en tipos de referencia en un proceso conocido como conversión boxing. Para
obtener más información, vea Boxing y Unboxing.
Información general sobre las estructuras
Las estructuras tienen las propiedades siguientes:
Las estructuras son tipos de valor, mientras que las clases son tipos de referencia.
A diferencia de las clases, se pueden crear instancias de las estructuras sin utilizar un operador new.
Las estructuras pueden declarar constructores, pero deben utilizar parámetros.
Una estructura no puede heredar de otra estructura o clase, ni puede ser la base de una clase. Todas las estructuras
heredan directamente de System.ValueType, que hereda de System.Object.
Una estructura puede implementar interfaces.
Secciones relacionadas
Para obtener más información:
Utilizar estructuras (Guía de programación de C#)
Utilizar constructores y destructores
Cómo: Saber las diferencias entre pasar a un método una estructura y una referencia a clase (Guía de programación de C#)
Cómo: Implementar conversiones entre estructuras definidas por el usuario (Guía de programación de C#)
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Conceptos
Guía de programación de C#
Diseño de estructuras
Clases (Guía de programación de C#)
Guía de programación de C#
Es un error declarar un constructor predeterminado (sin parámetros) para una estructura. Siempre existe un constructor
predeterminado que inicializa los miembros de la estructura con sus valores predeterminados. También es un error inicializar
un campo de instancia en una estructura.
Cuando se crea un objeto struct mediante el operador new, se crea y se llama al constructor apropiado. A diferencia de las
clases, es posible crear instancias de las estructuras sin utilizar el operador new. Si no se utiliza new, los campos
permanecerán sin asignar y el objeto no se podrá utilizar hasta haber inicializado todos los campos.
A diferencia de las clases, para las estructuras no existe herencia. Una estructura no puede heredar de otra estructura o clase, ni
puede ser la base de una clase. Sin embargo, las estructuras heredan de la clase base Object. Una estructura puede
implementar interfaces del mismo modo que las clases.
A diferencia de C++, no se puede declarar una clase mediante la palabra clave struct. En C#, las clases y las estructuras son
semánticamente diferentes. Una estructura es un tipo de valor, mientras que una clase es un tipo de referencia. Para obtener
más información, vea Tipos de valores (Referencia de C#).
A menos que se necesite semántica de tipo de referencia, el sistema puede controlar más eficazmente las clases pequeñas si se
definen como estructuras.
Ejemplo 1
Description
Este ejemplo muestra la inicialización de tipo struct mediante constructores predeterminados y constructores con parámetros.
C#
public struct CoOrds
{
public int x, y;
public CoOrds(int p1, int p2)
{
x = p1;
y = p2;
}
}
C#
// Declare and initialize struct objects.
class TestCoOrds
{
static void Main()
{
// Initialize:
CoOrds coords1 = new CoOrds();
CoOrds coords2 = new CoOrds(10, 10);
// Display results:
System.Console.Write("CoOrds 1: ");
System.Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);
System.Console.Write("CoOrds 2: ");
System.Console.WriteLine("x = {0}, y = {1}", coords2.x, coords2.y);
}
}
Resultado
CoOrds 1: x = 0, y = 0
CoOrds 2: x = 10, y = 10
Ejemplo 2
Description
Este ejemplo muestra una característica exclusiva de las estructuras. Crea un objeto CoOrds sin utilizar el operador new. Si se
reemplaza la palabra struct por la palabra class, el programa no se compilará.
C#
public struct CoOrds
{
public int x, y;
public CoOrds(int p1, int p2)
{
x = p1;
y = p2;
}
}
C#
// Declare a struct object without "new."
class TestCoOrdsNoNew
{
static void Main()
{
// Declare an object:
CoOrds coords1;
// Initialize:
coords1.x = 10;
coords1.y = 20;
// Display results:
System.Console.Write("CoOrds 1: ");
System.Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);
}
}
Resultado
CoOrds 1: x = 10, y = 20
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Conceptos
Guía de programación de C#
Estructuras (Guía de programación de C#)
Guía de programación de C#
public class B : A
{
public B() { }
}
La nueva clase (la clase derivada) obtiene todos los datos no privados y el comportamiento de la clase base, además de todos
los demás datos y comportamientos que define para sí misma. La nueva clase tiene dos tipos efectivos: el tipo de la nueva
clase y el tipo de la clase que hereda.
En el ejemplo anterior, la clase B es claramente B y A. Cuando se tiene acceso a un objeto B, se puede utilizar la operación de
conversión de tipos para convertirlo en un objeto A. La conversión de tipos no cambia el objeto B, pero la vista del objeto B se
restringe a los datos y comportamientos de A. Después de convertir un objeto B en un objeto A, es posible volver a convertir
ese objeto A en un objeto B. No todas las instancias de A se pueden convertir en B, sólo aquellas que son realmente instancias
de B. Si se tiene acceso a la clase B como tipo B, se obtienen los datos y comportamientos tanto de la clase A como de la clase
B. La capacidad que tiene un objeto de representar más de un tipo se denomina polimorfismo. Para obtener más información,
vea Polimorfismo (Guía de programación de C#). Para obtener más información sobre conversión, vea
Conversión (Guía de programación de C#).
Las estructuras no pueden heredar de otras estructuras o clases. Tanto las clases como las estructuras pueden heredar de una
o más interfaces. Para obtener más información, vea Interfaces (Guía de programación de C#)
En esta sección
Clases y miembros de clase abstractos y sellados (Guía de programación de C#)
Polimorfismo (Guía de programación de C#)
Interfaces (Guía de programación de C#)
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
class (Referencia de C#)
struct (Referencia de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
No se pueden crear instancias de una clase abstracta. El propósito de una clase abstracta es proporcionar una definición
común de una clase base que múltiples clases derivadas pueden compartir. Por ejemplo, una biblioteca de clase puede definir
una clase abstracta que se utiliza como parámetro para muchas de sus funciones y solicitar a los programadores que utilizan
esa biblioteca que proporcionen su propia implementación de la clase mediante la creación de una clase derivada.
Las clases abstractas también pueden definir métodos abstractos. Esto se consigue agregando la palabra clave abstract antes
del tipo de valor que devuelve el método. Por ejemplo:
C#
public abstract class A
{
public abstract void DoWork(int i);
}
Los métodos abstractos no tienen ninguna implementación, de modo que la definición de método va seguida por un punto y
coma en lugar de un bloque de método normal. Las clases derivadas de la clase abstracta deben implementar todos los
métodos abstractos. Cuando una clase abstracta hereda un método virtual de una clase base, la clase abstracta puede
reemplazar el método virtual con un método abstracto. Por ejemplo:
C#
// compile with: /target:library
public class D
{
public virtual void DoWork(int i)
{
// Original implementation.
}
}
public abstract class E : D
{
public abstract override void DoWork(int i);
}
public class F : E
{
public override void DoWork(int i)
{
// New implementation.
}
}
Si un método virtual se declara abstracto, sigue siendo virtual para cualquier clase que se herede de la clase abstracta. Una
clase que hereda un método abstracto no puede tener acceso a la implementación original del método; en el ejemplo anterior,
DoWork de la clase F no puede llamar a DoWork de la clase D. De esta forma, una clase abstracta puede obligar a las clases
derivadas a proporcionar nuevas implementaciones de método para los métodos virtuales.
Clases y miembros de clase sellados
Las clases pueden declararse como selladas. Esto se logra colocando la palabra clave sealed antes de la palabra clave class en
la definición de clase. Por ejemplo:
C#
public sealed class D
{
// Class members here.
}
Una clase sellada no se puede utilizar como clase base. Por esta razón, tampoco puede ser una clase abstracta. Las clases
selladas se utilizan principalmente para impedir la derivación. Puesto que nunca se pueden utilizar como una clase base,
algunas optimizaciones en tiempo de ejecución pueden hacer que sea un poco más rápido llamar a miembros de clase sellada.
Un miembro de clase, método, campo, propiedad o evento de una clase derivada que reemplaza a un miembro virtual de la
clase base puede declarar ese miembro como sellado. Esto niega el aspecto virtual del miembro para cualquier clase derivada
adicional. Esto se logra colocando la palabra clave sealed antes de la palabra clave override en la declaración del miembro de
clase. Por ejemplo:
C#
public class D : C
{
public sealed override void DoWork() { }
}
Vea también
Tareas
Cómo: Definir propiedades abstractas (Guía de programación de C#)
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Herencia (Guía de programación de C#)
Métodos (Guía de programación de C#)
Campos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
public Shape(string s)
{
// calling the set accessor of the Id property.
Id = s;
}
public string Id
{
get
{
return m_id;
}
set
{
m_id = value;
}
}
// Area is a read-only property - only a get accessor is needed:
public abstract double Area
{
get;
}
Cuando se declara una propiedad abstracta (tal como Area en este ejemplo), simplemente se indica qué descriptores de
acceso a la propiedad están disponibles, pero no se implementan. En este ejemplo, sólo se dispone de un descriptor de
acceso get, de modo que la propiedad es de sólo lectura.
El siguiente código muestra tres subclases de Shape y cómo reemplazan la propiedad Area para proporcionar sus propias
implementaciones.
C#
// compile with: csc /target:library /reference:abstractshape.dll shapes.cs
public class Square : Shape
{
private int m_side;
public Square(int side, string id)
: base(id)
{
m_side = side;
}
El siguiente código muestra un programa de prueba que crea una serie de objetos derivados de Shape e imprime sus áreas.
C#
// compile with: csc /reference:abstractshape.dll;shapes.dll shapetest.cs
class TestClass
{
static void Main()
{
Shape[] shapes =
{
new Square(5, "Square #1"),
new Circle(3, "Circle #1"),
new Rectangle( 4, 5, "Rectangle #1")
};
System.Console.WriteLine("Shapes Collection");
foreach (Shape s in shapes)
{
System.Console.WriteLine(s);
}
}
}
Resultados
Shapes Collection
Square #1 Area = 25.00
Circle #1 Area = 28.27
Rectangle #1 Area = 20.00
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Clases y miembros de clase abstractos y sellados (Guía de programación de C#)
Propiedades (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Cuando se utiliza la palabra clave new, se llama a los nuevos miembros de clase en lugar de los miembros de clase base que
se han reemplazado. Esos miembros de clase base se denominan miembros ocultos. Aún es posible llamar a los miembros de
clase ocultos si una instancia de la clase derivada se convierte en una instancia de la clase base. Por ejemplo:
C#
DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Calls the old method.
Para que una instancia de una clase derivada controle por completo un miembro de clase de una clase base, la clase base debe
declarar ese miembro como virtual. Esto se consigue agregando la palabra clave virtual antes del tipo de valor devuelto del
miembro. Una clase derivada tiene entonces la opción de utilizar la palabra clave override, en lugar de new, para reemplazar la
implementación de la clase base por la propia. Por ejemplo:
C#
public class BaseClass
{
public virtual void DoWork() { }
public virtual int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public override void DoWork() { }
public override int WorkProperty
{
get { return 0; }
}
}
Los campos no pueden ser virtuales. Sólo los métodos, propiedades, eventos e indizadores pueden serlo. Cuando una clase
derivada reemplaza un miembro virtual, se llama a ese miembro aunque se tenga acceso a una instancia de esa clase como
instancia de la clase base. Por ejemplo:
C#
DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Also calls the new method.
Los métodos y propiedades virtuales permiten hacer planes para una expansión futura. El hecho de llamar a un miembro
virtual sin importar cuál es el tipo que el llamador utiliza proporciona a las clases derivadas la opción de cambiar
completamente el comportamiento aparente de la clase base.
Los miembros virtuales siguen siendo virtuales de forma indefinida, independientemente de cuántas clases se hayan declarado
en la clase que originalmente declaró el miembro virtual. Si la clase A declara un miembro virtual, la clase B deriva de A y la
clase C deriva de B, la clase C hereda el miembro virtual y tiene la opción de reemplazarlo, independientemente de si la clase B
declaró la sustitución de ese miembro. Por ejemplo:
C#
public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}
C#
public class C : B
{
public override void DoWork() { }
}
Una clase derivada puede detener la herencia virtual si la sustitución se declara como sellada. Para ello es necesario colocar la
palabra clave sealed antes de la palabra clave override en la declaración del miembro de clase. Por ejemplo:
C#
public class C : B
{
public sealed override void DoWork() { }
}
En el ejemplo anterior, el método DoWork ya no es virtual para ninguna clase derivada de C. Todavía es virtual para instancias
de C, aunque se conviertan al tipo B o A. Los métodos sellados se pueden reemplazar por clases derivadas mediante la palabra
clave new, como se muestra en el ejemplo siguiente:
C#
public class D : C
{
public new void DoWork() { }
}
En este caso, si se llama a DoWork en D mediante una variable de tipo D, se llama al nuevo DoWork. Si se utiliza una variable de
tipo C, B o A para tener acceso a una instancia de D, una llamada a DoWork seguirá las reglas de la herencia virtual y enrutará
esas llamadas a la implementación de DoWork en la clase C.
Una clase derivada que ha reemplazado un método o propiedad todavía puede tener acceso al método o propiedad de la clase
base utilizando la palabra clave base. Por ejemplo:
C#
public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}
C#
public class C : B
{
public override void DoWork()
{
// Call DoWork on B to get B's behavior:
base.DoWork();
Vea también
Referencia
Herencia (Guía de programación de C#)
Clases y miembros de clase abstractos y sellados (Guía de programación de C#)
Métodos (Guía de programación de C#)
Propiedades (Guía de programación de C#)
Indizadores (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Eventos (Guía de programación de C#)
Guía de programación de C#
C#
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
La compañía utiliza esta clase, que se utiliza para derivar clases propias, mediante la adición de un nuevo método:
C#
class YourDerivedGraphicsClass : GraphicsClass
{
public void DrawRectangle() { }
}
La aplicación se utiliza sin problemas, hasta que la compañía lanza una nueva versión de GraphicsClass, que tiene el siguiente
aspecto:
C#
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
La nueva versión de GraphicsClass contiene ahora un método denominado DrawRectangle. Inicialmente, no sucede nada. La
nueva versión aún es compatible a nivel binario con la anterior; todo el software que se haya implementado continuará
funcionando, aunque la nueva clase esté instalada en los equipos. Cualquier llamada existente al método DrawRectangle
continuará haciendo referencia a la versión, en la clase derivada.
Sin embargo, una vez que se vuelve a compilar la aplicación mediante la nueva versión de GraphicsClass, se recibe una
advertencia del compilador. Para obtener más información, vea Advertencia del compilador (nivel 2) CS0108.
Esta advertencia informa de que el usuario debe considerar cómo desea que el método DrawRectangle se comporte en la
aplicación.
Si desea que el método reemplace el nuevo método de clase base, utilice la palabra clave override, como se muestra a
continuación:
C#
class YourDerivedGraphicsClass : GraphicsClass
{
public override void DrawRectangle() { }
}
La palabra clave override se asegura de que cualquier objeto derivado de YourDerivedGraphicsClass utilizará la versión de
clase derivada de DrawRectangle. Los objetos derivados de YourDerivedGraphicsClass aún pueden tener acceso a la versión
de clase base de DrawRectangle con la palabra clave base, de la forma siguiente:
C#
base.DrawRectangle();
Si no desea que el método reemplace el nuevo método de clase base, tenga en cuenta las consideraciones siguientes. Para
evitar la confusión entre los dos métodos, puede cambiar el nombre del método. Esto puede requerir mucho tiempo, llevar a
errores y, simplemente, no ser práctico en algunas situaciones. Sin embargo, si el proyecto es relativamente pequeño, se
pueden utilizar las opciones de refactorización de Visual Studio para cambiar el nombre del método. Para obtener más
información, vea Refactorizar clases y tipos.
Por otro lado, se puede evitar la advertencia mediante la palabra clave new en la definición de la clase derivada, de la forma
siguiente:
C#
class YourDerivedGraphicsClass : GraphicsClass
{
public new void DrawRectangle() { }
}
Con la palabra clave new se indica al compilador que la definición oculta la definición contenida en la clase base. Éste es el
comportamiento predeterminado.
Selección de método y reemplazo
Cuando se nombra un método en una clase, el compilador de C# selecciona el mejor método que se va a llamar si más de un
método es compatible con la llamada, al igual que cuando hay dos métodos con el mismo nombre y parámetros que son
compatibles con el parámetro pasado. Los métodos siguientes serían compatibles:
C#
public class Derived : Base
{
public override void DoWork(int param) { }
public void DoWork(double param) { }
}
Cuando se llama a DoWork en una instancia de Derived, el compilador de C# intentará primero hacer que la llamada sea
compatible con las versiones de DoWork declaradas originalmente en Derived. Los métodos de reemplazo no se consideran
como declarados en una clase; son nuevas implementaciones de un método declarado en una clase base. Sólo si el compilador
de C# no puede hacer coincidir la llamada de método con un método original de Derived, intentará hacer que la llamada
coincida con un método de reemplazo que tenga el mismo nombre y parámetros compatibles. Por ejemplo:
C#
int val = 5;
Derived d = new Derived();
d.DoWork(val); // Calls DoWork(double).
Puesto que la variable val se puede convertir implícitamente en double, el compilador de C# llama a DoWork(double) en lugar
de DoWork(int). Existen dos formas para evitar esto. En primer lugar, se debe evitar declarar nuevos métodos con el mismo
nombre que los métodos virtuales. En segundo lugar, se puede indicar al compilador de C# que llame al método virtual
haciendo que busque la lista de métodos de la clase base mediante la conversión de la instancia de Derived en Base. Debido a
que el método es virtual, se llamará a la implementación de DoWork(int) en Derived. Por ejemplo:
C#
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Métodos (Guía de programación de C#)
Herencia (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Ahora es posible escribir algún código que declara instancias de estas clases y llama a sus correspondientes métodos, de modo
que los objetos se puedan describir a sí mismos:
C#
public static void TestCars1()
{
Car car1 = new Car();
car1.DescribeCar();
System.Console.WriteLine("----------");
Sin embargo, en la siguiente sección de código, se declara una matriz de objetos derivada de la clase base Car. Esta matriz
puede almacenar los objetos Car, ConvertibleCar y Minivan. La matriz se declara de la siguiente manera:
C#
public static void TestCars2()
{
Car[] cars = new Car[3];
cars[0] = new Car();
cars[1] = new ConvertibleCar();
cars[2] = new Minivan();
}
Es posible utilizar un bucle foreach para visitar a cada objeto Car contenido en la matriz y llamar al método DescribeCar de la
siguiente manera:
C#
foreach (Car vehicle in cars)
{
System.Console.WriteLine("Car object: " + vehicle.GetType());
vehicle.DescribeCar();
System.Console.WriteLine("----------");
}
Se puede observar que la descripción ConvertibleCar no es como se podría esperar. Como la palabra clave new se utilizó
para definir este método, no se llamó al método de la clase derivada sino que, en su lugar, se llamó al método de la clase base.
El objeto Minivan llama correctamente al método reemplazado, lo que genera los resultados esperados.
Si se desea reforzar la regla de que todas las clases derivadas de Car deben implementar el método DescribeCar, se debe crear
una nueva clase base que defina el método DescribeCar como abstract. Un método abstracto no contiene ningún código, sólo
la firma del método. Cualquier clase derivada de esta clase base debe proporcionar una implementación de DescribeCar. Para
obtener más información, vea abstract.
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Conceptos
Guía de programación de C#
Control de versiones con las palabras clave Override y New (Guía de programación de C#)
Guía de programación de C#
Cuando cree una clase o estructura personalizada, debe reemplazar el método ToString para proporcionar información sobre
el tipo al código de cliente.
Nota de seguridad
Cuando decida qué información va a proporcionar a través de este método, considere si la clase o estructura se va a utilizar a
lguna vez en código que no sea de confianza. Asegúrese de que no proporciona información que pueda ser aprovechada por
código malintencionado.
class Person
{
string name;
int age;
SampleObject(string name, int age)
{
this.name = name;
this.age = age;
}
public override string ToString()
{
string s = age.ToString();
return "Person: " + name + " " + s;
}
}
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
new (Referencia de C#)
override (Referencia de C#)
virtual (Referencia de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Las interfaces describen un grupo de comportamientos relacionados que pueden pertenecer a cualquier clase o estructura. Las
interfaces pueden estar compuestas de métodos, propiedades, eventos, indizadores o cualquier combinación de estos cuatro
tipos de miembros. Una interfaz no puede contener campos. Los miembros de interfaz son automáticamente públicos.
Al igual que las clases se pueden heredar de una clase base o estructura, las clases y estructuras se pueden heredar de
interfaces, con dos excepciones:
Una clase o estructura puede heredar más de una interfaz.
Cuando una clase o la estructura hereda una interfaz, hereda sólo los nombres de método y las firmas, ya que la propia
interfaz no contiene ninguna implementación. Por ejemplo:
C#
public class Minivan : Car, IComparable
{
public int CompareTo(object obj)
{
//implementation of CompareTo
return 0; //if the Minivans are equal
}
}
Para implementar un miembro de interfaz, el miembro correspondiente de la clase debe ser público, no estático y tener el
mismo nombre y la misma firma que el miembro de interfaz. Las propiedades e indizadores de una clase pueden definir
descriptores de acceso adicionales para una propiedad o indizador definidos en una interfaz. Por ejemplo, una interfaz puede
declarar una propiedad con un descriptor de acceso get, pero la clase que implementa la interfaz puede declarar la misma
propiedad con descriptores de acceso get y set. Sin embargo, si la propiedad o el indizador utiliza una implementación
explícita, los descriptores de acceso deben coincidir.
Las interfaces y los miembros de interfaz son abstractos; las interfaces no proporcionan una implementación predeterminada.
Para obtener más información, vea Clases y miembros de clase abstractos y sellados (Guía de programación de C#).
La interfaz IComparable informa al usuario del objeto de que éste se puede comparar con otros objetos del mismo tipo y el
usuario de la interfaz no necesita saber cómo se implementa.
Las interfaces pueden heredar otras interfaces. Es posible que una clase herede una interfaz varias veces, a través de las clases
base o interfaces que hereda. En ese caso, la clase sólo puede implementar la interfaz una vez, siempre que ésta se declare
como parte de la nueva clase. Si la interfaz heredada no está declarada como parte de la nueva clase, la clase base que la
declaró proporcionará su implementación. Es posible que una clase base implemente miembros de interfaz a través de
miembros virtuales. En ese caso, la clase que hereda la interfaz puede cambiar el comportamiento de la interfaz reemplazando
los miembros virtuales. Para obtener más información sobre miembros virtuales, vea Polimorfismo.
Información general sobre interfaces
Una interfaz tiene las siguientes propiedades:
Una interfaz es similar a una clase base abstracta. Cualquier tipo no abstracto que hereda la interfaz debe implementar
todos sus miembros.
No se pueden crear instancias directamente de una interfaz.
Las interfaces pueden contener eventos, métodos, indizadores y propiedades.
Las interfaces no contienen implementaciones de métodos.
Las clases y estructuras se pueden heredar de más de una interfaz.
Una interfaz se puede heredar de varias interfaces.
En esta sección
Implementación explícita de interfaz (Guía de programación de C#)
Propiedades de interfaces (Guía de programación de C#)
Indizadores en interfaces (Guía de programación de C#)
Cómo: Implementar eventos de interfaz (Guía de programación de C#)
Cómo: Implementar explícitamente miembros de interfaz (Guía de programación de C#)
Cómo: Implementar explícitamente miembros de interfaz con herencia (Guía de programación de C#)
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Herencia (Guía de programación de C#)
Métodos (Guía de programación de C#)
Clases y miembros de clase abstractos y sellados (Guía de programación de C#)
Métodos (Guía de programación de C#)
Propiedades (Guía de programación de C#)
Indizadores (Guía de programación de C#)
Conceptos
Guía de programación de C#
Polimorfismo (Guía de programación de C#)
Eventos (Guía de programación de C#)
Guía de programación de C#
Sin embargo, s los miembros de dos interfaces no realizan la misma función, esto puede llevar a una implementación
incorrecta de una o ambas interfaces. Es posible implementar un miembro de interfaz explícitamente, creando un miembro de
clase que sólo se llama a través de la interfaz y es específico de ésta. Esto se puede llevar a cabo asignando al miembro de
clase el nombre de la interfaz y un punto. Por ejemplo:
C#
public class SampleClass : IControl, ISurface
{
void IControl.Paint()
{
System.Console.WriteLine("IControl.Paint");
}
void ISurface.Paint()
{
System.Console.WriteLine("ISurface.Paint");
}
}
El miembro de clase IControl.Paint sólo está disponible a través de la interfaz IControl, mientras que ISurface.Paint sólo
está disponible a través de ISurface. Ambas implementaciones de método son independientes y ninguna está directamente
disponible en la clase. Por ejemplo:
C#
SampleClass obj = new SampleClass();
//obj.Paint(); // Compiler error.
IControl c = (IControl)obj;
c.Paint(); // Calls IControl.Paint on SampleClass.
ISurface s = (ISurface)obj;
s.Paint(); // Calls ISurface.Paint on SampleClass.
La implementación explícita también se usa para resolver casos donde cada una de las dos interfaces declara miembros
diferentes del mismo nombre como propiedad y método:
C#
interface ILeft
{
int P { get;}
}
interface IRight
{
int P();
}
Para implementar ambas interfaces, una clase tiene que utilizar implementación explícita, ya sea para la propiedad P, el
método P o ambos, con el fin de evitar un error del compilador. Por ejemplo:
C#
class Middle : ILeft, IRight
{
public int P() { return 0; }
int ILeft.P { get { return 0; } }
}
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Interfaces (Guía de programación de C#)
Herencia (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Resultados
Length: 30
Width: 20
Programación eficaz
Observe que las siguientes líneas, en el método Main, están desactivadas mediante comentarios, ya que producirían
errores de compilación. No se puede obtener acceso desde una instancia de clase a un miembro de interfaz
implementado explícitamente:
C#
//System.Console.WriteLine("Length: {0}", box1.getlength());
//System.Console.WriteLine("Width: {0}", box1.getwidth());
Observe también que las siguientes líneas del método Main imprimen correctamente las dimensiones del cuadro, ya
que los métodos se invocan desde una instancia de la interfaz:
C#
System.Console.WriteLine("Length: {0}", dimensions.getLength());
System.Console.WriteLine("Width: {0}", dimensions.getWidth());
Vea también
Tareas
Cómo: Implementar explícitamente miembros de interfaz con herencia (Guía de programación de C#)
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Interfaces (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
float IEnglishDimensions.Width()
{
return widthInches;
}
Resultados
Length(in): 30
Width (in): 20
Length(cm): 76.2
Width (cm): 50.8
Programación eficaz
Si desea realizar las medidas en unidades inglesas de forma predeterminada, implemente los métodos Length y Width con
normalidad e implemente explícitamente los métodos Length y Width de la interfaz IMetricDimensions:
C#
// Normal implementation:
public float Length()
{
return lengthInches;
}
public float Width()
{
return widthInches;
}
// Explicit implementation:
float IMetricDimensions.Length()
{
return lengthInches * 2.54f;
}
float IMetricDimensions.Width()
{
return widthInches * 2.54f;
}
En este caso, se puede tener acceso a las unidades inglesas desde la instancia de clase y acceso a las unidades métricas desde
la instancia de interfaz:
C#
public static void Test()
{
Box box1 = new Box(30.0f, 20.0f);
IMetricDimensions mDimensions = (IMetricDimensions)box1;
System.Console.WriteLine("Length(in): {0}", box1.Length());
System.Console.WriteLine("Width (in): {0}", box1.Width());
System.Console.WriteLine("Length(cm): {0}", mDimensions.Length());
System.Console.WriteLine("Width (cm): {0}", mDimensions.Width());
}
Vea también
Tareas
Cómo: Implementar explícitamente miembros de interfaz (Guía de programación de C#)
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Interfaces (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Llamar a un método en un objeto es similar a tener acceso a un campo. Después del nombre de objeto, agregue un punto, el
nombre del método y paréntesis. Los argumentos se enumeran entre paréntesis y separados por comas. Por tanto, se puede
llamar a los métodos de la clase Motorcycle del modo siguiente:
C#
Motorcycle moto = new Motorcycle();
moto.StartEngine();
moto.AddGas(15);
moto.Drive(5, 20);
Parámetros de métodos
Como se muestra en el fragmento de código anterior, para pasar argumentos a un método simplemente hay que
proporcionarlos entre paréntesis cuando se llama al método. En el método al que se llama, los argumentos de entrada se
denominan parámetros.
Los parámetros que un método recibe también se proporcionan entre paréntesis, pero se debe especificar el tipo y nombre de
cada parámetro. El nombre no tiene por qué ser igual que el argumento. Por ejemplo:
C#
public static void PassesInteger()
{
int fortyFour = 44;
TakesInteger(fortyFour);
}
static void TakesInteger(int i)
{
i = 33;
}
Aquí un método denominado PassesInteger pasa un argumento a un método denominado TakesInteger. En PassesInteger
el argumento se denomina fortyFour, pero en TakeInteger es un parámetro denominado i. Este parámetro sólo existe dentro
del método TakesInteger. Otras variables también pueden denominarse i y pueden ser de cualquier tipo, siempre y cuando
no sean parámetros o variables declaradas en ese método.
Observe que TakesInteger asigna un nuevo valor al argumento proporcionado. Se podría esperar que este cambio se reflejara
en el método PassesInteger una vez que TakeInteger devuelve un valor, pero de hecho, el valor de la variable fortyFour se
mantiene sin cambios. Esto se debe a que int es un tipo de valor. De forma predeterminada, cuando un tipo de valor se pasa a
un método, se pasa una copia en lugar del propio objeto. Dado que son copias, cualquier cambio realizado en el parámetro no
tiene ningún efecto en el método de llamada. Los tipos de valor reciben su nombre del hecho de que se pasa una copia del
objeto en lugar del propio objeto. Se pasa el valor, pero no el objeto mismo.
Para obtener más información sobre el paso de tipos de valor, vea
Pasar parámetros de tipo de valor (Guía de programación de C#). Para obtener una lista de tipos de valores integrales de C#,
vea Tabla de tipos de valores (Referencia de C#).
Esto es diferente de los tipos de referencia, que se pasan por referencia. Cuando un objeto basado en un tipo de referencia se
pasa a un método, no se realiza ninguna copia del objeto. En su lugar, se hace una referencia al objeto que se utiliza como
argumento del método y se pasa dicha referencia. Los cambios realizados a través de esta referencia se reflejarán por
consiguiente en el método de llamada. Un tipo de referencia se crea con la palabra clave class, de la forma siguiente:
C#
public class SampleRefType
{
public int value;
}
Ahora, si un objeto basado en este tipo se pasa a un método, se pasará por referencia. Por ejemplo:
C#
public static void TestRefType()
{
SampleRefType rt = new SampleRefType();
rt.value = 44;
ModifyObject(rt);
System.Console.WriteLine(rt.value);
}
static void ModifyObject(SampleRefType obj)
{
obj.value = 33;
}
Este ejemplo hace esencialmente lo mismo que el ejemplo anterior. Pero, como se utiliza un tipo de referencia, la modificación
realizada por ModifyObject se efectúa en el objeto creado en el método TestRefType. Por consiguiente, el método
TestRefType mostrará el valor 33.
Para obtener más información, vea Pasar parámetros Reference-Type (Guía de programación de C#) y
Tipos de referencia (Referencia de C#).
Valores devueltos
Los métodos pueden devolver un valor al llamador. Si el tipo de valor devuelto (el que aparece antes del nombre de método)
no es void, el método puede devolver el valor mediante la palabra clave return. Una instrucción con la palabra clave return,
seguida de un valor que coincida con el tipo de valor devuelto, devolverá ese valor al llamador del método. La palabra clave
return también detiene la ejecución del método. Si el tipo de valor devuelto es void, una instrucción return sin ningún valor
sigue siendo útil para detener la ejecución del método. Sin la palabra clave return, el método detendrá la ejecución cuando
llegue al fin del bloque de código. Es necesario que los métodos con un tipo de valor devuelto no nulo utilicen la palabra clave
return para devolver un valor. Por ejemplo, estos dos métodos utilizan la palabra clave return para devolver enteros:
C#
class SimpleMath
{
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
C#
obj.SquareANumber(obj.AddTwoNumbers(1, 2));
El uso de una variable intermedia, en este caso result, para almacenar un valor es opcional. La legibilidad del código puede
ser útil o puede ser necesaria si el valor se va a utilizar más de una vez.
Para obtener más información, vea return (Referencia de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#:
1.6.5 Métodos
10.5 Métodos
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Modificadores de acceso (Guía de programación de C#)
Clases estáticas y sus miembros (Guía de programación de C#)
Herencia (Guía de programación de C#)
params (Referencia de C#)
return (Referencia de C#)
out (Referencia de C#)
ref (Referencia de C#)
Pasar parámetros (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
C#
// Passing by reference
static void Square(ref int x)
{
// code...
}
C#
class PassingValByVal
{
static void SquareIt(int x)
// The parameter x is passed by value.
// Changes to x will not affect the original value of x.
{
x *= x;
System.Console.WriteLine("The value inside the method: {0}", x);
}
static void Main()
{
int n = 5;
System.Console.WriteLine("The value before calling the method: {0}", n);
Resultados
The value before calling the method: 5
The value inside the method: 25
The value after calling the method: 5
Resultados
The value before calling the method: 5
The value inside the method: 25
The value after calling the method: 25
Cuando se invoca este método, se debe utilizar la palabra clave ref en la llamada, como se muestra a continuación:
C#
static void Main()
{
int i = 2, j = 3;
System.Console.WriteLine("i = {0} j = {1}" , i, j);
Resultados
i = 2 j = 3
i = 3 j = 2
Vea también
Referencia
Pasar parámetros (Guía de programación de C#)
Pasar parámetros Reference-Type (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
C#
class PassingRefByVal
{
static void Change(int[] pArray)
{
pArray[0] = 888; // This change affects the original element.
pArray = new int[5] {-3, -1, -2, -3, -4}; // This change is local.
System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0])
;
}
Change(arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element
is: {0}", arr [0]);
}
}
Resultados
Inside Main, before calling the method, the first element is: 1
Inside the method, the first element is: -3
Inside Main, after calling the method, the first element is: 888
Change(ref arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element
is: {0}", arr[0]);
}
}
Resultados
Inside Main, before calling the method, the first element is: 1
Inside the method, the first element is: -3
Inside Main, after calling the method, the first element is: -3
Resultados
Inside Main, before swapping: John Smith
Inside the method: Smith John
Inside Main, after swapping: Smith John
class TestTaxi
{
static void Main()
{
Taxi t = new Taxi();
System.Console.WriteLine(t.isInitialized);
}
}
Un constructor que no toma ningún parámetro se denomina constructor predeterminado. Se invocan los constructores
predeterminados cada vez que se crea una instancia de un objeto mediante el operador new y no se proporciona ningún
argumento a new. Para obtener más información, vea Constructores de instancias (Guía de programación de C#).
A menos que la clase sea estática, a las clases sin constructores se les asigna un constructor público predeterminado a través
del compilador de C# con el fin de habilitar la creación de instancias de clases. Para obtener más información, vea
Clases estáticas y sus miembros (Guía de programación de C#).
Es posible evitar que se creen instancias de una clase mediante la conversión del constructor a privado, como se muestra a
continuación:
C#
class NLog
{
// Private Constructor:
private NLog() { }
Para obtener más información, vea Constructores privados (Guía de programación de C#).
Los constructores para los tipos struct son similares a los constructores de clases, pero los tipos structs no pueden contener
un constructor predeterminado explícito porque el compilador proporciona uno automáticamente. Este constructor inicializa
cada campo de la estructura en los valores predeterminados mostrados en la
Tabla de valores predeterminados (Referencia de C#). Sin embargo, este constructor predeterminado sólo se invoca si se crean
instancias de la estructura con new. Por ejemplo, en este código se utiliza el constructor predeterminado para Int32, lo que
garantiza que se inicializa el tipo integral:
Sin embargo, el código siguiente da como resultado el Error del compilador CS0165 porque no se utiliza new y se intenta
utilizar un objeto que no se ha inicializado:
int i;
Console.WriteLine(i);
Alternativamente, se pueden inicializar objetos basados en structs o asignarse y, a continuación, utilizarse de la forma
siguiente:
Cualquier constructor puede utilizar la palabra clave base para llamar al constructor de una clase base. Por ejemplo:
C#
public class Manager : Employee
{
public Manager(int annualSalary)
: base(annualSalary)
{
//Add further instructions here.
}
}
En este ejemplo, se llama al constructor de la clase base antes de ejecutar el bloque del constructor. La palabra clave base se
puede utilizar con o sin parámetros. Cualquier parámetro del constructor se puede utilizar como parámetro de base o como
parte de una expresión. Para obtener más información, vea base (Referencia de C#).
En una clase derivada, si no se llama explícitamente al constructor de la clase base mediante la palabra clave base, se llama
implícitamente al constructor predeterminado, si hay uno. Esto significa que las siguientes declaraciones del constructor son
efectivamente las mismas:
C#
public Manager(int initialdata)
{
//Add further instructions here.
}
C#
public Manager(int initialdata) : base()
{
//Add further instructions here.
}
Si una clase base no proporciona un constructor predeterminado, la clase derivada debe realizar una llamada explícita a un
constructor base mediante base.
Un constructor puede invocar a otro constructor en el mismo objeto a través de la palabra clave this. Al igual que base, this se
puede utilizar con o sin parámetros y cualquier parámetro en el constructor está disponible como parámetro para this o como
parte de una expresión. Por ejemplo, el segundo constructor del ejemplo anterior se puede rescribir con this:
C#
public Employee(int weeklySalary, int numberOfWeeks)
: this(weeklySalary * numberOfWeeks)
{
}
El uso de la palabra clave this utilizada anteriormente hace que este constructor se denomine:
C#
public Employee(int annualSalary)
{
salary = annualSalary;
}
Los constructores se pueden marcar como public, private, protected, internal o protected internal. Estos modificadores de
acceso definen cómo los usuarios de la clase pueden construir la clase. Para obtener más información, vea
Modificadores de acceso (Guía de programación de C#).
Un constructor se puede declarar como estático mediante la palabra clave static. Se llama automáticamente a los constructores
estáticos de forma inmediata antes de que se tenga acceso a cualquier campo estático y, normalmente, se utilizan para
inicializar los miembros de clase estáticos. Para obtener más información, vea
Constructores estáticos (Guía de programación de C#).
Especificación del lenguaje C#
Para obtener más información, vea las siguientes secciones en la Especificación del lenguaje C#:
1.6.6.1 Constructores
10.10 Constructores de instancia (Clases)
10.11 Constructores de instancia (Clases)
11.3.8 Constructores (Estructuras)
11.3.10 Constructores estáticos (Estructuras)
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Destructores (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Constructores (Guía de programación de C#)
Guía de programación de C#
// constructor
public CoOrds()
{
x = 0;
y = 0;
}
}
Nota
Para mayor claridad, esta clase contiene los miembros de datos públicos. Esto no es un buen hábito de programación porque
permite que cualquier método de cualquier parte del programa tenga acceso sin restricciones ni comprobaciones al trabajo i
nterno de un objeto. Los miembros de datos generalmente deberían ser privados y sólo se debería obtener acceso a ellos a t
ravés de los métodos y propiedades de clase.
Se llama a este constructor cada vez que se crea un objeto basado en la clase CoOrds. Un constructor como éste, que no toma
ningún argumento, se denomina constructor predeterminado. Sin embargo, suele ser útil proporcionar constructores
adicionales. Por ejemplo, se puede agregar a la clase CoOrds un constructor que permita especificar los valores iniciales de los
miembros de datos:
C#
// A constructor with two arguments:
public CoOrds(int x, int y)
{
this.x = x;
this.y = y;
}
Esto permite crear objetos CoOrd con valores iniciales concretos o predeterminados, del modo siguiente:
C#
CoOrds p1 = new CoOrds();
CoOrds p2 = new CoOrds(5, 3);
Si una clase no tiene un constructor predeterminado, se genera uno automáticamente y se utilizan los valores
predeterminados para inicializar los campos del objeto, por ejemplo, un campo de tipo int se inicializa en 0. Para obtener más
información sobre los valores predeterminados, vea Tabla de valores predeterminados (Referencia de C#). Por consiguiente,
como el constructor predeterminado de la clase CoOrds inicializa todos los miembros de datos en cero, se puede quitar del
todo sin cambiar el funcionamiento de la clase. En el ejemplo 1, más adelante en este tema, hay un objeto completo del uso de
varios constructores. Además, en el ejemplo 2 se proporciona un ejemplo de un constructor generado automáticamente.
Los constructores de instancia también se pueden utilizar para llamar a los constructores de instancia de clases base. El
constructor de clase puede invocar el constructor de la clase base a través del inicializador, del modo siguiente:
C#
class Circle : Shape
{
public Circle(double radius)
: base(radius, 0)
{
}
}
En este ejemplo, la clase Circle pasa los valores que representan el radio y alto al constructor proporcionado por Shape del
que se deriva Circle. En el ejemplo 3 de este tema aparece un ejemplo completo del uso de Shape y Circle.
Ejemplo 1
En el siguiente ejemplo se muestra una clase con dos constructores de clase, uno sin argumentos y el otro con dos
argumentos.
C#
class CoOrds
{
public int x, y;
// Default constructor:
public CoOrds()
{
x = 0;
y = 0;
}
// A constructor with two arguments:
public CoOrds(int x, int y)
{
this.x = x;
this.y = y;
}
class MainClass
{
static void Main()
{
CoOrds p1 = new CoOrds();
CoOrds p2 = new CoOrds(5, 3);
Resultado
CoOrds #1 at (0,0)
CoOrds #2 at (5,3)
Ejemplo 2
En este ejemplo, la clase Person no tiene ningún constructor, por lo que se proporciona automáticamente un constructor
predeterminado y los campos se inicializan con los valores predeterminados.
C#
public class Person
{
public int age;
public string name;
}
class TestPerson
{
static void Main()
{
Person p = new Person();
Resultado
Name: , Age: 0
Observe que el valor predeterminado de age es 0 y el de name es null. Para obtener más información sobre los valores
predeterminados, vea Tabla de valores predeterminados (Referencia de C#).
Ejemplo 3
En el siguiente ejemplo se muestra el uso del inicializador de clase base. La clase Circle se deriva de la clase general Shape y la
clase Cylinder se deriva de la clase Circle. El constructor utiliza su inicializador de clase base en cada clase derivada.
C#
abstract class Shape
{
public const double pi = System.Math.PI;
protected double x, y;
public Shape(double x, double y)
{
this.x = x;
this.y = y;
}
public abstract double Area();
}
class TestShapes
{
static void Main()
{
double radius = 2.5;
double height = 3.0;
Resultado
Area of the circle = 19.63
Area of the cylinder = 86.39
Para obtener más ejemplos sobre cómo invocar los constructores de clase base, vea virtual (Referencia de C#),
override (Referencia de C#) y base (Referencia de C#).
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Destructores (Guía de programación de C#)
static (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Constructores (Guía de programación de C#)
Guía de programación de C#
La declaración de un constructor vacío evita la generación automática de un constructor predeterminado. Observe que si no
utiliza un modificador de acceso en el constructor, éste será private de manera predeterminada. Sin embargo, normalmente se
utiliza el modificador private de manera explícita para aclarar que no es posible crear una instancia de la clase.
Los constructores privados se utilizan para evitar la creación de instancias de una clase cuando no hay campos o métodos de
instancia, por ejemplo la clase Math, o cuando se llama a un método para obtener una instancia de una clase. Si todos los
métodos de la clase son estáticos, considere convertir la clase completa en estática. Para obtener más información, vea
Clases estáticas y sus miembros (Guía de programación de C#).
Ejemplo
El siguiente es un ejemplo de clase que utiliza un constructor private.
C#
public class Counter
{
private Counter() { }
public static int currentCount;
public static int IncrementCount()
{
return ++currentCount;
}
}
class TestCounter
{
static void Main()
{
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
// Counter aCounter = new Counter(); // Error
Counter.currentCount = 100;
Counter.IncrementCount();
System.Console.WriteLine("New count: {0}", Counter.currentCount);
}
}
Resultado
New count: 101
Observe que si quita el comentario de la siguiente instrucción del ejemplo, se producirá un error porque el constructor es
inaccesible debido a su nivel de protección:
C#
// Counter aCounter = new Counter(); // Error
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
10.10.5 Constructores privados
25.2 Clases estáticas
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Destructores (Guía de programación de C#)
private (Referencia de C#)
public (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Constructores (Guía de programación de C#)
Guía de programación de C#
class TestBus
{
static void Main()
{
Bus.Drive();
}
}
Resultado
The static constructor invoked.
The Drive method invoked.
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Destructores (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Constructores (Guía de programación de C#)
Guía de programación de C#
// Instance constructor.
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
// Get accessor.
public string Details
{
get
{
return name + " is " + age.ToString();
}
}
}
class TestPerson
{
static void Main()
{
// Create a new person object.
Person person1 = new Person("George", 40);
Resultados
George is 40
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Destructores (Guía de programación de C#)
ICloneable
Conceptos
Guía de programación de C#
Otros recursos
Constructores (Guía de programación de C#)
Guía de programación de C#
El destructor llama implícitamente al método Finalize en la case base del objeto. Por lo tanto, el código de destructor anterior
se traduce implícitamente a:
Esto significa que se llama al método Finalize de forma recursiva para todas las instancias de la cadena de herencia, desde la
más derivada hasta la menos derivada.
Nota
No se deben utilizar destructores vacíos. Cuando una clase contiene un destructor, se crea una entrada en la cola Finalize. C
uando se llama al destructor, se invoca al recolector de elementos no utilizados para procesar la cola. Si el destructor está vac
ío, simplemente se produce una pérdida de rendimiento innecesaria.
El programador no puede controlar cuándo se llama al destructor, porque esto lo determina el recolector de elementos no
utilizados. El recolector de elementos no utilizados comprueba si hay objetos que ya no están siendo utilizados por ninguna
aplicación. Si considera un objeto elegible para su destrucción, llama al destructor (si existe) y reclama la memoria utilizada
para almacenar el objeto. También se llama a los destructores cuando se cierra el programa.
Es posible forzar la recolección de elementos no utilizados llamando al método Collect, pero en la mayoría de los casos debe
evitarse su uso por razones de rendimiento. Para obtener más información, vea
Forzar una recolección de elementos no utilizados.
Utilizar destructores para liberar recursos
En general, C# no requiere tanta administración de memoria como se necesita al desarrollar con un lenguaje que no está
diseñado para un motor en tiempo de ejecución con recolección de elementos no utilizados. Esto es debido a que el recolector
de elementos no utilizados de .NET Framework administra implícitamente la asignación y liberación de memoria para los
objetos. Sin embargo, cuando la aplicación encapsule recursos no administrados como ventanas, archivos y conexiones de red,
debería utilizar destructores para liberar dichos recursos. Cuando el objeto se marca para su destrucción, el recolector de
elementos no utilizados ejecuta el método Finalize.
Liberación explícita de recursos
Si la aplicación utiliza un recurso externo caro, también es recomendable liberar explícitamente el recurso antes de que el
recolector de elementos utilizados libere el objeto. Para ello debe implementar un método Dispose desde la interfaz
IDisposable que realiza la limpieza del objeto necesaria. Esto puede mejorar considerablemente el rendimiento de la aplicación.
Aunque controle explícitamente los recursos, el destructor garantiza la liberación de recursos si falla la llamada al método
Dispose.
Para obtener más detalles sobre la liberación de recursos, vea los siguientes temas:
Limpiar recursos no administrados
Implementar un método Dispose
using (Instrucción, Referencia de C#)
Ejemplo
En el siguiente ejemplo se crean tres clases que forman una cadena de herencia. La clase First es la clase base, Second se
deriva de First y Third se deriva de Second. Las tres tienen destructores. En Main(), se crea una instancia de la clase más
derivada. Cuando ejecute el programa, observe que se llama a los destructores de las tres clases automáticamente y en orden,
desde la más derivada hasta la menos derivada.
C#
class First
{
~First()
{
System.Console.WriteLine("First's destructor is called");
}
}
class TestDestructors
{
static void Main()
{
Third t = new Third();
}
}
Resultados
Third's destructor is called
Second's destructor is called
First's destructor is called
El acceso a un campo en un objeto se realiza agregando un punto después del nombre de objeto, seguido del nombre del
campo, como en objectname.fieldname. Por ejemplo:
C#
CalendarDate birthday = new CalendarDate();
birthday.month = 7;
Se puede proporcionar un valor inicial a un campo utilizando el operador de asignación cuando se declara el campo. Para
asignar automáticamente al campo month el valor 7, por ejemplo, declararía month de la manera siguiente:
C#
public class CalendarDateWithInitialization
{
public int month = 7;
//...
}
Los campos se inicializan inmediatamente antes de llamar al constructor para la instancia de objeto, de modo que si el
constructor asigna el valor de un campo, sobrescribirá cualquier valor dado durante la declaración del campo. Para obtener
más información, vea Utilizar constructores (Guía de programación de C#).
Nota
Un inicializador de campo no puede hacer referencia a campos de otra instancia.
Los campos se pueden marcar como public, private, protected, internal o protected internal. Estos modificadores de acceso
definen cómo pueden tener acceso a los campos los usuarios de la clase. Para obtener más información, vea
Modificadores de acceso (Guía de programación de C#).
Un campo puede declararse de forma opcional como static. Esto hace que el campo esté siempre disponible para los
llamadores, aunque no exista ninguna instancia de la clase. Para obtener más información, vea
Clases estáticas y sus miembros (Guía de programación de C#).
Un campo puede declararse como readonly. Sólo es posible asignar un valor a un campo de tipo readonly durante la
inicialización o en un constructor. Un campo static readonly es muy similar a una constante, excepto en que el compilador de
C# no tiene acceso a él en tiempo de compilación, sólo en tiempo de ejecución. Para obtener más información, vea
Constantes (Guía de programación de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.6.4 Campos
10.4 Campos
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Utilizar constructores (Guía de programación de C#)
Herencia (Guía de programación de C#)
Modificadores de acceso (Guía de programación de C#)
Clases y miembros de clase abstractos y sellados (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
En este ejemplo, la constante months siempre será 12 y no se puede cambiar, ni siquiera puede hacerlo la propia clase. Las
constantes tienen que ser de un tipo integral (sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal,
bool o string), una enumeración o una referencia a null.
Se pueden declarar varias constantes del mismo tipo al mismo tiempo, por ejemplo:
C#
class Calendar2
{
const int months = 12, weeks = 52, days = 365;
}
La expresión utilizada para inicializar una constante puede hacer referencia a otra constante siempre que no cree una
referencia circular. Por ejemplo:
C#
class Calendar3
{
const int months = 12;
const int weeks = 52;
const int days = 365;
Las constantes se pueden marcar como public, private, protected, internal o protectedinternal. Estos modificadores de acceso
definen cómo los usuarios de la clase pueden tener acceso a la constante. Para obtener más información, vea
Modificadores de acceso (Guía de programación de C#).
Es posible tener acceso a las constantes como si fueran campos estáticos, aunque no pueden utilizar la palabra clave static. Las
expresiones que no están contenidas dentro de la clase que define la constante deben usar el nombre de la clase, un punto y el
nombre de la constante para tener acceso a la constante. Por ejemplo:
C#
int birthstones = Calendar.months;
Independientemente de si los tipos externos son clases o estructuras, los tipos anidados se establecen de forma
predeterminada en private, pero pueden definirse como public, protected internal, protected, internal o private. En el ejemplo
anterior, Nested es inaccesible a los tipos externos, pero se puede establecer en public de la manera siguiente:
C#
class Container
{
public class Nested
{
Nested() { }
}
}
El tipo anidado o interno puede tener acceso al tipo contenedor o externo. Para tener acceso al tipo contenedor, páselo como
un constructor al tipo anidado. Por ejemplo:
C#
public class Container
{
public class Nested
{
private Container m_parent;
public Nested()
{
}
public Nested(Container parent)
{
m_parent = parent;
}
}
}
Los tipos anidados pueden tener acceso a los miembros private y protected del tipo contenedor, incluidos los miembros
private o protected heredados.
En la declaración anterior, el nombre completo de la clase Nested es Container.Nested. Éste es el nombre que se utiliza para
crear una nueva instancia de la clase anidada, como sigue:
C#
Container.Nested nest = new Container.Nested();
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Modificadores de acceso (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Constructores (Guía de programación de C#)
Guía de programación de C#
// private field:
private int m_wheels = 3;
// protected internal property:
protected internal int Wheels
{
get { return m_wheels; }
}
}
Otros tipos
Las interfaces, como las clases, se pueden declarar como tipos públicos o internos. A diferencia de las clases, las interfaces
establecen como valor predeterminado el acceso interno. Los miembros de interfaz siempre son públicos y no se puede aplicar
ningún modificador de acceso.
Los miembros de espacio de nombres y de enumeración siempre son públicos y no se puede aplicar ningún modificador de
acceso.
Los delegados tienen acceso interno de forma predeterminada.
Cualquier tipo declarado dentro de un espacio de nombres o en el nivel superior de una unidad de compilación (por ejemplo,
no dentro de un espacio de nombres, clase o estructura) es interno de forma predeterminada, pero se puede hacer público.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes en la Especificación del lenguaje C#:
10.2.3 Modificadores de acceso
Vea también
Referencia
Objetos, clases y estructuras (Guía de programación de C#)
Interfaces (Guía de programación de C#)
private (Referencia de C#)
public (Referencia de C#)
internal (Referencia de C#)
protected (Referencia de C#)
class (Referencia de C#)
struct (Referencia de C#)
interface (Referencia de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Comentarios
La utilización de la palabra clave partial indica que otras partes de la clase, estructura o interfaz se pueden definir dentro del
espacio de nombres. Todas las partes deben utilizar la palabra clave partial. Todas las partes deben estar disponibles en
tiempo de compilación para formar el tipo final. Todas las partes deben tener la misma accesibilidad, ya sea public, private, etc.
Si alguna de las partes se declara abstracta, todo el tipo se considera abstracto. Si alguna de las partes se declara sellada, todo
el tipo se considera sellado. Si alguna de las partes declara un tipo base, todo el tipo hereda esa clase.
Todas las partes que especifican una clase base deben concordar, pero las partes que omiten una clase base heredan
igualmente el tipo base. Las partes pueden especificar diferentes interfaces base, pero el tipo final implementa todas las
interfaces mostradas por todas las declaraciones parciales. Cualquier miembro de clase, estructura o interfaz declarados en
una definición parcial está disponible para todas las demás partes. El tipo final es la combinación de todas las partes en tiempo
de compilación.
Nota
El modificador partial no está disponible en declaraciones de delegado o enumeración.
Los tipos anidados pueden ser parciales, aunque el tipo en el que están anidados no sea propiamente parcial. Por ejemplo:
C#
class Container
{
partial class Nested
{
void Test() { }
}
partial class Nested
{
void Test2() { }
}
}
En tiempo de compilación, se combinan los atributos de definiciones de tipo parcial. Por ejemplo, las siguientes
declaraciones:
C#
[System.SerializableAttribute]
partial class Moon { }
[System.ObsoleteAttribute]
partial class Moon { }
equivalen a:
C#
[System.SerializableAttribute]
[System.ObsoleteAttribute]
class Moon { }
Los siguientes elementos se combinan a partir de todas las definiciones de tipo parcial:
comentarios XML
interfaces
atributos de parámetro de tipo genérico
atributos de clase
miembros
Por ejemplo, las siguientes declaraciones:
C#
partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }
equivalen a:
C#
class Earth : Planet, IRotate, IRevolve { }
Restricciones
Existen varias reglas que se deben seguir al trabajar con definiciones de clase parciales:
Todas las definiciones de tipo parcial creadas para ser parte del mismo tipo deben modificarse con partial. Por ejemplo,
las siguientes declaraciones de clase generan un error:
C#
public partial class A { }
//public class A { } // Error, must also be marked partial
El modificador partial sólo puede aparecer inmediatamente antes de las palabras clave class, struct o interface.
Se permiten tipos parciales anidados en definiciones de tipo parcial, por ejemplo:
C#
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
Todas las definiciones de tipo parcial que deben ser parte del mismo tipo deben definirse en el mismo ensamblado y el
mismo módulo (archivo .exe o .dll). Las definiciones parciales no pueden abarcar varios módulos.
Los parámetros de nombre de clase y tipo genérico deben coincidir en todas las definiciones de tipo parcial. Los tipos
genéricos pueden ser parciales. Todas las declaraciones parciales deben utilizar los mismos nombres de parámetro en el
mismo orden.
Las siguientes palabras clave en una definición de tipo parcial son opcionales, pero si hay alguna en una definición de
tipo parcial, no puede entrar en conflicto con las palabras clave especificadas en otra definición parcial para el mismo
tipo:
public
private
protected
internal
abstract
sealed
clase base
modificador new (partes anidadas)
restricciones genéricas (Para obtener más información, vea
Restricciones de tipos de parámetros (Guía de programación de C#)).
Ejemplo 1
Description
En el siguiente ejemplo, los campos y el constructor de la clase, CoOrds, se declaran en una definición de clase parcial, mientras
que el miembro PrintCoOrds se declara en otra definición de clase parcial.
C#
public partial class CoOrds
{
private int x;
private int y;
class TestCoOrds
{
static void Main()
{
CoOrds myCoOrds = new CoOrds(10, 15);
myCoOrds.PrintCoOrds();
}
}
Resultado
CoOrds: 10,15
Ejemplo 2
Description
El siguiente ejemplo muestra que también se pueden desarrollar estructuras e interfaces parciales.
C#
partial interface ITest
{
void Interface_Test();
}
partial struct S1
{
void Struct_Test() { }
}
partial struct S1
{
void Struct_Test2() { }
}
Estos métodos no necesitan adjuntarse a una instancia concreta de la clase. Por consiguiente, en lugar de crear instancias
innecesarias de esta clase, puede declararla como una clase estática; por ejemplo:
C#
static class CompanyInfo
{
public static string GetCompanyName() { return "CompanyName"; }
public static string GetCompanyAddress() { return "CompanyAddress"; }
//...
}
Utilice una clase estática como unidad de organización para métodos no asociados a objetos concretos. Además, una clase
estática puede hacer que la implementación sea más sencilla y rápida, porque no es necesario crear un objeto para llamar a
sus métodos. Es conveniente organizar los métodos dentro de la clase de forma significativa, como los métodos de la clase
Math del espacio de nombres System.
Miembros estáticos
Se puede llamar a métodos, campos, propiedades o eventos estáticos de una clase aunque no se haya creado ninguna
instancia de la misma. Si se crea alguna instancia de la clase, no puede utilizarse para tener acceso al miembro estático. Sólo
existe una copia de los campos y eventos estáticos, y los métodos y propiedades estáticos sólo pueden tener acceso a campos
y eventos estáticos. Los miembros estáticos suelen utilizarse para representar datos o cálculos que no cambian según el estado
del objeto; por ejemplo, una biblioteca matemática puede contener métodos estáticos para calcular el seno y el coseno.
Los miembros de clase estáticos se declaran utilizando la palabra clave static delante del tipo de valor devuelto del miembro,
por ejemplo:
C#
public class Automobile
{
public static int NumberOfWheels = 4;
public static int SizeOfGasTank
{
get
{
return 15;
}
}
public static void Drive() { }
public static event EventType RunOutOfGas;
Los miembros estáticos se inicializan antes de que se tenga acceso al miembro estático por primera vez y antes de llamar al
constructor estático, si se va a llamar a alguno. Para tener acceso a un miembro de clase estático, utilice el nombre de la clase
en lugar de un nombre de variable para especificar la ubicación del miembro. Por ejemplo:
C#
Automobile.Drive();
int i = Automobile.NumberOfWheels;
Ejemplo
Este es un ejemplo de clase estática que contiene dos métodos que convierten la temperatura de grados Celsius en Fahrenheit
y viceversa:
C#
public static class TemperatureConverter
{
public static double CelsiusToFahrenheit(string temperatureCelsius)
{
// Convert argument to double for calculations.
double celsius = System.Double.Parse(temperatureCelsius);
return fahrenheit;
}
public static double FahrenheitToCelsius(string temperatureFahrenheit)
{
// Convert argument to double for calculations.
double fahrenheit = System.Double.Parse(temperatureFahrenheit);
class TestTemperatureConverter
{
static void Main()
{
System.Console.WriteLine("Please select the convertor direction");
System.Console.WriteLine("1. From Celsius to Fahrenheit.");
System.Console.WriteLine("2. From Fahrenheit to Celsius.");
System.Console.Write(":");
default:
System.Console.WriteLine("Please select a convertor.");
break;
}
}
}
Entrada
2
98.6
Resultados de ejemplo:
Please select the convertor
1. From Celsius to Fahrenheit.
2. From Fahrenheit to Celsius.
:2
Please enter the Fahrenheit temperature: 98.6
Temperature in Celsius: 37.00
struct TheStruct
{
public string willIChange;
}
class TestClassAndStruct
{
static void ClassTaker(TheClass c)
{
c.willIChange = "Changed";
}
ClassTaker(testClass);
StructTaker(testStruct);
Resultados
Class field = Changed
Struct field = Not Changed
Vea también
Referencia
Pasar parámetros (Guía de programación de C#)
Conceptos
Guía de programación de C#
Clases (Guía de programación de C#)
Estructuras (Guía de programación de C#)
Guía de programación de C#
class Program
{
static void Main()
{
TimePeriod t = new TimePeriod();
Resultados
Time in hours: 24
En este ejemplo, Month se declara como una propiedad para que el descriptor de acceso set pueda asegurarse de que el valor
Month se establece entre 1 y 12. La propiedad Month utiliza un campo privado para realizar el seguimiento del valor real. La
ubicación real de los datos de una propiedad suele conocerse como "almacén de respaldo" de la propiedad. Es normal que las
propiedades utilicen campos privados como almacén de respaldo. El campo se marca como privado para asegurarse de que
sólo puede cambiarse llamando a la propiedad. Para obtener más información sobre restricciones de acceso público y privado,
vea Modificadores de acceso (Guía de programación de C#).
El descriptor de acceso get
El cuerpo del descriptor de acceso get es similar al de un método. Debe devolver el valor del tipo de la propiedad. La ejecución
del descriptor de acceso get equivale a leer el valor del campo. Por ejemplo, cuando se devuelve la variable privada del
descriptor de acceso get y las optimizaciones están habilitadas, el compilador pone la llamada al método del descriptor de
acceso get entre líneas para que no se produzca una sobrecarga de método-llamada. Sin embargo, un método de descriptor
de acceso get virtual no se puede poner entre líneas, porque el compilador no sabe en tiempo de compilación qué método
puede llamarse en tiempo de ejecución. A continuación, se muestra un descriptor de acceso get que devuelve el valor de un
campo privado name:
C#
class Person
{
private string name; // the name field
public string Name // the Name property
{
get
{
return name;
}
}
}
Cuando se haga referencia a la propiedad, se llamará al descriptor de acceso get para leer el valor de la misma, salvo en el
caso de que la referencia se haga como el destino de una asignación. Por ejemplo:
C#
Person p1 = new Person();
//...
System.Console.Write(p1.Name); // the get accessor is invoked here
El descriptor de acceso get debe terminar en una instrucción return o throw, y el control no puede salir del cuerpo del
descriptor de acceso.
Cambiar el estado de un objeto mediante el descriptor de acceso get es una técnica de programación poco recomendable. Por
ejemplo, el siguiente descriptor de acceso cambia, como efecto secundario, el estado del objeto cada vez que se tenga acceso al
campo number.
C#
private int number;
public int Number
{
get
{
return number++; // Don't do this
}
}
Se puede utilizar el descriptor de acceso get para devolver el valor de un campo o para calcularlo y devolverlo. Por ejemplo:
C#
class Employee
{
private string name;
public string Name
{
get
{
return name != null ? name : "NA";
}
}
}
Cuando se asigne un valor a la propiedad, se llamará al descriptor de acceso set con un argumento que proporciona el nuevo
valor. Por ejemplo:
C#
Person p1 = new Person();
p1.Name = "Joe"; // the set accessor is invoked here
No es correcto utilizar el nombre de parámetro implícito, value, para una declaración de variable local en un descriptor de
acceso set.
Comentarios
Las propiedades pueden marcarse como public, private, protected, internal o protected internal. Estos modificadores de
acceso definen cómo pueden tener acceso a las propiedades los usuarios de la clase. Los descriptores de acceso get y set para
la misma propiedad pueden tener modificadores de acceso diferentes. Por ejemplo, el descriptor de acceso get puede ser
public para permitir el acceso de sólo lectura desde fuera del tipo, y el descriptor de acceso set puede ser private o
protected. Para obtener más información, vea Modificadores de acceso (Guía de programación de C#).
Una propiedad puede declararse como propiedad estática mediante la palabra clave static. Esto hace que la propiedad esté
siempre disponible para los llamadores, aunque no exista ninguna instancia de la clase. Para obtener más información, vea
Clases estáticas y sus miembros (Guía de programación de C#).
Una propiedad puede marcarse como propiedad virtual mediante la palabra clave virtual. Esto permite que las clases derivadas
reemplacen el comportamiento de la propiedad mediante la palabra clave override. Para obtener más información sobre estas
opciones, vea Herencia (Guía de programación de C#).
Una propiedad que reemplaza una propiedad virtual también puede ser de tipo sealed, lo cual especifica que ya no es virtual
para las clases derivadas. Por último, una propiedad puede declararse como abstract, lo que significa que no hay ninguna
implementación en la clase y las clases derivadas deben escribir su propia implementación. Para obtener más información
sobre estas opciones, vea Clases y miembros de clase abstractos y sellados (Guía de programación de C#).
Nota
No es correcto utilizar un modificador virtual (Referencia de C#), abstract (Referencia de C#) o override (Referencia de C#) en
un descriptor de acceso de una propiedad static.
Ejemplo 1
En este ejemplo se muestra el uso de propiedades de instancia, estáticas y de sólo lectura. Lee el nombre del empleado escrito
mediante el teclado, incrementa el número de empleados NumberOfEmployees en una unidad y muestra el nombre del
empleado y su número correspondiente.
C#
public class Employee
{
public static int NumberOfEmployees;
private static int counter;
private string name;
// A Constructor:
public Employee()
{
// Calculate the employee's number:
counter = ++counter + NumberOfEmployees;
}
}
class TestEmployee
{
static void Main()
{
Employee.NumberOfEmployees = 100;
Employee e1 = new Employee();
e1.Name = "Claude Vige";
Resultado 1
Employee number: 101
Employee name: Claude Vige
Ejemplo 2
En este ejemplo se muestra el método para tener acceso a una propiedad de una clase base que está oculta por otra propiedad
con el mismo nombre de una clase derivada.
C#
public class Employee
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
class TestHiding
{
static void Main()
{
Manager m1 = new Manager();
Resultado 2
Name in the derived class is: John, Manager
Name in the base class is: Mary
Se utiliza la conversión (Employee) para tener acceso a la propiedad oculta de la clase base:
C#
((Employee)m1).Name = "Mary";
Para obtener más información sobre miembros ocultos, vea new (Modificador, Referencia de C#).
Ejemplo 3
En este ejemplo se utilizan dos clases, Cube y Square para implementar una clase abstracta, Shape, y reemplazar su propiedad
abstracta Area. Conviene resaltar que se utiliza el modificador override en las propiedades. El programa lee el valor del lado
como entrada y calcula las superficies del cuadrado y el cubo. También lee el valor de la superficie como entrada y calcula el
lado correspondiente del cuadrado y el cubo.
C#
abstract class Shape
{
public abstract double Area
{
get;
set;
}
}
public Cube(double s)
{
side = s;
}
class TestShapes
{
static void Main()
{
// Input the side:
System.Console.Write("Enter the side: ");
double side = double.Parse(System.Console.ReadLine());
Entrada
4
24
Resultado 3
Enter the side: 4
Area of the square = 16.00
Area of the cube = 96.00
Enter the area: 24
Side of the square = 4.90
Side of the cube = 2.00
Vea también
Tareas
Ejemplo de propiedades
Referencia
Propiedades (Guía de programación de C#)
Propiedades de interfaces (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Un identificador de acceso de una propiedad de interfaz no tiene cuerpo. Así, el propósito de los descriptores de acceso es
indicar si la propiedad es de lectura y escritura, de sólo lectura o de sólo escritura.
Ejemplo
En este ejemplo, la interfaz IEmployee tiene una propiedad de lectura y escritura, Name, y una propiedad de sólo lectura,
Counter. La clase Employee implementa la interfaz IEmployee y utiliza las dos propiedades. El programa lee el nombre de un
empleado nuevo y el número actual de empleados, y muestra como resultado el nombre del empleado y el nuevo número de
empleados calculado.
Se podría utilizar el nombre completo de la propiedad, que hace referencia a la interfaz en la que se declara el miembro. Por
ejemplo:
C#
string IEmployee.Name
{
get { return "Employee Name"; }
set { }
}
Esto se denomina Implementación explícita de interfaz (Guía de programación de C#). Por ejemplo, si la clase Employee
implementa dos interfaces ICitizen y IEmployee, y ambas tienen la propiedad Name, será necesario implementar
explícitamente el miembro de interfaz. Es decir, la siguiente declaración de propiedad:
C#
string IEmployee.Name
{
get { return "Employee Name"; }
set { }
}
class TestEmployee
{
static void Main()
{
System.Console.Write("Enter number of employees: ");
Employee.numberOfEmployees = int.Parse(System.Console.ReadLine());
Entrada
210
Hazem Abolrous
Vea también
Referencia
Propiedades (Guía de programación de C#)
Utilizar propiedades (Guía de programación de C#)
Comparación entre propiedades e indizadores (Guía de programación de C#)
Indizadores (Guía de programación de C#)
Interfaces (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
En este ejemplo, una propiedad denominada Name define un descriptor de acceso get y set. El descriptor de acceso get recibe
el nivel de accesibilidad de la misma propiedad, public en este caso, al mismo tiempo que el descriptor de acceso set se
restringe explícitamente aplicando el modificador de acceso protected al propio descriptor de acceso.
Restricciones en los modificadores y descriptores de acceso
El uso de modificadores de descriptores de acceso en propiedades o indizadores está sujeto a estas condiciones:
No se pueden utilizar modificadores de descriptores de acceso en una interfaz o en una implementación explícita de
miembro de interface.
Sólo se pueden utilizar los modificadores de descriptores de acceso si la propiedad o el indizador tiene descriptores de
acceso set y get. En este caso, sólo se permite el modificador en sólo uno de los dos descriptores de acceso.
Si la propiedad o el indizador tiene un modificador override, el modificador del descriptor de acceso debe coincidir con el
descriptor de acceso del descriptor de acceso de reemplazo, si corresponde.
El nivel de accesibilidad en el descriptor de acceso debe ser más restrictivo que el nivel de accesibilidad en la propiedad o
el indizador.
Modificadores de acceso en descriptores de acceso de reemplazo
Cuando se reemplaza una propiedad o un indizador, los descriptores de acceso reemplazados deben ser accesibles al código
de reemplazo. Además, el nivel de accesibilidad de la propiedad y del indizador, y de los descriptores de acceso debe coincidir
con la propiedad y el indizador reemplazado y los descriptores de acceso correspondientes. Por ejemplo:
C#
public class Parent
{
public virtual int TestProperty
{
// Notice the accessor accessibility level.
protected set { }
// No access modifier is used here.
get { return 0; }
}
}
public class Kid : Parent
{
public override int TestProperty
{
// Use the same accessibility level as in the overridden accessor.
protected set { }
// Cannot use access modifier here.
get { return 0; }
}
}
Implementar interfaces
Cuando utiliza un descriptor de acceso para implementar una interfaz, el descriptor de acceso no puede tener un modificador
de acceso. Sin embargo, si implementa la interfaz mediante un descriptor de acceso, como get, el otro descriptor de acceso
puede tener un modificador de acceso, como se muestra en el siguiente ejemplo:
C#
public interface ISomeInterface
{
int TestProperty
{
// No access modifier allowed here
// because this is an interface.
get;
}
}
public string Id
{
get { return id; }
set { }
}
}
class MainClass
{
static void Main()
{
BaseClass b1 = new BaseClass();
DerivedClass d1 = new DerivedClass();
b1.Name = "Mary";
d1.Name = "John";
b1.Id = "Mary123";
d1.Id = "John123"; // The BaseClass.Id property is called.
Resultado
Name and ID in the base class: Name-BaseClass, ID-BaseClass
Name and ID in the derived class: John, ID-BaseClass
Comentarios
Observe que si reemplaza la declaración new private string Id por new public string Id, obtiene el resultado:
Name and ID in the base class: Name-BaseClass, ID-BaseClass
Name and ID in the derived class: John, John123
Vea también
Referencia
Propiedades (Guía de programación de C#)
Indizadores (Guía de programación de C#)
Modificadores de acceso (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
set
{
m_Age = value;
}
}
public override string ToString()
{
return "Name = " + Name + ", Age = " + Age;
}
}
class TestPerson
{
static void Main()
{
// Create a new Person object:
Person person = new Person();
// Print out the name and the age associated with the person:
System.Console.WriteLine("Person details - {0}", person);
// Set some values on the person object:
person.Name = "Joe";
person.Age = 99;
System.Console.WriteLine("Person details - {0}", person);
Resultados
Person details - Name = N/A, Age = 0
Person details - Name = Joe, Age = 99
Person details - Name = Joe, Age = 100
Programación eficaz
En el ejemplo anterior, las propiedades Name y Age son public e incluyen un descriptor de acceso get y set. Esto permite que
cualquier objeto lea y escriba estas propiedades. Sin embargo, a veces es conveniente excluir uno de los descriptores de
acceso. Por ejemplo, al omitir el descriptor de acceso set, la propiedad pasa a ser de sólo lectura:
C#
public string Name
{
get
{
return m_name;
}
}
Opcionalmente, se puede exponer públicamente un descriptor de acceso pero definir el otro como private o protected. Para
obtener más información, vea Accesibilidad del descriptor de acceso asimétrico (Guía de programación de C#).
Una vez declaradas las propiedades, se pueden utilizar como si fueran campos de la clase. Esto permite una sintaxis muy
natural, tanto para obtener como para establecer el valor de una propiedad, como se muestra en las siguientes instrucciones:
C#
person.Name = "Joe";
person.Age = 99;
Observe que, en un método set de una propiedad, se dispone de una variable especial value. Esta variable contiene el valor
especificado por el usuario, por ejemplo:
C#
m_name = value;
Observe la sintaxis tan simple que se utiliza para incrementar la propiedad Age de un objeto Person:
C#
person.Age += 1;
Si se utilizaron métodos set y get independientes para modelar las propiedades, el código equivalente tendría el siguiente
aspecto:
person.SetAge(person.GetAge() + 1);
Observe que ToString no se utiliza explícitamente en el programa. Se invoca de forma predeterminada mediante las llamadas
WriteLine.
Vea también
Referencia
Propiedades (Guía de programación de C#)
Objetos, clases y estructuras (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Comentarios
El tipo de un indizador y el tipo de sus parámetros deben ser por lo menos tan accesibles como el propio indizador. Para más
información acerca de los niveles de accesibilidad, vea Modificadores de acceso.
La firma de un indizador está formada por el número de parámetros formales y sus tipos. No incluye el tipo de indizador ni los
nombres de los parámetros formales. Si se declara más de un indizador en una misma clase, cada indizador deberá tener una
firma diferente.
Los valores de un indizador no se clasifican como variables; por ello, no es posible transferir un valor de indizador como un
parámetro ref u out.
Para proporcionar un nombre al indizador que otros lenguajes puedan utilizar, use un atributo name en la declaración. Por
ejemplo:
[System.Runtime.CompilerServices.IndexerName("TheItem")]
public int this [int index] // Indexer declaration
{
}
Este indizador tendrá el nombre TheItem. Si no se proporciona el atributo con nombre, se le dará como nombre
predeterminado Item.
Ejemplo 1
En el ejemplo siguiente se muestra cómo declarar un campo de matriz privado, arr, y un indizador. El uso del indizador
permite el acceso directo a la instancia test[i]. La alternativa a utilizar el indizador es declarar la matriz como miembro de
tipo public y tener acceso directamente a sus miembros, arr[i].
C#
class IndexerClass
{
private int[] arr = new int[100];
public int this[int index] // Indexer declaration
{
get
{
// Check the index limits.
if (index < 0 || index >= 100)
{
return 0;
}
else
{
return arr[index];
}
}
set
{
if (!(index < 0 || index >= 100))
{
arr[index] = value;
}
}
}
}
class MainClass
{
static void Main()
{
IndexerClass test = new IndexerClass();
// Call the indexer to initialize the elements #3 and #5.
test[3] = 256;
test[5] = 1024;
for (int i = 0; i <= 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, test[i]);
}
}
}
Resultados
Element #0 = 0
Element #1 = 0
Element #2 = 0
Element #3 = 256
Element #4 = 0
Element #5 = 1024
Element #6 = 0
Element #7 = 0
Element #8 = 0
Element #9 = 0
Element #10 = 0
Conviene tener en cuenta que cuando se evalúa el acceso de un indizador, por ejemplo, en una instrucción Console.Write se
llama al descriptor de acceso get. Por ello, si no existe un descriptor de acceso get se producirá un error en tiempo de
compilación.
Indizar utilizando otros valores
C# no limita el tipo de índice al entero. Por ejemplo, puede ser útil utilizar una cadena con un indizador. Este tipo de indizador
podría implementarse buscando la cadena dentro de la colección y devolviendo el valor adecuado. Como se pueden
sobrecargar los descriptores de acceso, es posible la coexistencia de cadenas y enteros.
Ejemplo 2
En este ejemplo, se declara una clase que almacena los días de la semana. Se declara un descriptor de acceso get que toma
una cadena, el nombre de un día, y devuelve el entero correspondiente. Por ejemplo, Sunday devolverá 0, Monday devolverá 1,
y así sucesivamente.
C#
// Using a string as an indexer value
class DayCollection
{
string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };
Resultados
5
-1
Programación eficaz
Fundamentalmente, hay dos maneras de mejorar la seguridad y confiabilidad de los indizadores:
Asegúrese siempre de que su código realiza comprobaciones de intervalo y tipo cuando establece y recupera los valores
de cualquier búfer o matriz a la que tienen acceso los indizadores.
Establezca la accesibilidad de los descriptores de acceso get y set para que sea lo más restrictiva posible. Es importante
particularmente para el descriptor de acceso set. Para obtener más información, vea
Accesibilidad del descriptor de acceso asimétrico (Guía de programación de C#).
Vea también
Tareas
Ejemplo de indizadores
Referencia
Indizadores (Guía de programación de C#)
Propiedades (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
// Indexer declaration:
string this[int index]
{
get;
set;
}
}
La firma de un indizador debe ser diferente de las firmas de los demás indizadores declarados en la misma interfaz.
Ejemplo
En el ejemplo siguiente se muestra cómo se implementan indizadores de interfaz:
C#
// Indexer on an interface:
public interface ISomeInterface
{
// Indexer declaration:
int this[int index]
{
get;
set;
}
}
class MainClass
{
static void Main()
{
IndexerClass test = new IndexerClass();
// Call the indexer to initialize the elements #2 and #5.
test[2] = 4;
test[5] = 32;
for (int i = 0; i <= 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, test[i]);
}
}
}
Resultados
Element #0 = 0
Element #1 = 0
Element #2 = 4
Element #3 = 0
Element #4 = 0
Element #5 = 32
Element #6 = 0
Element #7 = 0
Element #8 = 0
Element #9 = 0
Element #10 = 0
En el ejemplo anterior, se podría usar la implementación de miembro de interfaz explícito mediante el nombre completo del
miembro de interfaz. Por ejemplo:
Sin embargo, el nombre completo sólo es necesario para evitar la ambigüedad cuando la clase implementa más de una
interfaz con la misma firma de indizador. Por ejemplo, si una clase Employee implementa dos interfaces, ICitizen y IEmployee,
y ambas tienen la misma firma de indizador, será necesario implementar explícitamente el miembro de interfaz. Es decir, la
siguiente declaración de indizador:
Los descriptores de acceso get de una propiedad Los descriptores de acceso get de un indizador tienen la misma lista de pará
no tienen parámetros. metros formales que el indizador.
Los descriptores de acceso set de una propiedad Los descriptores de acceso set de un indizador tienen la misma lista de pará
contienen el parámetro implícito value. metros formales que el indizador, además del parámetro value.
Vea también
Referencia
Indizadores (Guía de programación de C#)
Propiedades (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Cualquier método que coincide con la firma del delegado, que está compuesta por los parámetros y el tipo de valor devuelto,
puede asignarse al delegado. Esto permite el cambio mediante programación de las llamadas a métodos y la incorporación de
nuevo código en las clases existentes. Si conoce la firma del delegado, puede asignar su propio método delegado.
Esta capacidad para hacer referencia a un método como parámetro hace que los delegados sean idóneos para definir métodos
de devolución de llamada. Por ejemplo, un algoritmo de ordenación se podría pasar como referencia al método que compara
dos objetos. La separación del código de comparación permite programar el algoritmo de forma más general.
Información general sobre delegados
Los delegados tienen las propiedades siguientes:
Los delegados son similares a los punteros a función de C++, pero poseen seguridad de tipos.
Los delegados permiten pasar los métodos como parámetros.
Los delegados pueden utilizarse para definir métodos de devolución de llamada.
Los delegados pueden encadenarse; por ejemplo, se puede llamar a varios métodos en un solo evento.
No es necesario que los métodos coincidan exactamente con la firma de delegado. Para obtener más información, vea
Covarianza y contravarianza en los delegados (Guía de programación de C#).
La versión 2.0 de C# introduce el concepto de métodos anónimos, que permiten pasar bloques de código como
parámetros en lugar de utilizar métodos definidos independientemente.
En esta sección
Información general sobre delegados
Cuándo utilizar delegados en lugar de interfaces
Métodos con nombre
Métodos anónimos
Covarianza y contravarianza
Cómo: Combinar delegados
Cómo: Declarar un delegado, crear instancias del mismo y utilizarlo
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.11 Delegados
4.2.6 Tipos de delegado
7.5.5.2 Invocaciones de delegado
15 Delegados
Vea también
Referencia
Delegate
Conceptos
Guía de programación de C#
Eventos (Guía de programación de C#)
Guía de programación de C#
Generalmente, un objeto de delegado se crea proporcionando el nombre del método que el delegado contendrá o con un
método anónimo. Una vez que se crean instancias de un delegado, el delegado pasará al método una llamada realizada por
éste al delegado. Los parámetros que el llamador pasó al delegado se pasan al método y el delegado devuelve al llamador el
valor devuelto del método, si hay alguno. Esto se conoce como invocar al delegado. Se puede invocar un delegado con
instancias como si fuera el propio método contenido. Por ejemplo:
C#
// Create a method for a delegate.
public static void DelegateMethod(string message)
{
System.Console.WriteLine(message);
}
C#
// Instantiate the delegate.
Del handler = DelegateMethod;
Los tipos de delegados se derivan de la clase Delegate en .NET Framework. Los tipos de delegados son sealed (no se pueden
derivar) y no es posible derivar clases personalizadas de Delegate. Puesto que el delegado con instancias es un objeto, puede
pasarse como parámetro o asignarse a una propiedad. Esto permite que un método acepte un delegado como parámetro y
llame al delegado posteriormente. Esto se conoce como devolución de llamada asincrónica y constituye un método común de
notificación de un llamador cuando ha finalizado un proceso largo. Cuando se utiliza un delegado de esta forma, no es
necesario que el código que utiliza el delegado conozca la implementación del método que se está utilizando. La funcionalidad
es similar a la encapsulación que proporcionan las interfaces. Para obtener más información, vea
Cuándo se utilizan delegados en lugar de interfaces (Guía de programación de C#).
Otro uso común de devoluciones de llamada es definir un método de comparación personalizado y pasar ese delegado a un
método de ordenación. Esto permite al código del llamador ser parte del algoritmo de ordenación. El método del ejemplo
siguiente utiliza el tipo Del como parámetro:
C#
public void MethodWithCallback(int param1, int param2, Del callback)
{
callback("The number is: " + (param1 + param2).ToString());
}
Al utilizar el delegado como abstracción, MethodWithCallback no es necesario llamar a la consola directamente; es decir, el
delegado no se tiene que diseñar pensando en una consola. Lo que MethodWithCallback hace es simplemente preparar una
cadena y pasarla a otro método. Esto es especialmente eficaz, puesto que un método delegado puede utilizar cualquier número
de parámetros.
Cuando se crea un delegado para contener un método de instancia, el delegado hace referencia tanto a la instancia como al
método. Un delegado no conoce el tipo de instancia a parte del método que éste contiene, de modo que un delegado puede
hacer referencia a cualquier tipo de objeto siempre que exista un método en dicho objeto que coincida con la firma del
delegado. Cuando se crea un delegado para contener un método estático, éste sólo hace referencia al método. Considere las
siguientes declaraciones:
C#
public class MethodClass
{
public void Method1(string message) { }
public void Method2(string message) { }
}
Junto con el método estático DelegateMethod que se mostró previamente, ahora tenemos tres métodos que la instancia de Del
puede contener.
Un delegado puede llamar a más de un método cuando se invoca. Esto se denomina multidifusión. Para agregar un método
adicional a la lista de métodos del delegado (lista de invocación), simplemente es necesario agregar dos delegados mediante
los operadores de suma o de asignación de suma ('+' o '+='). Por ejemplo:
C#
MethodClass obj = new MethodClass();
Del d1 = obj.Method1;
Del d2 = obj.Method2;
Del d3 = DelegateMethod;
En este momento, allMethodsDelegate contiene tres métodos en su lista de invocación: Method1, Method2 y DelegateMethod.
Los tres delegados originales, d1, d2 y d3 no cambian. Cuando se invoca a allMethodsDelegate, se llama a los tres métodos por
orden. Si el delegado utiliza parámetros de referencia, ésta a su vez se pasa secuencialmente a cada uno de los tres métodos y
todos los cambios efectuados por un método son visibles para el siguiente método. Cuando alguno de los métodos produce
una excepción que no se detecta dentro del método, esa excepción se pasa al llamador del delegado y no se llama a ninguno
de los métodos siguientes de la lista de invocación. Si el delegado tiene un valor devuelto y/o fuera de los parámetros,
devuelve el valor devuelto y los parámetros del último método invocado. Para quitar un método de la lista de invocación,
utilice el operador de resta o de asignación de resta ('-' o '-='). Por ejemplo:
C#
//remove Method1
allMethodsDelegate -= d1;
// copy AllMethodsDelegate while removing d2
Del oneMethodDelegate = allMethodsDelegate - d2;
Puesto que los tipos de delegados se derivan de System.Delegate, los métodos y las propiedades definidos por esa clase se
pueden llamar en el delegado. Por ejemplo, para buscar el número de métodos en la lista de invocación de un delegado, puede
escribir:
C#
int invocationCount = d1.GetInvocationList().GetLength(0);
Los delegados con más de un método en su lista de invocación derivan de MulticastDelegate, que es una subclase de
System.Delegate. El código anterior funciona en ambos casos porque las dos clases admiten GetInvocationList.
Los delegados de multidifusión se utilizan ampliamente en el control de eventos. Los objetos de origen de eventos envían
notificaciones de eventos a objetos de destinatario registrados para recibir ese evento. Para registrar un evento, el destinatario
crea un método diseñado para controlar el evento, a continuación crea un delegado para dicho método y pasa al delegado al
origen de eventos. El origen llama al delegado cuando se produce el evento. Luego el delegado llama al método de control de
eventos del destinatario y entrega los datos del evento. El origen de eventos define el tipo de delegado para un evento dado.
Para obtener más información, vea Eventos (Guía de programación de C#).
La comparación de delegados de dos tipos distintos asignados en tiempo de compilación producirá un error de compilación. Si
las instancias de delegado son estáticamente del tipo System.Delegate, se permite la comparación, pero se devolverá false en
tiempo de ejecución. Por ejemplo:
C#
delegate void Delegate1();
delegate void Delegate2();
static void method(Delegate1 d, Delegate2 e, System.Delegate f)
{
// Compile-time error.
//Console.WriteLine(d == e);
Vea también
Referencia
Covarianza y contravarianza en los delegados (Guía de programación de C#)
Conceptos
Guía de programación de C#
Delegados (Guía de programación de C#)
Eventos (Guía de programación de C#)
Guía de programación de C#
Esto se denomina utilizar un método con nombre. Los delegados creados con un método con nombre pueden encapsular un
método estático o con instancias. La utilización de métodos con nombre es el único modo de crear instancias de un delegado
en versiones anteriores de C#. Sin embargo, en una situación en que crear un método nuevo constituye una sobrecarga no
deseada, C# 2.0 permite crear instancias de un delegado y especificar inmediatamente un bloque de código que el delegado
procesará cuando se le llame. Estos métodos se denominan Métodos anónimos (Guía de programación de C#).
Comentarios
El método, que se pasa como parámetro de delegado, debe tener la misma firma que la declaración de delegado.
La instancia de un delegado puede encapsular un método estático o de instancia.
Aunque el delegado puede utilizar un parámetro out, no se recomienda su uso con delegados de evento de multidifusión
porque no hay forma de saber a qué delegado se va a llamar.
Ejemplo 1
El siguiente es un ejemplo sencillo de declaración y uso de un delegado. Observe que tanto el delegado, Del, como el método
asociado, MultiplyNumbers, tienen la misma firma
C#
// Declare a delegate
delegate void Del(int i, double j);
class MathClass
{
static void Main()
{
MathClass m = new MathClass();
// Delegate instantiation using "MultiplyNumbers"
Del d = m.MultiplyNumbers;
Ejemplo 2
En el siguiente ejemplo, un delegado se asigna a métodos estáticos y de instancia y devuelve información específica de cada
uno de ellos.
C#
// Declare a delegate
delegate void Del();
class SampleClass
{
public void InstanceMethod()
{
System.Console.WriteLine("A message from the instance method.");
}
class TestSampleClass
{
static void Main()
{
SampleClass sc = new SampleClass();
Resultado
A message from the instance method.
A message from the static method.
Vea también
Tareas
Cómo: Combinar delegados (delegados de multidifusión) (Guía de programación de C#)
Conceptos
Guía de programación de C#
Delegados (Guía de programación de C#)
Eventos (Guía de programación de C#)
Guía de programación de C#
O bien,
C#
// Create a delegate instance
delegate void Del(int x);
Mediante los métodos anónimos, se reduce la sobrecarga de codificación al crear instancias de delegados sin tener que crear
un método independiente.
Por ejemplo, especificar un bloque de código en vez de un delegado puede ser útil en el caso de que la creación de un método
parezca una sobrecarga innecesaria. Un buen ejemplo es cuando se inicia un nuevo subproceso. Esta clase crea un subproceso
y también contiene el código que el subproceso ejecuta, sin necesidad de crear un método adicional para el delegado.
C#
void StartThread()
{
System.Threading.Thread t1 = new System.Threading.Thread
(delegate()
{
System.Console.Write("Hello, ");
System.Console.WriteLine("World!");
});
t1.Start();
}
Comentarios
El ámbito de los parámetros de un método anónimo es anonymous-method-block.
Es un error utilizar una instrucción de salto, como goto, break o continue, en un bloque de método anónimo cuyo destino está
fuera del bloque. También es un error utilizar una instrucción de salto, como goto, break o continue, fuera de un bloque de
método anónimo cuyo destino está dentro del bloque.
Las variables locales y los parámetros cuyo ámbito contiene una declaración de método anónimo se denominan variables
externas o capturadas del método anónimo. Por ejemplo, en el segmento de código siguiente, n es una variable externa:
C#
int n = 0;
Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };
A diferencia de las variables locales, el período de duración de la variable externa se extiende hasta que los delegados que
hacen referencia a los métodos anónimos cumplan con los requisitos para la recolección de elementos no utilizados. En el
momento en que se crea el delegado, se captura el valor de n.
Un método anónimo no puede tener acceso a los parámetros ref u out de un ámbito externo.
No se puede tener acceso a ningún código no seguro dentro de anonymous-method-block.
Ejemplo
El ejemplo siguiente muestra las dos maneras de crear instancias de un delegado:
Asociar el delegado a un método anónimo.
Asociar el delegado a un método con nombre (DoWork).
En cada uno de los casos, se muestra un mensaje cuando se invoca al delegado.
C#
// Declare a delegate
delegate void Printer(string s);
class TestClass
{
static void Main()
{
// Instatiate the delegate type using an anonymous method:
Printer p = delegate(string j)
{
System.Console.WriteLine(j);
};
Resultado
The delegate using the anonymous method is called.
The delegate using the named method is called.
Vea también
Referencia
Métodos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Delegados (Guía de programación de C#)
Código no seguro y punteros (Guía de programación de C#)
Métodos con nombre (Guía de programación de C#)
Otros recursos
Referencia de C#
Guía de programación de C#
class Program
{
// Define the delegate.
public delegate Mammals HandlerMethod();
Ejemplo 2 (contravarianza)
Este ejemplo muestra cómo se pueden utilizar los delegados con métodos que tienen parámetros de un tipo que son tipos
base del tipo de parámetro de la firma de delegado. Con la contravarianza, puede utilizar ahora un controlador de eventos en
lugares donde anteriormente tenía que utilizar controladores distintos. Por ejemplo, ahora puede crear un controlador de
eventos que acepte un parámetro de entrada EventArgs y utilizarlo con el evento Button.MouseClick que envía un tipo
MouseEventArgs como parámetro, y también con el evento TextBox.KeyDown que envía un parámetro KeyEventArgs.
C#
System.DateTime lastActivity;
public Form1()
{
InitializeComponent();
Vea también
Referencia
Delegados genéricos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Eventos (Guía de programación de C#)
Delegados (Guía de programación de C#)
Guía de programación de C#
class TestClass
{
static void Hello(string s)
{
System.Console.WriteLine(" Hello, {0}!", s);
}
Resultados
Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!
Vea también
Referencia
MulticastDelegate
Conceptos
Guía de programación de C#
Eventos (Guía de programación de C#)
Guía de programación de C#
C#
Del<int> d1 = new Del<int>(Notify);
El siguiente ejemplo ilustra la declaración, creación de instancias y uso de un delegado. La clase BookDB encapsula una base de
datos de los libros de una librería. Expone un método ProcessPaperbackBooks, el cual busca todos los libros en edición rústica
de la base de datos y llama a un delegado para cada uno. El tipo delegate que se utiliza se denomina ProcessBookDelegate.
La clase Test utiliza esta clase para imprimir los títulos y el precio medio de los libros en rústica.
El uso de delegados promueve una buena separación de la funcionalidad entre la base de datos de la librería y el código del
programa cliente. El código del cliente no tiene conocimiento de cómo están almacenados los libros ni de cómo busca el
código de la librería de los libros en rústica. El código de la librería no conoce qué procesamiento se realiza sobre los libros en
rústica después de encontrarlos.
Ejemplo
C#
// A set of classes for handling a bookstore:
namespace Bookstore
{
using System.Collections;
// Describes a book in the book list:
public struct Book
{
public string Title; // Title of the book.
public string Author; // Author of the book.
public decimal Price; // Price of the book.
public bool Paperback; // Is it paperback?
public Book(string title, string author, decimal price, bool paperBack)
{
Title = title;
Author = author;
Price = price;
Paperback = paperBack;
}
}
// Declare a delegate type for processing a book:
public delegate void ProcessBookDelegate(Book book);
// Maintains a book database.
public class BookDB
{
// List of all books in the database:
ArrayList list = new ArrayList();
Resultados
Paperback Book Titles:
The C Programming Language
The Unicode Standard 2.0
Dogbert's Clues for the Clueless
Average Paperback Book Price: $23.97
Programación eficaz
Declarar un delegado.
La siguiente instrucción:
C#
public delegate void ProcessBookDelegate(Book book);
declara un nuevo tipo delegado. Cada tipo delegado describe el número y tipo de los argumentos, así como el tipo del
valor devuelto de los métodos que puede encapsular. Cuando se necesita un nuevo conjunto de tipos de argumentos o
de valor devuelto, se debe declarar un nuevo tipo delegado.
Crear instancias de un delegado.
Una vez declarado un tipo delegado, debe crearse un objeto delegado y asociarlo con un determinado método. En el
ejemplo anterior, esto se hace pasando el método PrintTitle al método ProcessPaperbackBooks de la forma siguiente:
C#
bookDB.ProcessPaperbackBooks(PrintTitle);
Esto crea un nuevo objeto delegado asociado con el método estático Test.PrintTitle. Igualmente, el método no
estático AddBookToTotal del objeto totaller se pasa así:
C#
bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
Se puede llamar a un delegado de forma sincrónica, como en este ejemplo, o de forma asincrónica, utilizando los
métodos BeginInvoke y EndInvoke.
Vea también
Conceptos
Guía de programación de C#
Eventos (Guía de programación de C#)
Delegados (Guía de programación de C#)
Guía de programación de C#
La línea de código necesaria para suscribirse al evento también se genera automáticamente en el método
InitializeComponent en el archivo Form1.Designer.cs del proyecto. Presenta el aspecto siguiente:
2. Utilice el operador de suma y asignación (+ =) para asociar el controlador de eventos al evento. En el ejemplo siguiente,
se asume que un objeto denominado publisher tiene un evento denominado RaiseCustomEvent. Observe que la clase
de suscriptor necesita una referencia a la clase de editor para suscribirse a sus eventos.
publisher.RaiseCustomEvent += HandleCustomEvent;
Observe que la sintaxis anterior es nueva en C# 2.0. Al igual que en la sintaxis de C# 1.0, el delegado encapsulador debe
crearse explícitamente mediante la nueva palabra clave:
Es importante tener en cuenta que puede no resultar fácil cancelar la suscripción a un evento si se ha utilizado un método
anónimo para suscribirse a él. Para cancelar la suscripción en esta situación, regrese al código donde se ha suscrito al evento,
almacene el método anónimo en una variable de delegado y, a continuación, agregue el delegado al evento.
Cancelar una suscripción
Para impedir que se invoque el controlador de eventos cuando se produce el evento, basta con cancelar la suscripción al
evento. Para evitar que se pierdan recursos, es importante cancelar la suscripción a los eventos antes de eliminar un objeto
suscriptor. Hasta que se cancela la suscripción a un evento, el delegado multidifusión subyacente al evento en el objeto de
publicación tiene una referencia al delegado que encapsula el controlador de eventos del suscriptor. Mientras el objeto de
publicación mantenga esa referencia, el objeto suscriptor no se recolectará como elemento no utilizado.
Para cancelar la suscripción a un evento
Utilice el operador de resta y asignación (-=) para cancelar la suscripción a un evento:
publisher.RaiseCustomEvent -= HandleCustomEvent;
Cuando se haya cancelado la suscripción a un evento de todos los suscriptores, la instancia del evento en la clase de
editor se establecerá en null.
Vea también
Tareas
Cómo: Publicar eventos que cumplan las directrices de .NET Framework (Guía de programación de C#)
Referencia
event (Referencia de C#)
Operador -= (Referencia de C#)
Operador += (Referencia de C#)
Conceptos
Eventos (Guía de programación de C#)
Guía de programación de C#
Nota
.NET Framework 2.0 incluye una versión genérica de este delegado, EventHandler<T>. Los ejemplos siguientes muestran có
mo utilizar ambas versiones.
Aunque los eventos de las clases que defina se pueden basar en cualquier tipo de delegado válido, incluidos los delegados que
devuelven un valor, normalmente es aconsejable que los eventos se basen en el modo .NET Framework utilizando para ello
EventHandler, como se muestra en el ejemplo siguiente:
Para publicar eventos basados en el modelo EventHandler
1. (Omita este paso y vaya directamente al paso 3a si no tiene necesidad de enviar datos personalizados con el evento).
Declare la clase en un ámbito visible a las clases de editor y suscriptor, y agregue los miembros necesarios para
almacenar los datos de eventos personalizados. En este ejemplo, se devuelve una cadena simple.
2. (Omita este paso si utiliza la versión genérica de EventHandler). Declare un delegado en la clase de publicación.
Asígnele un nombre que acabe en EventHandler. El segundo parámetro especifica el tipo EventArgs personalizado.
b. Si utiliza la versión no genérica de EventHandler y tiene una clase personalizada derivada de EventArgs, declare el
evento dentro de la clase de publicación y use el delegado como tipo:
class Publisher
{
public event CustomEventHandler RaiseCustomEvent;
}
c. Si utiliza la versión genérica, no necesita un delegado personalizado. En lugar de ello, especifique el tipo de evento
como EventHandler<CustomEventArgs>, como sustituto del nombre de su propia clase incluido entre corchetes
angulares.
Ejemplo
El ejemplo siguiente muestra los pasos indicados anteriormente con una clase EventArgs personalizada y EventHandler<T>
como el tipo de evento.
C#
namespace DotNetEvents
{
using System;
using System.Collections.Generic;
}
// Wrap event invocations inside a protected virtual method
// to allow derived classes to override the event invocation behavior
protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
}
}
}
Vea también
Referencia
Delegate
Conceptos
Guía de programación de C#
Eventos (Guía de programación de C#)
Diseño de eventos
Delegados (Guía de programación de C#)
Guía de programación de C#
namespace BaseClassEvents
{
using System;
using System.Collections.Generic;
public ShapeEventArgs(double d)
{
newArea = d;
}
public double NewArea
{
get { return newArea; }
}
}
class Test
{
Resultados
Received event. Shape area is now 178.98
Drawing a circle
Received event. Shape area is now 49
Drawing a rectangle
Vea también
Referencia
Modificadores de acceso (Guía de programación de C#)
Conceptos
Guía de programación de C#
Eventos (Guía de programación de C#)
Delegados (Guía de programación de C#)
Otros recursos
Crear controladores de eventos en formularios Windows Forms
Guía de programación de C#
Ejemplo
El ejemplo siguiente muestra cómo controlar la situación menos común en la que la clase se hereda de dos o más interfaces y
cada interfaz tiene un evento con el mismo nombre. En esta situación, debe proporcionar una implementación de interfaz
explícita para al menos uno de los eventos. Cuando escriba una implementación de interfaz explícita para un evento, también
debe incluir los descriptores de acceso a eventos add y remove. Normalmente, estos descriptores los proporciona el
compilador, pero en este caso no es así.
Al proporcionar sus propios descriptores de acceso, puede especificar si los dos eventos se representan mediante el mismo
evento en la clase o mediante eventos diferentes. Por ejemplo, si los eventos deben producirse en momentos diferentes según
las especificaciones de la interfaz, puede asociar cada evento a una implementación distinta en la clase. En el ejemplo siguiente,
los suscriptores determinan qué evento OnDraw se recibirá convirtiendo la referencia de la forma en IShape o IDrawingObject.
C#
namespace WrapTwoInterfaceEvents
{
using System;
public interface IDrawingObject
{
// Raise this event before drawing
// the object.
event EventHandler OnDraw;
}
public interface IShape
{
// Raise this event after drawing
// the shape.
event EventHandler OnDraw;
}
Resultados
Sub1 receives the IDrawingObject event.
Drawing a shape.
Sub2 receives the IShape event.
Vea también
Tareas
Cómo: Producir eventos de una clase base en clases derivadas (Guía de programación de C#)
Referencia
Implementación explícita de interfaz (Guía de programación de C#)
Conceptos
Guía de programación de C#
Eventos (Guía de programación de C#)
Delegados (Guía de programación de C#)
Guía de programación de C#
public PropertyEventsSample()
{
eventTable = new System.Collections.Generic.Dictionary<string, System.Delegate>();
eventTable.Add("Event1", null);
eventTable.Add("Event2", null);
}
Resultados
2
TestString
Vea también
Conceptos
Guía de programación de C#
Eventos (Guía de programación de C#)
Delegados (Guía de programación de C#)
Manual del programador de .NET Framework
En el ejemplo de código siguiente se muestra cómo el código de cliente utiliza la clase genérica GenericList<T> para crear una
lista de enteros. Con sólo cambiar el argumento de tipo, el código que aparece a continuación se puede modificar fácilmente
para crear listas de cadenas o cualquier otro tipo personalizado:
C#
class TestGenericList
{
static void Main()
{
// int is the type argument
GenericList<int> list = new GenericList<int>();
Vea también
Referencia
System.Collections.Generic
Conceptos
Guía de programación de C#
Genéricos (Guía de programación de C#)
Guía de programación de C#
Pero esta conveniencia tiene su costo. Cualquier referencia o tipo de valor agregado a un objeto ArrayList se convierte
implícitamente a Object. Si los elementos son tipos de valor, se les debe aplicar la conversión boxing cuando se agregan a la
lista y la conversión unboxing cuando se recuperan. Tanto las operaciones de conversión de tipos como las de conversiones
boxing y unboxing degradan el rendimiento; el efecto de las conversiones boxing y unboxing puede ser muy importante en
escenarios donde se deben recorrer en iteración colecciones extensas.
La otra limitación es la ausencia de comprobación de tipos en tiempo de compilación; puesto que un objeto ArrayList
convierte todo a Object, en tiempo de compilación no hay forma de evitar que el código de cliente haga lo siguiente:
C#
System.Collections.ArrayList list = new System.Collections.ArrayList();
// Add an integer to the list.
list.Add(3);
// Add a string to the list. This will compile, but may cause an error later.
list.Add("It is raining in Redmond.");
int t = 0;
// This causes an InvalidCastException to be returned.
foreach (int x in list)
{
t += x;
}
Aunque es perfectamente válido y a veces intencionado si se crea una colección heterogénea, es probable que la combinación
de cadenas y valores ints en un objeto ArrayList único sea un error de programación, el cual no se detectará hasta el tiempo
de ejecución.
En las versiones 1.0 y 1.1 del lenguaje C#, se podían evitar los riesgos de utilizar código generalizado en las clases de colección
de la biblioteca de clases base de .NET Framework escribiendo colecciones propias específicas del tipo. Claro está que, como
dicha clase no se puede reutilizar para más de un tipo de datos, se pierden las ventajas de la generalización y se debe volver a
escribir la clase para cada uno de los tipos que se almacenarán.
Lo que ArrayList y otras clases similares realmente necesitan es un modo de que el código de cliente especifique, por
instancias, el tipo de datos particular que se va a utilizar. Eso eliminaría la necesidad de convertir a T:System.Object y también
haría posible que el compilador realizara la comprobación de tipos. Es decir, ArrayList necesita un type parameter. Eso es
precisamente lo que los tipos genéricos proporcionan. En la colección genérica List<T>, en el espacio de nombres
N:System.Collections.Generic, la misma operación de agregar elementos a la colección tiene la apariencia siguiente:
C#
// The .NET Framework 2.0 way to create a list
List<int> list1 = new List<int>();
// No boxing, no casting:
list1.Add(3);
// Compile-time error:
// list1.Add("It is raining in Redmond.");
En el código de cliente, la única sintaxis que se agrega con List<T> en comparación con ArrayList es el argumento de tipo en
la declaración y creación de instancias. A cambio de esta complejidad de codificación ligeramente mayor, se puede crear una
lista que no sólo es más segura que ArrayList, sino que también es bastante más rápida, en especial cuando los elementos de
lista son tipos de valor.
Vea también
Referencia
Introducción a los genéricos (Guía de programación de C#)
System.Collections.Generic
Conceptos
Guía de programación de C#
Guía de programación de C#
En cada una de estas instancias de GenericList<T>, cada aparición de T en la clase se sustituirá en tiempo de ejecución con el
argumento de tipo. Mediante esta sustitución, hemos creado tres objetos independientes y eficaces con seguridad de tipos
utilizando una sola definición de clase. Para obtener más información sobre cómo el CLR realiza esta sustitución, vea
Genéricos en el motor en tiempo de ejecución (Guía de programación de C#).
Instrucciones de nomenclatura de parámetros de tipo
Denomine los parámetros de tipo genérico con nombres descriptivos, a menos que un nombre de una sola letra sea
muy fácil de entender y un nombre descriptivo no agregue ningún valor.
C#
public interface ISessionChannel<TSession> { /*...*/ }
public delegate TOutput Converter<TInput, TOutput>(TInput from);
public class List<T> { /*...*/ }
Considere el uso de T como nombre del parámetro de tipo para los tipos con un parámetro de tipo de una sola letra.
C#
public int IComparer<T>() { return 0; }
public delegate bool Predicate<T>(T item);
public struct Nullable<T> where T : struct { /*...*/ }
Considere indicar las restricciones de un parámetro de tipo en el nombre del parámetro. Por ejemplo, un parámetro
restringido a ISession se puede denominar TSession.
Vea también
Referencia
Diferencias entre plantillas de C++ y tipos genéricos de C# (Guía de programación de C#)
System.Collections.Generic
Conceptos
Guía de programación de C#
Genéricos (Guía de programación de C#)
Guía de programación de C#
where T : class El argumento de tipo debe ser un tipo de referencia, entre los que se incluye cualquier clase, interfaz, delegad
o o tipo de matriz.
where T : new() El argumento de tipo debe tener un constructor público sin parámetros. Cuando se utiliza junto con otras res
tricciones, se debe especificar la restricción new() en último lugar.
where T : <nomb El argumento de tipo debe ser la clase base especificada, o bien debe derivarse de la misma.
re de clase base
>
where T: <nomb El argumento de tipo debe ser o implementar la interfaz especificada. Se pueden especificar varias restriccio
re de interfaz> nes de interfaz. La interfaz con restricciones también puede ser genérica.
where T : U El argumento de tipo proporcionado para T debe ser o derivarse del argumento proporcionado para U. Esto
se denomina una restricción de tipo naked.
Por qué utilizar restricciones
Si se desea examinar un elemento en una lista genérica para determinar si es válido o compararlo con otro elemento, el
compilador debe tener alguna garantía de que el operador o método que necesita llamar será compatible con cualquier
argumento de tipo que el código de cliente pudiera especificar. Esta garantía se obtiene al aplicar una o más restricciones a la
definición de clase genérica. Por ejemplo, la restricción de clase base le indica al compilador que sólo los objetos de este tipo o
derivados de éste se usarán como argumentos de tipo. Una vez que el compilador tiene esta garantía, puede permitir que se
llame a los métodos de ese tipo dentro de la clase genérica. Las restricciones se aplican mediante el uso de la palabra clave
contextual where. En el siguiente ejemplo de código se muestra la funcionalidad que se puede agregar a la clase
GenericList<T> (en Introducción a los genéricos (Guía de programación de C#)) mediante la aplicación de una restricción de
clase base.
C#
public class Employee
{
private string name;
private int id;
public T Data
{
get { return data; }
set { data = value; }
}
}
public T FindFirstOccurrence(string s)
{
Node current = head;
T t = null;
La restricción habilita la clase genérica para utilizar la propiedad Employee.Name, ya que está garantizado que todos los
elementos de tipo T son un objeto Employee o un objeto que se hereda de Employee.
Se pueden aplicar varias restricciones al mismo parámetro de tipo y las propias restricciones pueden ser tipos genéricos, como
se ve a continuación:
C#
class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
// ...
}
Al restringir el parámetro de tipo, se aumenta el número de operaciones permitidas y el método llama a aquellas admitidas
por el tipo de restricción y todos los tipos de su jerarquía de herencia. Por lo tanto, al diseñar clases o métodos genéricos, si se
va a realizar cualquier operación en los miembros genéricos más allá de una simple asignación o se va a llamar a cualquier
método que no está admitido por System.Object, será necesario aplicar restricciones al parámetro de tipo.
Al aplicar la restricción where T : class, se recomienda no utilizar los operadores == y != en el parámetro de tipo, ya que
éstos comprobarán sólo la identidad de referencias, no la igualdad de valores. Esto es aplicable aunque estos operadores se
sobrecarguen en un tipo utilizado como argumento. El código siguiente ilustra este punto; el resultado es false aunque la clase
String sobrecargue el operador ==.
C#
public static void OpTest<T>(T s, T t) where T : class
{
System.Console.WriteLine(s == t);
}
static void Main()
{
string s1 = "foo";
System.Text.StringBuilder sb = new System.Text.StringBuilder("foo");
string s2 = sb.ToString();
OpTest<string>(s1, s2);
}
La razón de este comportamiento es que, en tiempo de compilación, el compilador sabe que T es un tipo de referencia y que,
por lo tanto, debe usar los operadores predeterminados que son válidos para todos los tipos de referencia. Si necesita probar
la igualdad de valores, la forma recomendada es aplicar también la restricción where T : IComparable<T> e implementar esa
interfaz en cualquier clase que se vaya a utilizar para construir la clase genérica.
Parámetros de tipo sin delimitar
Los parámetros de tipo que no tienen restricciones, como T en la clase pública SampleClass<T>{}, se denominan parámetros
de tipo sin delimitar. Los parámetros de tipo sin delimitar tienen las siguientes reglas:
No se pueden utilizar los operadores != ni ==, porque no existe ninguna garantía de que el argumento de tipo concreto
admitirá estos operadores.
Pueden convertirse a o desde System.Object, o bien convertirse explícitamente en cualquier tipo de interfaz.
Se pueden comparar con null. Si un parámetro sin delimitar se compara con null, la comparación siempre devolverá
false si el argumento de tipo es un tipo de valor.
Restricciones de tipo naked
Cuando un parámetro de tipo genérico se utiliza como restricción, se denomina restricción de tipo naked. Las restricciones de
tipo naked son útiles cuando una función de miembro con su propio parámetro de tipo necesita restringir ese parámetro al
parámetro del tipo que lo contiene, como se muestra en el siguiente ejemplo:
C#
class List<T>
{
void Add<U>(List<U> items) where U : T {/*...*/}
}
En el ejemplo anterior, T es una restricción de tipo naked en el contexto del método Add y un parámetro de tipo sin delimitar
en el contexto de la clase List.
Las restricciones de tipo naked también se pueden utilizar en definiciones de clase genéricas. Observe que la restricción de tipo
naked también se debe declarar dentro de los corchetes angulares junto con cualquier otro parámetro de tipo:
C#
//naked type constraint
public class SampleClass<T, U, V> where T : V { }
La utilidad de las restricciones de tipo naked con clases genéricas es muy limitada, porque el compilador no puede suponer
nada acerca de la restricción de tipo naked excepto que se deriva de System.Object. Utilice las restricciones de tipo naked en
clases genéricas en escenarios en los que desea reforzar una relación de herencia entre dos parámetros de tipo.
Vea también
Referencia
Introducción a los genéricos (Guía de programación de C#)
Restricción new (Referencia de C#)
System.Collections.Generic
Conceptos
Guía de programación de C#
Guía de programación de C#
Las clases no genéricas (concretas) pueden heredar de las clases base construidas cerradas, pero no de las clases construidas
abiertas ni de los parámetros de tipo 'naked', porque no hay ninguna forma de que el código de cliente pueda proporcionar el
tipo de argumento necesario para crear una instancia de la clase base en tiempo de ejecución.
C#
//No error
class Node1 : BaseNodeGeneric<int> { }
//Generates an error
//class Node2 : BaseNodeGeneric<T> {}
//Generates an error
//class Node3 : T {}
Las clases genéricas que heredan de tipos construidos abiertos deben proporcionar argumentos de tipo para cada parámetro
de tipo de clase base no compartidos con la clase que hereda, tal como se muestra en el código siguiente:
C#
class BaseNodeMultiple<T, U> { }
//No error
class Node4<T> : BaseNodeMultiple<T, int> { }
//No error
class Node5<T, U> : BaseNodeMultiple<T, U> { }
//Generates an error
//class Node6<T> : BaseNodeMultiple<T, U> {}
Las clases genéricas que heredan de tipos construidos abiertos deben especificar restricciones que impliquen o sean un
superconjunto de las restricciones sobre el tipo base:
C#
class NodeItem<T> where T : System.IComparable<T>, new() { }
class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { }
Los tipos genéricos pueden utilizar varios parámetros y restricciones de tipo, de la forma siguiente:
C#
class SuperKeyType<K, V, U>
where U : System.IComparable<U>
where V : new()
{ }
Los tipos construidos abiertos y construidos cerrados se pueden utilizar como parámetros de método:
C#
void Swap<T>(List<T> list1, List<T> list2)
{
//code to swap items
}
Las clases genéricas son invariables. En otras palabras, si un parámetro de entrada especifica una List<BaseClass>, obtendrá
un error de compilación si intenta proporcionar una List<DerivedClass>.
Vea también
Referencia
System.Collections.Generic
Conceptos
Guía de programación de C#
Genéricos (Guía de programación de C#)
Guía de programación de C#
C#
//Type parameter T in angle brackets.
public class GenericList<T> : System.Collections.Generic.IEnumerable<T>
{
protected Node head;
protected Node current = null;
class Program
{
static void Main()
{
//Declare and instantiate a new generic SortedList class.
//Person is the type argument.
SortedList<Person> list = new SortedList<Person>();
int[] ages = new int[] { 45, 19, 28, 23, 18, 9, 108, 72, 30, 35 };
//Populate the list.
for (int x = 0; x < 10; x++)
{
list.AddHead(new Person(names[x], ages[x]));
}
Se pueden especificar varias interfaces como restricciones en un solo tipo, de la siguiente manera:
C#
class Stack<T> where T : System.IComparable<T>, IEnumerable<T>
{
}
Se aplican las mismas reglas de herencia a las interfaces que a las clases:
C#
interface IMonth<T> { }
Las interfaces genéricas pueden heredar de interfaces no genéricas si son contra-variantes, lo que significa que sólo utilizan su
parámetro de tipo como valor devuelto. En la biblioteca de clases de .NET Framework, IEnumerable<T> hereda de IEnumerable
porque IEnumerable<T> sólo utiliza T en el valor devuelto de GetEnumerator y en el receptor de la propiedad Current.
Las clases concretas pueden implementar interfaces construidas cerradas, de la siguiente manera:
C#
interface IBaseInterface<T> { }
Las clases genéricas pueden implementar interfaces genéricas o interfaces construidas cerradas siempre que la lista de
parámetros de la clase suministre todos los argumentos que necesita la interfaz, de la siguiente manera:
C#
interface IBaseInterface1<T> { }
interface IBaseInterface2<T, U> { }
El siguiente ejemplo de código muestra una manera de llamar al método, utilizando int para el argumento de tipo:
C#
public static void TestSwap()
{
int a = 1;
int b = 2;
También puede omitir el argumento de tipo y el compilador lo inferirá. La siguiente llamada a Swap es equivalente a la
llamada anterior:
C#
Swap(ref a, ref b);
Las mismas reglas para la inferencia de tipo se aplican a los métodos estáticos, como también a los métodos de instancia. El
compilador es capaz de inferir los parámetros de tipo basados en los argumentos de método que se traspasan; no es posible
inferir los parámetros de tipo únicamente a partir de una restricción o un valor devuelto. Por consiguiente, la inferencia de tipo
no funciona con métodos que no tienen parámetros. La inferencia de tipo tiene lugar en el tiempo de compilación antes de que
el compilador intente resolver cualquier firma de método sobrecargado. El compilador aplica la lógica de inferencia de tipo a
todos los métodos genéricos que comparten el mismo nombre. En el paso de resolución de sobrecarga, el compilador incluye
sólo aquellos métodos genéricos en los cuales la inferencia se realizó correctamente.
Dentro de una clase genérica, los métodos no genéricos pueden tener acceso a los parámetros de tipo de nivel de clase, como
sigue a continuación:
C#
class SampleClass<T>
{
void Swap(ref T lhs, ref T rhs) { }
}
Si define un método genérico que acepta los mismos parámetros de tipo que la clase contenedora, el compilador generará la
advertencia CS0693 porque dentro del ámbito del método, el argumento suministrado para la T interior ocultará el argumento
suministrado para la T exterior. Si se requiere la flexibilidad de llamar a un método de clase genérica con argumentos de tipo
diferentes a los proporcionados cuando la clase fue creada con instancias, considere proporcionar otro identificador para los
parámetros de tipo de método, como se muestra en GenericList2<T> en el siguiente ejemplo.
C#
class GenericList<T>
{
// CS0693
void SampleMethod<T>() { }
}
class GenericList2<T>
{
//No warning
void SampleMethod<U>() { }
}
Utilice las restricciones para habilitar las operaciones más especializadas en parámetros de tipo en métodos. Esta versión de
Swap<T>, ahora denominada SwapIfGreater<T>, sólo se puede utilizar con argumentos de tipo que implementan
IComparable<T>.
C#
void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
}
}
Los métodos genéricos se pueden sobrecargar en varios parámetros de tipo. Por ejemplo, los siguientes métodos pueden
existir en la misma clase:
C#
void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }
ProcessItems<int>(arr);
ProcessItems<int>(list);
}
Nota
Aunque el método ProcessItems no puede agregar ni quitar elementos, la propiedad IsReadOnly devuelve el valor falso par
a un T[] dentro de ProcessItems porque la propia matriz no se declaró con el atributo ReadOnly.
Vea también
Referencia
System.Collections.Generic
Conceptos
Guía de programación de C#
Genéricos (Guía de programación de C#)
Matrices (Guía de programación de C#)
Otros recursos
Genéricos en .NET Framework
Guía de programación de C#
C# 2.0 tiene una nueva función denominada conversión de grupo de métodos, que se aplica a los tipos delegados concretos y
genéricos, y permite escribir la línea anterior con esta sintaxis simplificada:
C#
Del<int> m2 = Notify;
Los delegados definidos dentro de una clase genérica pueden utilizar los parámetros de tipo de la clase genérica de la misma
manera que lo hacen los métodos de clase.
C#
class Stack<T>
{
T[] items;
int index;
El código que hace referencia al delegado debe especificar el argumento de tipo de la clase contenedora, de la siguiente
manera:
C#
private static void DoWork(float[] items) { }
Los delegados genéricos son especialmente útiles para definir eventos basados en el patrón de diseño habitual porque el
argumento del remitente puede tener establecimiento inflexible de tipos y ya no tiene que convertirse a y de Object.
C#
delegate void StackEventHandler<T, U>(T sender, U eventArgs);
class Stack<T>
{
public class StackEventArgs : System.EventArgs { }
public event StackEventHandler<Stack<T>, StackEventArgs> stackEvent;
protected virtual void OnStackChanged(StackEventArgs a)
{
stackEvent(this, a);
}
}
class SampleClass
{
public void HandleStackChange<T>(Stack<T> stack, Stack<T>.StackEventArgs args) { }
}
Vea también
Referencia
Introducción a los genéricos (Guía de programación de C#)
Métodos genéricos (Guía de programación de C#)
Clases genéricas (Guía de programación de C#)
Interfaces genéricas (Guía de programación de C#)
System.Collections.Generic
Conceptos
Guía de programación de C#
Delegados (Guía de programación de C#)
Otros recursos
Genéricos en .NET Framework
Guía de programación de C#
//...
public T GetNext()
{
T temp = default(T);
Vea también
Referencia
Métodos genéricos (Guía de programación de C#)
System.Collections.Generic
Conceptos
Guía de programación de C#
Genéricos (Guía de programación de C#)
Otros recursos
Genéricos en .NET Framework
Guía de programación de C#
C# no admite la especialización explícita; es decir, una implementación personalizada de una plantilla para un tipo
específico.
C# no admite la especialización parcial: una implementación personalizada para un subconjunto de argumentos de tipo.
C# no permite el uso del parámetro de tipo como clase base para el tipo genérico.
C# no permite que los parámetros de tipo tengan tipos predeterminados.
En C#, un parámetro de tipo genérico no puede ser genérico en sí mismo, aunque los tipos construidos se pueden utilizar
como genéricos. C++ permite los parámetros de plantilla.
C++ permite código que podría no ser válido para todos los parámetros de tipo de la plantilla, en la cual se busca el tipo
específico utilizado como parámetro de tipo. C# requiere que el código de una clase se escriba de tal forma que funcione
con cualquier tipo que cumpla con las restricciones. Por ejemplo, en C++ es posible escribir una función que usa los
operadores aritméticos + y - en objetos del parámetro de tipo, lo cual producirá un error en el momento de crear una
instancia de la plantilla con un tipo que no admita esos operadores. C# no permite esto; las únicas construcciones de
lenguaje permitidas son aquéllas que se pueden deducir de las restricciones.
Vea también
Referencia
Introducción a los genéricos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Templates
Guía de programación de C#
En este momento, el motor de ejecución genera una versión especializada de la clase Stack<T> sustituyendo el entero
adecuadamente para su parámetro. Ahora, cada vez que el código de su programa utilice una pila de enteros, el motor en
tiempo de ejecución reutilizará la clase especializada generada Stack<T>. En el ejemplo siguiente, se crean dos instancias de
una pila de enteros y comparten una instancia única del código Stack<int>:
C#
Stack<int> stackOne = new Stack<int>();
Stack<int> stackTwo = new Stack<int>();
No obstante, si en otro punto del código del programa se crea otra clase Stack<T>, esta vez con un tipo de valor distinto
como long o una estructura definida por el usuario como su parámetro, el motor en tiempo de ejecución genera otra versión
del tipo genérico, sustituyendo esta vez un long en las posiciones adecuadas en MSIL. Las conversiones ya no son necesarias
porque cada clase genérica especializada contiene de forma nativa el tipo de valor.
Los genéricos funcionan de forma ligeramente distinta para los tipos de referencia. Cuando se construye un tipo genérico por
primera vez con un tipo de referencia, el motor en tiempo de ejecución crea un tipo genérico especializado sustituyendo las
referencias a objetos para los parámetros del MSIL. A continuación, cada vez que se crea una instancia de un tipo construido
con un tipo de referencia como parámetro, independientemente del tipo que sea, el motor en tiempo de ejecución reutiliza la
versión especializada del tipo genérico previamente creada. Esto es posible porque todas las referencias son del mismo
tamaño.
Por ejemplo, suponga que tiene dos tipos de referencia, una clase Customer y una clase Order, y que creó una pila de tipos
Customer:
C#
class Customer { }
class Order { }
C#
Stack<Customer> customers;
En este punto, el motor en tiempo de ejecución genera una versión especializada de la clase Stack<T> que, en lugar de
almacenar los datos, almacena referencias a objetos que se rellenarán más tarde. Suponga que la línea siguiente de código
crea una pila de otro tipo de referencia, llamado Order:
C#
Stack<Order> orders = new Stack<Order>();
A diferencia de lo que sucede con los tipos de valor, no se crea otra versión especializada de la clase Stack<T> para el tipo
Order. Más bien, se crea una instancia de la versión especializada de la clase Stack<T> y se establece la variable orders para
hacer referencia a ella. Suponga que encuentra una línea de código para crear una pila de tipo Customer:
C#
customers = new Stack<Customer>();
Al igual que en el uso anterior de la clase Stack<T> creada con el tipo Order, se crea otra instancia de la clase especializada
Stack<T>, y los punteros que ésta contiene se establecen para hacer referencia a un área de memoria del tamaño de un tipo
Customer. Dado que el número de tipos de referencia puede variar significativamente de un programa a otro, la
implementación de genéricos de C@ reduce significativamente el tamaño del código limitando a uno el número de clases
especializadas creadas por el compilador para las clases genéricas de tipos de referencia.
Además, cuando se crea una instancia de una clase de C# genérica con un parámetro de tipo, ya sea un tipo de valor o de
referencia, se puede consultar en tiempo de ejecución mediante reflexión, y se puede comprobar su tipo real como el tipo de
su parámetro.
Vea también
Referencia
Introducción a los genéricos (Guía de programación de C#)
System.Collections.Generic
Conceptos
Guía de programación de C#
Otros recursos
Genéricos en .NET Framework
Guía de programación de C#
GetGenericArguments Devuelve una matriz de objetos Type que representan los argumentos de tipo suministrado
s para un tipo construido o los parámetros de tipo de una definición de tipo genérico.
GetGenericTypeDefinition Devuelve la definición de tipo genérico subyacente para el tipo construido actual.
GetGenericParameterConstraints Devuelve una matriz de objetos Type que representan las restricciones en el parámetro de ti
po genérico actual.
ContainsGenericParameters Devuelve true si el tipo o cualquiera de los tipos o métodos que incluye contiene parámetros
de tipo para los que no se han proporcionado tipos específicos.
GenericParameterPosition En un objeto Type que representa un parámetro de tipo, obtiene la posición de éste en la list
a de parámetros de tipo de la definición de tipo genérico o la definición de método genérico
que declaró el parámetro de tipo.
IsGenericParameter Obtiene un valor que indica si el objeto Type actual representa un parámetro de tipo de un ti
po genérico o de una definición de método.
IsGenericTypeDefinition Obtiene un valor que indica si el Type actual representa una definición de tipo genérico, a pa
rtir de la cual se pueden construir otros tipos genéricos. Devuelve true si el tipo representa la
definición de un tipo genérico.
DeclaringMethod Devuelve el método genérico que definió el parámetro de tipo genérico actual o null si un m
étodo genérico no define el parámetro de tipo.
MakeGenericType Sustituye los elementos de una matriz de tipos por los parámetros de tipo de la definición de
tipo genérico actual y devuelve un objeto Type que representa el tipo construido resultante.
Además, se agregan miembros nuevos a la clase MethodInfo para habilitar la información en tiempo de ejecución para los
métodos genéricos. Vea los comentarios de la propiedad IsGenericMethod para obtener una lista de condiciones invariables
que se utilizan para reflejarlas en métodos genéricos.
Nombre de miembro Syst Descripción
em.Reflection.MemberInf
o
IsGenericMethod Devuelve true si un método es genérico.
GetGenericArguments Devuelve una matriz de objetos Type que representan los argumentos de tipo de un método gen
érico construido o los parámetros de tipo de una definición de método genérico.
GetGenericMethodDefinition Devuelve la definición de método genérico subyacente para el método construido actual.
ContainsGenericParameters Devuelve true si el método o cualquiera de los tipos que incluye contiene cualquier parámetro de
tipo para el que no se han proporcionado tipos específicos.
IsGenericMethodDefinition Devuelve true si el objeto MethodInfo actual representa la definición de un método genérico.
MakeGenericMethod Sustituye los elementos de una matriz de tipos por los parámetros de tipo de la definición de mé
todo genérico actual y devuelve un objeto MethodInfo que representa el método construido res
ultante.
Vea también
Conceptos
Guía de programación de C#
Genéricos (Guía de programación de C#)
Información general sobre la reflexión y los genéricos
Otros recursos
Genéricos en .NET Framework
Guía de programación de C#
[CustomAttribute(info = typeof(GenericClass1<>))]
class ClassA { }
Especifique varios parámetros de tipo mediante el número adecuado de comas. En este ejemplo, GenericClass2 tiene dos
parámetros de tipo:
C#
public class GenericClass2<T, U> { }
[CustomAttribute(info = typeof(GenericClass2<,>))]
class ClassB { }
Un atributo que hace referencia a un parámetro de tipo genérico producirá un error de compilación:
C#
//[CustomAttribute(info = typeof(GenericClass3<int, T, string>))] //Error
class ClassD<T> { }
En este caso, podría tratar un objeto List<int> qué también es IEnumerable<int>, como IEnumerable<object>. Parece
razonable hacer esto, ya que int se puede convertir en un objeto. Es muy similar a poder tratar una cadena[] como objeto[] tal
como se puede hacer actualmente. Si se encuentra en esta situación, la característica que busca se llama varianza de genéricos.
Esta característica trata una creación de instancias de un tipo genérico, en este caso IEnumerable<int>, como una creación de
instancias diferente del mismo tipo, en este caso IEnumerable<object>.
C# no admite la varianza de tipos genéricos; por tanto, cuando encuentre situaciones como ésta, tendrá que probar una de las
técnicas que se pueden utilizar para evitar el problema. En los casos más simples, como el de un único método denominado
AddRange en el ejemplo anterior, puede declarar un método auxiliar sencillo que realice la conversión automáticamente. Por
ejemplo, podría escribir este método:
C#
// Simple workaround for single method
// Variance in one direction only
public static void Add<S, D>(List<S> source, List<D> destination)
where S : D
{
foreach (S sourceElement in source)
{
destination.Add(sourceElement);
}
}
Este ejemplo muestra algunas características de una solución de varianza sencilla. El método auxiliar toma dos parámetros de
tipo, para el origen y el destino, y el parámetro de tipo de origen S tiene una restricción que es el parámetro de tipo de destino
D. Esto significa que el objeto List<> del que se lee debe contener elementos que sean convertibles al tipo de elementos del
objeto List<> en el que se inserta. Esto permite al compilador forzar la conversión de int en un objeto. La restricción de un
parámetro de tipo para derivar de otro parámetro de tipo se denomina restricción de parámetro de tipo naked.
Definir un método único para evitar los problemas de varianza no está mal del todo. Desafortunadamente, los problemas de
varianza se pueden volver bastante complejos con rapidez. El nivel siguiente de complejidad es cuando se desea tratar una
interfaz de una creación de instancias como una interfaz de otra creación de instancias. Por ejemplo, tiene IEnumerable<int> y
desea pasarlo a un método que sólo toma IEnumerable<object>. Esto también tiene sentido, porque IEnumerable<object> se
puede considerar una secuencia de objetos e IEnumerable<int> es una secuencia de ints. Puesto que los valores ints son
objetos, debería ser posible tratar una secuencia de ints como una secuencia de objetos. Por ejemplo:
C#
static void PrintObjects(IEnumerable<object> objects)
{
foreach (object o in objects)
{
Console.WriteLine(o);
}
}
La solución para la interfaz case es crear un objeto contenedor que hace las conversiones de cada miembro de la interfaz. Esto
tendría una apariencia similar a lo siguiente:
C#
// Workaround for interface
// Variance in one direction only so type expressinos are natural
public static IEnumerable<D> Convert<S, D>(IEnumerable<S> source)
where S : D
{
return new EnumerableWrapper<S, D>(source);
}
De nuevo, observe la restricción de parámetro de tipo naked en la clase contenedora y el método auxiliar. Esta metodología
resulta bastante complicada pero el código de la clase contenedora es bastante sencillo; simplemente se delega en los
miembros de la interfaz contenedora, que no hace nada más que conversiones de tipo directas a medida que surgen. ¿Por qué
no hacer que el compilador permita directamente la conversión de IEnumerable<int> a IEnumerable<object>?
Aunque la varianza tiene seguridad de tipos en el caso de que se busquen vistas de sólo lectura de las colecciones, no la tiene
en el caso de que se realicen operaciones de lectura y escritura. Por ejemplo, la interfaz IList<> no se podría tratar de esta
manera automática. Sigue teniendo la opción de escribir un método auxiliar que ajuste todas las operaciones de lectura de
IList<> con seguridad de tipos, pero ajustar las operaciones de escritura no es tan sencillo.
Lo siguiente es una parte de un contenedor para tratar la varianza en la interfaz IList<T> que muestra los problemas que
surgen con la varianza en la lectura y la escritura:
C#
private class ListWrapper<S, D> : CollectionWrapper<S, D>, IList<D>
where S : D
{
public ListWrapper(IList<S> source) : base(source)
{
this.source = source;
}
El método Insert del contenedor tiene un problema. Toma como argumento D, pero debe insertarla en IList<S>. Como D es un
tipo base de S, no todo D es S, por lo que se puede producir un error en la operación de inserción. Este ejemplo tiene un
análogo con varianza en matrices. Cuando se inserta un objeto en un objeto[], se realiza una comprobación de tipo dinámico
porque el objeto[], de hecho, puede ser una cadena[] en tiempo de ejecución. Por ejemplo:
C#
object[] objects = new string[10];
En el ejemplo IList<>, el contenedor del método Insert puede producir simplemente una excepción cuando el tipo actual no
coincide con el tipo deseado en tiempo de ejecución. También en este caso se podía imaginar que el compilador generaría
automáticamente el contenedor para el programador. Sin embargo, hay situaciones en las que esta directiva no es la solución
correcta. El método IndexOf busca el elemento proporcionado en la colección y devuelve el índice de la colección si se
encuentra el elemento. Sin embargo, si no se encuentra el elemento, el método IndexOf simplemente devuelve -1, no produce
una excepción. Un contenedor generado automáticamente no puede proporcionar este tipo de ajuste.
Hasta ahora, se han descrito la dos formas más sencillas de evitar los problemas de varianza de genéricos. Sin embargo, los
problemas de varianza pueden volverse arbitrariamente complejos. Por ejemplo, cuando List<IEnumerable<int>> se trata
como List<IEnumerable<object>> o List<IEnumerable<IEnumerable<int>>> se trata como
List<IEnumerable<IEnumerable<object>>>.
La generación de estos contenedores para evitar los problemas de varianza en el código puede producir una sobrecarga
significativa en el código. Además, puede producir problemas de identidad de referencia, ya que los contenedores no tienen la
misma identidad que la colección original, lo que puede llevar a errores imperceptibles. Al utilizar los genéricos, se debe elegir
la creación de instancias de tipo para reducir las desigualdades entre componentes que se corresponden estrictamente. Esto
puede requerir algunos compromisos en el diseño del código. Como siempre, el diseño implica contrapartidas entre requisitos
que entran en conflicto y se deben tener en cuenta las restricciones del sistema de tipos del lenguaje en el proceso de diseño.
Hay sistemas de tipos que incluyen la varianza de genéricos como una primera parte de clase del lenguaje. Eiffel es un ejemplo
idóneo de esto. Sin embargo, incluir la varianza de genéricos como primera parte de clase del sistema de tipos aumentaría
significativamente la complejidad del sistema de tipos de C#, incluso en escenarios relativamente sencillos en los que no se
utilice varianza. Como resultado, los diseñadores de C# pensaron que no incluir la varianza era la opción correcta para C#.
A continuación se muestra el código fuente completo de los ejemplos anteriores.
C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public D Current
{
get { return this.source.Current; }
}
public void Dispose()
{
this.source.Dispose();
}
object IEnumerator.Current
{
get { return this.source.Current; }
}
namespace GenericVariance
{
class Program
{
static void PrintObjects(IEnumerable<object> objects)
{
foreach (object o in objects)
{
Console.WriteLine(o);
}
}
// does compile
VarianceWorkaround.Add<int, object>(ints, objects);
Vea también
Conceptos
Guía de programación de C#
Genéricos (Guía de programación de C#)
Guía de programación de C#
El tipo de valor devuelto de un iterador debe ser IEnumerable, IEnumerator, IEnumerable<T> o IEnumerator.
La palabra clave yield se utiliza para especificar el valor o valores devueltos. Cuando se llega a la instrucción yield return, se
almacena la ubicación actual. La ejecución se reinicia desde esta ubicación la próxima vez que se llame al iterador.
Los iteradores son especialmente útiles con las clases de colección, ya que proporcionan una manera fácil de recorrer en
iteración las estructuras de datos no triviales, por ejemplo, los árboles binarios.
Secciones relacionadas
Para obtener más información:
Utilizar iteradores (Guía de programación de C#)
Cómo: Crear un bloque de iteradores para una lista de enteros (Guía de programación de C#)
Cómo: Crear un bloque de iteradores para una lista genérica (Guía de programación de C#)
Interfaces genéricas (Guía de programación de C#)
Ejemplo
En este ejemplo, la clase DaysOfTheWeek es una clase de colección simple que almacena los días de la semana como cadenas.
Después de cada iteración de un bucle foreach, se devuelve la cadena siguiente en la colección.
C#
public class DaysOfTheWeek : System.Collections.IEnumerable
{
string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
Resultado
Sun Mon Tue Wed Thr Fri Sat
La presencia del método GetEnumerator transforma el tipo en un tipo enumerable y permite utilizar la instrucción foreach. Si el
método anterior formaba parte de una definición de clase para ListClass, sería posible utilizar foreach en la clase de la forma
siguiente:
C#
static void Main()
{
ListClass listClass1 = new ListClass();
La instrucción foreach invoca al método ListClass.GetEnumerator() y utiliza el enumerador que devuelve para recorrer en
iteración los valores. Para obtener un ejemplo de cómo crear un iterador genérico que devuelve una interfaz IEnumerator, vea
Cómo: Crear un bloque de iteradores para una lista genérica (Guía de programación de C#).
También es posible utilizar iteradores con nombre para admitir maneras diferentes de recorrer en iteración la misma colección
de datos. Por ejemplo, podría proporcionar un iterador que devuelve los elementos en orden ascendente y otro que los
devuelve en orden descendente. Un iterador también puede tener parámetros que permitan a los clientes controlar todo o
parte del comportamiento de iteración. El iterador siguiente implementa la interfaz IEnumerable utilizando el iterador con
nombre SampleIterator:
C#
// Implementing the enumerable pattern
public System.Collections.IEnumerable SampleIterator(int start, int end)
{
for (int i = start; i <= end; i++)
{
yield return i;
}
}
En cada iteración sucesiva del bucle foreach (o llamada directa a IEnumerator.MoveNext), el cuerpo del código del iterador
siguiente se reanuda después de la instrucción yield anterior y continúa a la siguiente hasta que se llega al final del cuerpo del
iterador o se encuentra una instrucción yield break.
Vea también
Tareas
Cómo: Crear un bloque de iteradores para una lista de enteros (Guía de programación de C#)
Cómo: Crear un bloque de iteradores para una lista genérica (Guía de programación de C#)
Referencia
yield (Referencia de C#)
Utilizar foreach son matrices (Guía de programación de C#)
foreach, in (Referencia de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
public SampleCollection()
{
items = new int[5] { 5, 4, 7, 9, 3 };
}
class MainClass
{
static void Main()
{
SampleCollection col = new SampleCollection();
Resultados
Values in the collection are:
5 4 7 9 3
Vea también
Tareas
Cómo: Crear un bloque de iteradores para una lista genérica (Guía de programación de C#)
Referencia
Utilizar iteradores (Guía de programación de C#)
yield (Referencia de C#)
Array
Conceptos
Guía de programación de C#
Iteradores (Guía de programación de C#)
Guía de programación de C#
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
// Iterate from top to bottom.
public IEnumerable<T> TopToBottom
{
get
{
// Since we implement IEnumerable<T>
// and the default iteration is top to bottom,
// just return the object.
return this;
}
}
// Iterate from bottom to top.
public IEnumerable<T> BottomToTop
{
get
{
for (int i = 0; i < top; i++)
{
yield return values[i];
}
}
}
//A parameterized iterator that return n items from the top
public IEnumerable<T> TopN(int n)
{
// in this example we return less than N if necessary
int j = n >= top ? 0 : top - n;
//This code uses a stack and the TopToBottom and BottomToTop properties
//to enumerate the elements of the stack.
class Test
{
static void Main()
{
Stack<int> s = new Stack<int>();
for (int i = 0; i < 10; i++)
{
s.Push(i);
}
// Prints: 9 8 7 6 5 4 3 2 1 0
// Foreach legal since s implements IEnumerable<int>
foreach (int n in s)
{
System.Console.Write("{0} ", n);
}
System.Console.WriteLine();
// Prints: 9 8 7 6 5 4 3 2 1 0
// Foreach legal since s.TopToBottom returns IEnumerable<int>
foreach (int n in s.TopToBottom)
{
System.Console.Write("{0} ", n);
}
System.Console.WriteLine();
// Prints: 0 1 2 3 4 5 6 7 8 9
// Foreach legal since s.BottomToTop returns IEnumerable<int>
foreach (int n in s.BottomToTop)
{
System.Console.Write("{0} ", n);
}
System.Console.WriteLine();
// Prints: 9 8 7 6 5 4 3
// Foreach legal since s.TopN returns IEnumerable<int>
foreach (int n in s.TopN(7))
{
System.Console.Write("{0} ", n);
}
System.Console.WriteLine();
}
}
}
Resultados
9 8 7 6 5 4 3 2 1 0
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3
Vea también
Tareas
Cómo: Crear un bloque de iteradores para una lista de enteros (Guía de programación de C#)
Referencia
Utilizar iteradores (Guía de programación de C#)
System.Collections.Generic
IEnumerable
Conceptos
Guía de programación de C#
Iteradores (Guía de programación de C#)
Guía de programación de C#
System es un espacio de nombres y Console es una clase incluida en ese espacio de nombres. Se puede utilizar la palabra
clave using a fin de que no se requiera el nombre completo, de la manera siguiente:
C#
using System;
C#
Console.WriteLine("Hello");
Console.WriteLine("World!");
Para obtener más información, vea el tema using (Directiva, Referencia de C#).
En segundo lugar, declarar espacios de nombres propios puede ayudar a controlar el ámbito de clase y nombres de método en
proyectos de programación grandes. Utilice la palabra clave namespace para declarar un espacio de nombres, como en el
ejemplo siguiente:
C#
namespace SampleNamespace
{
class SampleClass
{
public void SampleMethod()
{
System.Console.WriteLine(
"SampleMethod inside SampleNamespace");
}
}
}
En lugar de:
C#
System.Console.WriteLine("Hello, World!");
Nombres completos
Los espacios de nombres y tipos tienen nombres únicos que se describen mediante nombres completos que indican una
jerarquía lógica. Por ejemplo, la instrucción A.B implica que A es el nombre del espacio de nombres o tipo y que B está anidado
dentro de él.
En el siguiente ejemplo, se muestran clases y espacios de nombres anidados. El nombre completo se indica como un
comentario que sigue a cada entidad.
C#
namespace N1 // N1
{
class C1 // N1.C1
{
class C2 // N1.C1.C2
{
}
}
namespace N2 // N1.N2
{
class C2 // N1.N2.C2
{
}
}
}
En general, utilice :: para hacer referencia a un alias de espacio de nombres o global:: para hacer referencia al espacio de
nombres global y . para calificar tipos o miembros.
No es correcto utilizar :: con un alias que hace referencia a un tipo en lugar de a un espacio de nombres. Por ejemplo:
C#
using Alias = System.Console;
C#
class TestClass
{
static void Main()
{
// Error
//Alias::WriteLine("Hi");
// OK
Alias.WriteLine("Hi");
}
}
Tenga presente que la palabra global no es un alias predefinido; por consiguiente, global.X no tiene ningún significado
especial. Sólo adquiere un significado especial cuando se utiliza con ::.
Se genera una advertencia (vea Advertencia del compilador (nivel 2) CS0440) si se define un alias denominado global porque
global:: siempre hace referencia al espacio de nombres global y no a un alias. Por ejemplo, la línea siguiente genera la
advertencia:
C#
using global = System.Collections; // Warning
El uso de :: con alias es una buena idea y proporciona protección contra la introducción inesperada de tipos adicionales. Por
ejemplo, considere este ejemplo:
C#
using Alias = System;
C#
namespace Library
{
public class C : Alias.Exception { }
}
Esto funciona, pero si después se introdujera un tipo denominado Alias, Alias. se enlazaría en su lugar a ese tipo. El uso de
Alias::Exception asegura que Alias se trate como un alias de espacio de nombres y no se confunda con un tipo.
Vea el tema Cómo: Utilizar el calificador de alias del espacio de nombres (Guía de programación de C#) para obtener más
detalles relativos al alias global.
Vea también
Referencia
Palabras clave del espacio de nombres (Referencia de C#)
Operador . (Referencia de C#)
Operador :: (Referencia de C#)
extern (Referencia de C#)
Conceptos
Guía de programación de C#
Espacios de nombres (Guía de programación de C#)
Guía de programación de C#
C#
class TestApp
{
// Define a new class called 'System' to cause problems.
public class System { }
La utilización de System.Console aún produce un error porque la clase TestApp.System oculta el espacio de nombres
System:
C#
// Error Accesses TestApp.System
System.Console.WriteLine(number);
Sin embargo, este error se puede evitar utilizando global::System.Console, del modo siguiente:
C#
// OK
global::System.Console.WriteLine(number);
Cuando el identificador izquierdo es global, la búsqueda del identificador derecho se inicia en el espacio de nombres global.
Por ejemplo, la siguiente declaración hace referencia a TestApp como miembro del espacio global.
C#
class TestClass : global::TestApp
Obviamente, no se recomienda la creación de espacios de nombres propios denominados System y es improbable que se
encuentre algún código en el que se haya hecho esto. Sin embargo, en proyectos grandes, es muy posible que se pueda
producir la duplicación del espacio de nombres en un formulario u otro. En estas situaciones, el calificador de espacio de
nombres global es la garantía de que se puede especificar el espacio de nombres raíz.
Ejemplo
En este ejemplo, se utiliza el espacio de nombres System para incluir la clase TestClass; por lo tanto, se debe utilizar
global::System.Console para hacer referencia a la clase System.Console, que el espacio de nombres System oculta.
Además, el alias colAlias se utiliza para hacer referencia al espacio de nombres System.Collections; por consiguiente, la
instancia de un objeto System.Collections.Hashtable se crea con este alias en lugar del espacio de nombres.
C#
using colAlias = System.Collections;
namespace System
{
class TestClass
{
static void Main()
{
// Searching the alias:
colAlias::Hashtable test = new colAlias::Hashtable();
Vea también
Referencia
Operador . (Referencia de C#)
Operador :: (Referencia de C#)
extern (Referencia de C#)
Conceptos
Guía de programación de C#
Espacios de nombres (Guía de programación de C#)
Guía de programación de C#
Ejemplo
Este ejemplo llama a distintos métodos estáticos contenidos en el espacio de nombres MyServices. Para que este código se
compile, es necesario agregar al proyecto una referencia a Microsoft.VisualBasic.DLL.
C#
using System;
using Microsoft.VisualBasic.Devices;
class TestMyServices
{
static void Main()
{
// Play a sound with the Audio class:
Audio myAudio = new Audio();
Console.WriteLine("Playing sound...");
myAudio.Play(@"c:\WINDOWS\Media\chimes.wav");
if (myComputer.Network.IsAvailable)
{
Console.WriteLine("Computer is connected to network.");
}
else
{
Console.WriteLine("Computer is not connected to network.");
}
}
}
No todas las clases del espacio de nombres MyServices se pueden llamar desde una aplicación de C#: por ejemplo, la clase
FileSystemProxy no es compatible. En este caso particular, en lugar de esta clase se pueden utilizar los métodos estáticos que
forman parte de FileSystem, que también se encuentran en el archivo VisualBasic.dll. Por ejemplo, aquí se muestra cómo
utilizar un método de este tipo para duplicar un directorio:
C#
// Duplicate a directory
Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(
@"C:\original_directory",
@"C:\copy_of_original_directory");
Vea también
Conceptos
Guía de programación de C#
Espacios de nombres (Guía de programación de C#)
Utilizar espacios de nombres (Guía de programación de C#)
Guía de programación de C#
Utilice la propiedad System.Nullable.GetValueOrDefault para devolver el valor asignado o el valor predeterminado del
tipo subyacente si el valor es null, por ejemplo int j = x.GetValueOrDefault();
Utilice las propiedades de sólo lectura HasValue y Value para comprobar si el valor es NULL y recuperar el valor, por
ejemplo if(x.HasValue) j = x.Value;
La propiedad HasValue devuelve el valor verdadero si la variable contiene un valor, o falso si es NULL.
La propiedad Value devuelve un valor si se ha asignado uno; de lo contrario, devuelve
System.InvalidOperationException.
El valor predeterminado para una variable de tipo que acepta valores NULL establece HasValue a false. El Value
es indefinido.
Utilice el operador ?? para asignar un valor predeterminado que se aplicará cuando un tipo que acepta valores NULL
cuyo valor actual sea NULL se asigne a una tipo que no acepte valore NULL, por ejemplo int? x = null; int y = x ??
-1;
No se permite la anidación de tipos que aceptan valores NULL. La línea siguiente no se compilará:
Nullable<Nullable<int>> n;
Secciones relacionadas
Para obtener más información:
Utilizar tipos que aceptan valores NULL (Guía de programación de C#)
Aplicar la conversión boxing a tipos que aceptan valores NULL (Guía de programación de C#)
Operador ?? (Referencia de C#)
O bien
T? variable
T es el tipo subyacente del tipo que acepta valores NULL. T puede ser cualquier tipo de valor, incluso struct; no puede ser un
tipo de referencia.
Para obtener un ejemplo de cuándo se podría utilizar un tipo que acepta valores NULL, piense en una variable booleana
común que puede tener dos valores: true y false. No hay ningún valor que signifique "indefinido". En muchas aplicaciones de
programación, en particular interacciones de bases de datos, pueden existir variables con un estado indefinido. Por ejemplo, un
campo de una base de datos puede contener los valores true o false, pero también puede que no contenga ningún valor.
Igualmente, los tipos de referencia se pueden establecer en null para indicar que no se inicializan.
Esta disparidad puede crear trabajo de programación extra, con variables adicionales que se utilizan para almacenar
información de estado, el uso de valores especiales, etc. El modificador de tipos que aceptan valores NULL permite a C# crear
variables de tipo de valor que pueden indicar un valor indefinido.
Ejemplos de tipos que aceptan valores NULL
Cualquier tipo de valor se puede utilizar como base para un tipo que acepta valores NULL. Por ejemplo:
C#
int? i = 10;
double? d1 = 3.14;
bool? flag = null;
char? letter = 'a';
int?[] arr = new int?[10];
Value
Value es del mismo tipo que el tipo subyacente. Si HasValue es true, Value contiene un valor significativo. Si HasValue es
false, al tener acceso a Value se producirá una excepción InvalidOperationException.
En este ejemplo, el miembro HasValue se utiliza para comprobar si la variable contiene un valor antes de mostrarlo.
C#
int? x = 10;
if (x.HasValue)
{
System.Console.WriteLine(x.Value);
}
else
{
System.Console.WriteLine("Undefined");
}
Conversiones explícitas
Un tipo que acepta valores NULL se puede convertir en un tipo normal mediante el uso explícito de la conversión o a través de
la propiedad Value. Por ejemplo:
C#
int? n = null;
//int m1 = n; // Will not compile.
int m2 = (int)n; // Compiles, but will create an exception if x is null.
int m3 = n.Value; // Compiles, but will create an exception if x is null.
Si se define una conversión definida por el usuario entre dos tipos de datos, la misma conversión se puede utilizar con las
versiones que aceptan valores NULL de estos tipos de datos.
Conversiones implícitas
Una variable de tipo que acepta valores NULL se puede establecer como null con la palabra clave null, como se muestra a
continuación:
C#
int? n1 = null;
Operadores
Los operadores predefinidos unarios y binarios así como cualquier operador definido por el usuario que exista para los tipos
de valor también pueden ser utilizados por los tipos que aceptan valores NULL. Estos operadores generan un valor null si los
operandos son null; de lo contrario, el operador utiliza el valor contenido para calcular el resultado. Por ejemplo:
C#
int? a = 10;
int? b = null;
Al realizar comparaciones con tipos que aceptan valores null, si alguno de estos tipos es null, la comparación siempre se
evalúa como false. Por consiguiente, es importante no dar por supuesto que, porque una comparación sea false, el caso
contrario será true. Por ejemplo:
C#
int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
System.Console.WriteLine("num1 is greater than or equal to num1");
}
else
{
// num1 is NOT less than num2
}
La conclusión en la instrucción else anterior no es válida porque num2 es null y por consiguiente no contiene un valor.
Una comparación de dos tipos que aceptan valores null y ambos son null se evaluará como true.
El operador ??
El operador ?? define un valor predeterminado que se devuelve cuando un tipo que acepta valores NULL se asigna a un tipo
que no acepta valores NULL.
C#
int? c = null;
Este operador también se puede utilizar con muchos tipos que no aceptan valores NULL. Por ejemplo:
C#
int? e = null;
int? f = null;
// g = e or f, unless e and f are both null, in which case g = -1.
int g = e ?? f ?? -1;
El tipo bool?
El tipo bool?, que acepta valores NULL, puede contener tres valores diferentes: true, false y null. Como tal, no se puede utilizar
en instrucciones condicionales con if, for o while. Por ejemplo, este código no se puede compilar y produce el error
Error del compilador CS0266:
bool? b = null;
if (b) // Error CS0266.
{
}
Esto no se permite porque el significado de null en el contexto de una instrucción condicional es incierto. Los tipos booleanos
que aceptan valores NULL se pueden convertir explícitamente en bool para utilizarlos en una instrucción condicional, pero si el
objeto tiene un valor de null, se producirá una excepción InvalidOperationException. Por consiguiente, es importante
comprobar la propiedad HasValue antes de convertir a bool.
Los tipos booleanos que aceptan valores NULL son similares al tipo de variable booleano que se utiliza en SQL. Para
asegurarse de que los resultados producidos por los operadores & y | sean coherentes con el tipo booleano de tres valores de
SQL, se proporcionan los siguientes operadores predefinidos:
bool? operator &(bool? x, bool? y)
bool? operator |(bool? x, bool? y)
bool? b = null;
object o = b;
// Now o is null.
Si el objeto no es NULL (si HasValue es true), tiene lugar la conversión boxing, pero sólo se aplica al tipo subyacente en el que
se basa el objeto que acepta valores NULL. La conversión boxing de un tipo de valor no NULL que acepta valores NULL se
aplica al propio tipo de valor, no al objeto System.Nullable que ajusta el tipo de valor. Por ejemplo:
bool? b = false;
int? i = 44;
object bBoxed = b; // bBoxed contains a boxed bool.
object iBoxed = i; // iBoxed contains a boxed int.
Los dos objetos a los que se aplica la conversión boxing son idénticos a aquellos creados aplicando la conversión boxing a
tipos que no aceptan valores NULL. Además, al igual que los tipos sin conversión boxing que aceptan valores NULL, se les
puede aplicar la conversión unboxing en los tipos que aceptan valores NULL, del modo siguiente:
bool? b2 = (bool?)bBoxed;
int? i2 = (int?)iBoxed;
Comentarios
El comportamiento de los tipos que aceptan valores NULL cuando se aplica la conversión boxing proporciona dos ventajas:
1. Se comprueba si los objetos que aceptan valores NULL y sus homólogos a los que se aplica la conversión boxing tienen
valores NULL:
bool? b = null;
object boxedB = b;
if (b == null)
{
// True.
}
if (boxedB == null)
{
// Also true.
}
2. Los tipos que aceptan valores NULL y a los que se aplica la conversión boxing admiten la funcionalidad del tipo
subyacente:
double? d = 44.4;
object iBoxed = d;
// Access IConvertible interface implemented by double.
IConvertible ic = (IConvertible)iBoxed;
int i = ic.ToInt32(null);
string str = ic.ToString();
Para obtener más ejemplos de tipos que aceptan valores NULL y del comportamiento de la conversión boxing, vea
Ejemplo Nullable.
Vea también
Tareas
Cómo: Identificar tipos que aceptan valores NULL (Guía de programación de C#)
Conceptos
Guía de programación de C#
Tipos que aceptan valores NULL (Guía de programación de C#)
Guía de programación de C#
También puede utilizar las clases y métodos del espacio de nombres System.Reflection para generar objetos Type que
representen tipos que aceptan valores NULL. Sin embargo, si intenta obtener información de tipo de las variables que aceptan
valores NULL en tiempo de ejecución mediante el método GetType o el operador is, el resultado es un objeto Type que
representa el tipo subyacente y no el propio tipo que acepta valores NULL.
La llamada a GetType en un tipo que acepta valores NULL origina que se ejecute una operación de conversión boxing cuando
el tipo se convierte implícitamente en Object. Por consiguiente, GetType siempre devuelve un objeto Type que representa el
tipo subyacente y no el tipo que acepta valores NULL.
int? i = 5;
Type t = i.GetType();
Console.WriteLine(t.FullName); //"System.Int32"
El operador is de C# funciona también en el tipo subyacente de un tipo que acepta valores NULL. Por tanto, no puede utilizar is
para determinar si una variable es un tipo que acepta valores NULL. El ejemplo siguiente muestra que el operador is trata una
variable <int> que acepta valores NULL como un valor int.
Ejemplo
Utilice el código siguiente para determinar si un objeto Type representa un tipo que acepta valores NULL. Recuerde que este
código siempre devuelve false si el objeto Type se devuelve de una llamada a GetType, como se ha explicado anteriormente.
Vea también
Referencia
Aplicar la conversión boxing a tipos que aceptan valores NULL (Guía de programación de C#)
Conceptos
Tipos que aceptan valores NULL (Guía de programación de C#)
Guía de programación de C#
Comentarios
En versiones anteriores de C#, declarar una estructura de tamaño fijo con el estilo de C++ era difícil, porque una estructura de
C# que contiene una matriz, no contiene los elementos de la matriz, sino una referencia a ellos.
C# 2.0 agrega la capacidad de incrustar una matriz de tamaño fijo en un objeto struct cuando se utiliza en un bloque de código
unsafe.
Por ejemplo, antes de C# 2.0, los siguientes objetos struct tendrían un tamaño de 8 bytes, siendo la matriz pathName una
referencia a la matriz asignada por montón:
C#
public struct MyArray
{
public char[] pathName;
private int reserved;
}
En esta estructura, la matriz pathName es de tamaño y ubicación fijos y, por consiguiente, puede utilizarse con otro código no
seguro.
El tamaño de la matriz char de 128 elementos es 256 bytes. Los búferes char de tamaño fijo siempre admiten dos bytes por
carácter, independientemente de la codificación. Esto es verdadero, incluso cuando los búferes de caracteres se calculan por
referencia a los métodos API o estructuras con CharSet = CharSet.Auto o CharSet = CharSet.Ansi. Para obtener más
información, vea CharSet.
Otra matriz de tamaño fijo común es la matriz bool. Los elementos en una matriz bool siempre tienen un byte de tamaño: Las
matrices bool no son adecuadas para crear matrices de bits o búferes.
Nota
Con excepción de la memoria creada con stackalloc, el compilador de C# y el Common Language Runtime (CLR) no realizan
ninguna comprobación de saturación del búfer de seguridad. Como sucede con todo código no seguro, se ha de tener preca
ución.
Los búferes no seguros son diferentes de las matrices normales en los siguientes puntos:
Sólo se pueden utilizar búferes no seguros en un contexto no seguro.
Los búferes no seguros siempre son vectores, o matrices unidimensionales.
La declaración de la matriz debe incluir un recuento, por ejemplo, char id[8]. No puede utilizar char id[] en su lugar.
Los búferes no seguros sólo pueden ser campos de instancias de estructuras en un contexto no seguro.
Vea también
Tareas
Cómo: Llamar a archivos DLL nativos desde el código administrado mediante PInvoke
Cómo: Calcular referencias a matrices mediante PInvoke
Cómo: Calcular referencias de punteros incrustados mediante PInvoke
Cómo: Calcular referencias de punteros a función mediante PInvoke
Cómo: Calcular referencias de cadenas mediante PInvoke
Referencia
fixed (Instrucción, Referencia de C#)
Conceptos
Guía de programación de C#
Código no seguro y punteros (Guía de programación de C#)
Cálculo de referencias predeterminado para matrices
Guía de programación de C#
class Test
{
static int Main(string[] args)
{
if (args.Length != 1)
{
System.Console.WriteLine("Usage : ReadFile <FileName>");
return 1;
}
if (!System.IO.File.Exists(args[0]))
{
System.Console.WriteLine("File " + args[0] + " not found.");
return 1;
}
if (fr.Open(args[0]))
{
// Assume that an ASCII file is being read.
System.Text.ASCIIEncoding Encoding = new System.Text.ASCIIEncoding();
int bytesRead;
do
{
bytesRead = fr.Read(buffer, 0, buffer.Length);
string content = Encoding.GetString(buffer, 0, bytesRead);
System.Console.Write("{0}", content);
}
while (bytesRead > 0);
fr.Close();
return 0;
}
else
{
System.Console.WriteLine("Failed to open requested file");
return 1;
}
}
}
Vea también
Referencia
Tipos de puntero (Guía de programación de C#)
Conceptos
Guía de programación de C#
Código no seguro y punteros (Guía de programación de C#)
Otros recursos
Referencia de C#
Recolección de elementos no utilizados
Guía de programación de C#
type* identifier;
void* identifier; //allowed but not recommended
Un puntero no puede apuntar a una referencia o a una estructura que contenga referencias, porque es posible que la
referencia a un objeto se recolecte como elemento no utilizado aunque haya un puntero que apunte a ella. GC no controla si
hay tipos de punteros que apuntan a un objeto.
El valor de la variable de puntero de tipo myType* es la dirección de una variable de tipo myType. A continuación se muestran
ejemplos de declaraciones de tipo de puntero:
Ejemplo Descripción
int* p p es un puntero a un entero
El operador de direccionamiento indirecto de puntero * puede utilizarse para tener acceso al contenido de la ubicación
señalada por la variable de puntero. Por ejemplo, para la siguiente declaración,
int* myVariable;
la expresión *myVariable denota la variable int que se encuentra en la dirección contenida en myVariable.
No se puede aplicar el operador de direccionamiento indirecto a un puntero de tipo void*. Sin embargo, es posible utilizar una
conversión de tipos para convertir un puntero de tipo void en cualquier otro tipo de puntero y viceversa.
Un puntero puede ser null. La aplicación del operador de direccionamiento indirecto a un puntero nulo (null) da como
resultado un comportamiento definido según la implementación.
Tenga en cuenta que el paso de punteros entre métodos puede provocar un comportamiento no definido. Un ejemplo es la
devolución de un puntero a una variable local a través de un parámetro Out o Ref, o como resultado de la función. Si el
puntero se estableció en un bloque fijo, es posible que la variable a la que apunta ya no pueda ser fija.
La tabla siguiente muestra los operadores e instrucciones que pueden funcionar sobre punteros en un contexto no seguro:
Operador/instrucción Uso
* Para realizar el direccionamiento indirecto de puntero.
fixed (Instrucción) Para hacer que una variable sea temporalmente fija para que pueda encontrarse su dirección.
Especificación del lenguaje C#
Para obtener más información, vea la sección siguiente de Especificación del lenguaje C#.
18 Código no seguro
Vea también
Referencia
Conversiones de puntero (Guía de programación de C#)
Expresiones de puntero (Guía de programación de C#)
unsafe (Referencia de C#)
fixed (Instrucción, Referencia de C#)
stackalloc (Referencia de C#)
Conceptos
Guía de programación de C#
Código no seguro y punteros (Guía de programación de C#)
Conversión boxing y unboxing (Guía de programación de C#)
Otros recursos
Tipos (Referencia de C#)
Guía de programación de C#
La conversión de puntero explícita se utiliza para realizar conversiones para las que no existe conversión implícita utilizando
una expresión de conversión de tipos. La siguiente tabla muestra estas conversiones.
Conversiones de puntero explícitas
De Para
Cualquier tipo de puntero. Cualquier otro tipo de puntero
sbyte, byte, short, ushort, int, uint, long o ulong Cualquier tipo de puntero.
Cualquier tipo de puntero. sbyte, byte, short, ushort, int, uint, long o ulong
Ejemplo
En el ejemplo siguiente, un puntero a int se convierte en un puntero a byte. Observe que el puntero señala al byte
direccionado más bajo de la variable. Cuando incrementa sucesivamente el resultado, hasta el tamaño de int (4 bytes), puede
mostrar los bytes restantes de la variable.
C#
// compile with: /unsafe
C#
class ClassConvert
{
static void Main()
{
int number = 1024;
unsafe
{
// Convert to byte:
byte* p = (byte*)&number;
Vea también
Referencia
Expresiones de puntero (Guía de programación de C#)
Tipos de puntero (Guía de programación de C#)
unsafe (Referencia de C#)
fixed (Instrucción, Referencia de C#)
stackalloc (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Tipos (Referencia de C#)
Guía de programación de C#
*p;
No se puede utilizar el operador de direccionamiento indirecto unario en una expresión de cualquier tipo distinta de la del tipo
de puntero. Tampoco se puede aplicar a un puntero void.
Cuando se aplica el operador de direccionamiento indirecto a un puntero null, el resultado depende de la implementación.
Ejemplo
En el ejemplo siguiente, se tiene acceso a una variable del tipo char mediante punteros de tipos diferentes. Hay que tener en
cuenta que la dirección de theChar variará de una ejecución a otra porque la dirección física asignada a una variable puede
cambiar.
C#
// compile with: /unsafe
C#
unsafe class TestClass
{
static void Main()
{
char theChar = 'Z';
char* pChar = &theChar;
void* pVoid = pChar;
int* pInt = (int*)pVoid;
Vea también
Referencia
Expresiones de puntero (Guía de programación de C#)
Tipos de puntero (Guía de programación de C#)
unsafe (Referencia de C#)
fixed (Instrucción, Referencia de C#)
stackalloc (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Tipos (Referencia de C#)
Guía de programación de C#
int number;
int* p = &number; //address-of operator &
El operador de dirección sólo se puede aplicar a una variable. Si la variable es una variable móvil, puede utilizar la
instrucción fixed para fijar temporalmente la variable antes de obtener su dirección.
Es responsabilidad del usuario asegurarse de que se inicialice la variable. El compilador no emitirá un mensaje de error si no se
inicializa la variable.
No se puede obtener la dirección de una constante o un valor.
Ejemplo
En este ejemplo, se declara un puntero a int, p, y se le asigna la dirección de una variable de entero, number. La variable number
se inicializa como resultado de la asignación a *p. Comentar esta instrucción de asignación eliminará la inicialización de la
variable number, pero no se emitirá un error de compilación. Observe el uso del operador Acceso a miembros -> para obtener
y mostrar la dirección almacenada en el puntero.
C#
// compile with: /unsafe
C#
class AddressOfOperator
{
static void Main()
{
int number;
unsafe
{
// Assign the address of number to a pointer:
int* p = &number;
// Commenting the following statement will remove the
// initialization of number.
*p = 0xffff;
CoOrds* p = &home;
p -> x = 25; //member access operator ->
Ejemplo
En este ejemplo, se declara una estructura, CoOrds, que contiene dos coordenadas x e y y se crean instancias de la misma.
Utilizando el operador de acceso a miembros -> y un puntero a la instancia home, se asignan valores a x e y.
Nota
Observe que la expresión p->x es equivalente a la expresión (*p).x y se puede obtener el mismo resultado utilizando cualqu
iera de las dos expresiones.
C#
// compile with: /unsafe
C#
struct CoOrds
{
public int x;
public int y;
}
class AccessMembers
{
static void Main()
{
CoOrds home;
unsafe
{
CoOrds* p = &home;
p->x = 25;
p->y = 12;
System.Console.WriteLine("The coordinates are: x={0}, y={1}", p->x, p->y );
}
}
}
Vea también
Referencia
Expresiones de puntero (Guía de programación de C#)
Tipos de puntero (Guía de programación de C#)
unsafe (Referencia de C#)
fixed (Instrucción, Referencia de C#)
stackalloc (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Tipos (Referencia de C#)
Guía de programación de C#
La expresión entre corchetes debe poder convertirse implícitamente en int, uint, long o ulong. La operación p[e] es
equivalente a *(p+e). Al igual que en C y C++, el acceso al elemento de puntero no comprueba errores fuera de los límites.
Ejemplo
En este ejemplo, se asignan 123 ubicaciones de memoria a una matriz de caracteres, charPointer. La matriz se utiliza para
mostrar las letras en minúscula y en mayúscula en dos bucles for.
Observe que la expresión charPointer[i] es equivalente a la expresión *(charPointer + i) y se puede obtener el mismo
resultado utilizando cualquiera de las dos expresiones.
C#
// compile with: /unsafe
C#
class Pointers
{
unsafe static void Main()
{
char* charPointer = stackalloc char[123];
Vea también
Referencia
Expresiones de puntero (Guía de programación de C#)
Tipos de puntero (Guía de programación de C#)
unsafe (Referencia de C#)
fixed (Instrucción, Referencia de C#)
stackalloc (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Tipos (Referencia de C#)
Guía de programación de C#
++p;
P++;
--p;
p--;
Los operadores de incremento y decremento se pueden aplicar a punteros de cualquier tipo, a excepción del tipo void*.
El efecto de aplicar el operador de incremento a un puntero del tipo pointer-type es agregar sizeof (pointer-type) a la dirección
que se encuentra en la variable del puntero.
El efecto de aplicar el operador de decremento a un puntero del tipo pointer-type es restar sizeof (pointer-type) de la dirección
que se encuentra en la variable del puntero.
No se genera ninguna excepción cuando la operación desborda el dominio del puntero y el resultado depende de la
implementación.
Ejemplo
En este ejemplo, se avanza a través de una matriz incrementando el puntero según el tamaño de int. Con cada paso que
avanza, se muestra la dirección y el contenido del elemento de matriz.
C#
// compile with: /unsafe
C#
class IncrDecr
{
unsafe static void Main()
{
int[] numbers = {0,1,2,3,4};
Vea también
Referencia
Expresiones de puntero (Guía de programación de C#)
Operadores de C#
Manipular punteros (Guía de programación de C#)
Tipos de puntero (Guía de programación de C#)
unsafe (Referencia de C#)
fixed (Instrucción, Referencia de C#)
stackalloc (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Tipos (Referencia de C#)
Guía de programación de C#
Restar punteros
También es posible restar punteros del mismo tipo. El resultado siempre es de tipo long. Por ejemplo, si p1 y p2 son punteros
del tipo pointer-type*, entonces la expresión p1-p2 da como resultado:
((long)p1 - (long)p2)/sizeof(pointer_type)
No se genera ninguna excepción cuando la operación aritmética desborda el dominio del puntero y el resultado depende de la
implementación.
Ejemplo
C#
// compile with: /unsafe
C#
class PointerArithmetic
{
unsafe static void Main()
{
int* memory = stackalloc int[30];
long* difference;
int* p1 = &memory[4];
int* p2 = &memory[10];
difference = (long*)(p2 - p1);
Resultado
The difference is: 6
C#
class CompareOperators
{
unsafe static void Main()
{
int x = 234;
int y = 236;
int* p1 = &x;
int* p2 = &y;
Vea también
Referencia
Expresiones de puntero (Guía de programación de C#)
Operadores de C#
Manipular punteros (Guía de programación de C#)
Tipos de puntero (Guía de programación de C#)
unsafe (Referencia de C#)
fixed (Instrucción, Referencia de C#)
stackalloc (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Tipos (Referencia de C#)
Guía de programación de C#
C#
class TestCopy
{
// The unsafe keyword allows pointers to be used within the following method:
static unsafe void Copy(byte[] src, int srcIndex, byte[] dst, int dstIndex, int count)
{
if (src == null || srcIndex < 0 ||
dst == null || dstIndex < 0 || count < 0)
{
throw new System.ArgumentException();
}
// The following fixed statement pins the location of the src and dst objects
// in memory so that they will not be moved by garbage collection.
fixed (byte* pSrc = src, pDst = dst)
{
byte* ps = pSrc;
byte* pd = pDst;
Resultados
The first 10 elements are:
0 1 2 3 4 5 6 7 8 9
Vea también
Tareas
Ejemplo de código no seguro
Referencia
/unsafe (Habilitar modo Unsafe) (Opciones del compilador de C#)
Conceptos
Guía de programación de C#
Código no seguro y punteros (Guía de programación de C#)
Otros recursos
Recolección de elementos no utilizados
Guía de programación de C#
/// <summary>
/// This class performs an important function.
/// </summary>
public class MyClass{}
Cuando compila con la opción /doc, el compilador busca todas las etiquetas XML del código fuente y crea un archivo de
documentación XML.
Nota
Los comentarios de documentación XML no son metadatos; no se incluyen en el ensamblado compilado y, por tanto, no se p
uede obtener acceso a ellos mediante la reflexión.
En esta sección
Etiquetas recomendadas para comentarios de documentación
Procesar el archivo XML
Delimitadores para etiquetas de documentación
Cómo: Utilizar las características de documentación XML (Guía de programación de C#)
Secciones relacionadas
Para obtener más información al respecto, vea:
/doc (procesar comentarios de documentación)
Ejemplo XML Documentation
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
Apéndice A Comentarios de la documentación
Vea también
Conceptos
Guía de programación de C#
Guía de programación de C#
El compilador procesará cualquier etiqueta válida en XML. Las siguientes etiquetas proporcionan la funcionalidad habitual en la
documentación de usuario:
<c>text</c>
Parámetros
text
Texto que se desea marcar como código.
Comentarios
La etiqueta <c> proporciona un modo de indicar que el texto de una descripción se debería marcar como código. Utilice
<code> para marcar varias líneas como código.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<code>content</code>
Parámetros
content
Texto que se desea marcar como código.
Comentarios
La etiqueta <code> proporciona un modo de marcar varias líneas como código. Utilice <c> para indicar que el texto de una
descripción se debería marcar como código.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
Vea el tema <example> para obtener un ejemplo sobre la utilización de la etiqueta <code>.
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<example>description</example>
Parámetros
description
Descripción del ejemplo de código.
Comentarios
La etiqueta <example> permite especificar un ejemplo de cómo utilizar un método u otro miembro de una biblioteca.
Generalmente, esto supone utilizar la etiqueta <code>.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<exception cref="member">description</exception>
Parámetros
cref = "member"
Referencia a una excepción disponible desde el entorno de compilación actual. El compilador comprueba si existe la
excepción dada y convierte member al nombre de elemento canónico en el resultado XML. member debe aparecer entre
comillas dobles (" ").
Para obtener más información sobre cómo crear una referencia cref a un tipo genérico, vea
<see> (Guía de programación de C#).
description
Descripción de la excepción.
Comentarios
La etiqueta <exception> permite especificar las excepciones que se pueden producir. Esta etiqueta puede aplicarse a las
definiciones de métodos, propiedades, eventos e indizadores.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Parámetros
filename
Nombre del archivo que contiene la documentación. El nombre de archivo se puede completar con una ruta de acceso.
Agregue filename entre comillas simples (' ').
tagpath
Ruta de acceso de las etiquetas de filename que conduce a la etiqueta name. Ponga la ruta de acceso entre comillas simples
(' ').
name
Especificador de nombre en la etiqueta que precede a los comentarios; name poseerá un id.
id
Identificador para la etiqueta que precede a los comentarios. Ponga el id. entre comillas dobles (" ").
Comentarios
La etiqueta <include> permite hacer referencia a comentarios colocados en otro archivo que describen los tipos y miembros
del código fuente. Ésta es una alternativa al método habitual de colocar los comentarios de la documentación directamente en
el archivo de código fuente.
La etiqueta <include> utiliza la sintaxis XPath de XML. Consulte la documentación de XPath para conocer diversos modos de
personalizar el uso de <include>.
Ejemplo
Este ejemplo utiliza varios archivos. El primer archivo, que utiliza <include>, se muestra a continuación:
C#
// compile with: /doc:DocFileName.xml
/// <include file='xml_include_tag.doc' path='MyDocs/MyMembers[@name="test"]/*' />
class Test
{
static void Main()
{
}
}
/// <include file='xml_include_tag.doc' path='MyDocs/MyMembers[@name="test2"]/*' />
class Test2
{
public void Test()
{
}
}
<MyDocs>
<MyMembers name="test">
<summary>
The summary for this type.
</summary>
</MyMembers>
<MyMembers name="test2">
<summary>
The summary for this other type.
</summary>
</MyMembers>
</MyDocs>
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Parámetros
term
Término que se define en description.
description
Elemento de una lista numerada o con viñetas, o definición de un term.
Comentarios
El bloque <listheader> se utiliza para definir la fila de encabezado de una tabla o de una lista de definiciones. Cuando se define
una tabla, sólo es necesario suministrar una entrada para un término en el encabezado.
Cada elemento de la lista se especifica con un bloque <item>. Cuando se crea una lista de definiciones, se deberán especificar
tanto term como description. Sin embargo, para una tabla, lista con viñetas o lista numerada, sólo es necesario suministrar una
entrada para description.
Una lista o una tabla pueden tener tantos bloques <item> como sean necesarios.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<para>content</para>
Parámetros
content
Texto del párrafo.
Comentarios
La etiqueta <para> se utiliza dentro de otra etiqueta, tal como <summary>, <remarks> o <returns>, y permite dar una
estructura al texto.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
Vea <summary> para obtener un ejemplo del uso de <para>.
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<param name='name'>description</param>
Parámetros
name
Nombre de un parámetro de método. Ponga el nombre entre comillas dobles (" ").
description
Descripción del parámetro.
Comentarios
La etiqueta <param> se debe utilizar en el comentario de una declaración de método para describir uno de los parámetros del
método.
El texto para la etiqueta <param> se mostrará en IntelliSense, el Examinador de objetos y en el Informe Web de comentario de
código.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<paramref name="name"/>
Parámetros
name
Nombre del parámetro al que hay que hacer referencia. Ponga el nombre entre comillas dobles (" ").
Comentarios
La etiqueta <paramref> proporciona una forma de indicar que una palabra en los comentarios del código, por ejemplo en un
bloque <summary> o <remarks>, hace referencia a un parámetro. El archivo XML se puede procesar para dar formato a esta
palabra de alguna manera distinta, como con una fuente en negrita o en cursiva.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<permission cref="member">description</permission>
Parámetros
cref = "member"
Referencia a un miembro o campo al cual se puede llamar desde el entorno de compilación actual. El compilador comprueba
si el elemento de código dado existe y convierte member al nombre de elemento canónico en el resultado XML. member
debe aparecer entre comillas dobles (" ").
Para obtener información sobre cómo crear una referencia de tipo cref a un tipo genérico, vea
<see> (Guía de programación de C#).
description
Descripción del acceso al miembro.
Comentarios
La etiqueta <permission> permite documentar el acceso de un miembro. La clase PermissionSet permite especificar el acceso
a un miembro.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
class TestClass
{
/// <permission cref="System.Security.PermissionSet">Everyone can access this method.</
permission>
public static void Test()
{
}
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<remarks>description</remarks>
Parámetros
Description
Descripción del miembro.
Comentarios
La etiqueta <remarks> se utiliza para agregar información sobre un tipo, de modo que completa la información especificada
con <summary>. Esta información se muestra en el Examinador de objetos.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
/// <summary>
/// You may have some primary information about this class.
/// </summary>
/// <remarks>
/// You may have some additional information about this class.
/// </remarks>
public class TestClass
{
/// text for Main
static void Main()
{
}
}
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<returns>description</returns>
Parámetros
description
Descripción del valor devuelto.
Comentarios
La etiqueta <returns> se debe utilizar en el comentario de una declaración de método para describir el valor devuelto.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<see cref="member"/>
Parámetros
cref = "member"
Referencia a un miembro o campo al cual se puede llamar desde el entorno de compilación actual. El compilador comprueba
si el elemento de código dado existe y pasa member al nombre de elemento en el resultado XML. Agregue member entre
comillas dobles (" ").
Comentarios
La etiqueta <see> permite especificar un vínculo desde dentro del texto. Utilice <seealso> para indicar que el texto debe
colocarse en una sección Vea también.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Vea <summary> para obtener un ejemplo del uso de <see>.
Ejemplo
El ejemplo siguiente muestra cómo convertir una referencia cref en un tipo genérico.
C#
// compile with: /doc:DocFileName.xml
// the following cref shows how to specify the reference, such that,
// the compiler will resolve the reference
/// <summary cref="C{T}">
/// </summary>
class A { }
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<seealso cref="member"/>
Parámetros
cref = "member"
Referencia a un miembro o campo al cual se puede llamar desde el entorno de compilación actual. El compilador comprueba
si el elemento de código dado existe y pasa member al nombre de elemento en el resultado XML. member debe aparecer
entre comillas dobles (" ").
Para obtener información sobre cómo crear una referencia de tipo cref a un tipo genérico, vea
<see> (Guía de programación de C#).
Comentarios
La etiqueta <seealso> permite especificar el texto que se desea que aparezca en una sección Vea también. Utilice <see> para
especificar un vínculo desde dentro del texto.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
Vea <summary> para obtener un ejemplo del uso de <seealso>.
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<summary>description</summary>
Parámetros
description
Resumen del objeto.
Comentarios
La etiqueta <summary> se utiliza para describir un tipo o un miembro de tipo. Utilice <remarks> para suministrar
información adicional a una descripción de tipo.
El texto de la etiqueta <summary> es la única fuente de información sobre el tipo en IntelliSense y también se muestra en el
Examinador de objetos.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<typeparam name="name">description</typeparam>
Parámetros
name
Nombre del parámetro de tipo. Ponga el nombre entre comillas dobles (" ").
description
Descripción del parámetro de tipo.
Comentarios
La etiqueta <typeparam> se debería utilizar en el comentario de una declaración de tipo o método genérico para describir un
parámetro de tipo. Agregue una etiqueta para cada parámetro de tipo del tipo o método genérico.
Para obtener más información, vea Genéricos (Guía de programación de C#).
El texto de la etiqueta <typeparam> se mostrará en IntelliSense, el informe Web de comentario de código de
Examinador de objetos.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Vea <typeparamref> (Guía de programación de C#) para obtener un ejemplo de código que muestra cómo utilizar
<typeparam>.
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Guía de programación de C#
<typeparamref name="name"/>
Parámetros
name
Nombre del parámetro de tipo. Ponga el nombre entre comillas dobles (" ").
Comentarios
Para obtener más información sobre los parámetros de tipo en tipos y métodos genéricos, vea Genéricos.
Utilice esta etiqueta para permitir a los consumidores del archivo de documentación dar formato a la palabra de una manera
distinta, por ejemplo en cursiva.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
<value>property-description</value>
Parámetros
property-description
Descripción de la propiedad.
Comentarios
La etiqueta <value> permite describir el valor que representa una propiedad. Tenga en cuenta que al agregar una propiedad a
través de un asistente para código en el entorno de desarrollo de Visual Studio .NET, se agregará una etiqueta <summary>
para la nueva propiedad. A continuación, se debe agregar manualmente una etiqueta <value> que describa el valor que
representa la propiedad.
Compile con el parámetro /doc para procesar los comentarios de documentación y generar un archivo con ellos.
Ejemplo
C#
// compile with: /doc:DocFileName.xml
Vea también
Referencia
Etiquetas recomendadas para comentarios de documentación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
F campo
E evento
! cadena de error
El resto de la cadena proporciona información acerca del error. El compilador de C# genera información de error
para vínculos que no se pueden resolver.
La segunda parte de la cadena es el nombre completo del elemento, empezando en la raíz del espacio de nombres. El
nombre del elemento, los tipos contenedores y el espacio de nombres se separan mediante puntos. Si el propio nombre
del elemento contiene puntos, éstos se reemplazan por el signo #. Se supone que ningún elemento contiene un signo #
directamente en su nombre. Por ejemplo, el nombre completo del constructor de String sería "System.String.#ctor".
Para propiedades y métodos, si existen argumentos para el método, la lista de argumentos que se encuentra entre
paréntesis aparece a continuación. Si no existen argumentos, no se escribe ningún paréntesis. Los argumentos se
separan por comas. La codificación de cada argumento indica directamente cómo se codifica en una firma de .NET
Framework:
Tipos base. Los tipos normales (ELEMENT_TYPE_CLASS o ELEMENT_TYPE_VALUETYPE) se representan como el
nombre completo del tipo.
Tipos intrínsecos (por ejemplo, ELEMENT_TYPE_I4, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_STRING,
ELEMENT_TYPE_TYPEDBYREF y ELEMENT_TYPE_VOID). Se representan como el nombre completo del
correspondiente tipo completo. Por ejemplo, System.Int32 o System.TypedReference.
ELEMENT_TYPE_PTR se representa con un '*' a continuación del tipo modificado.
ELEMENT_TYPE_BYREF se representa con un signo '@' a continuación del tipo modificado.
ELEMENT_TYPE_PINNED se representa con un signo '^' a continuación del tipo modificado. El compilador de C#
nunca genera este resultado.
ELEMENT_TYPE_CMOD_REQ se representa como una '|' y el nombre completo de la clase modificadora, a
continuación del tipo modificado. El compilador de C# nunca genera este resultado.
ELEMENT_TYPE_CMOD_OPT se representa como un '!' y el nombre completo de la clase modificadora, a
continuación del tipo modificado.
ELEMENT_TYPE_SZARRAY se representa como "[]" a continuación del tipo de elemento de la matriz.
ELEMENT_TYPE_GENERICARRAY se representa como "[?]" a continuación del tipo de elemento de la matriz. El
compilador de C# nunca genera este resultado.
ELEMENT_TYPE_ARRAY se representa como [límite inferior:size,límite inferior:size] donde el número de comas es
el rango, 1, y los límites inferiores y el tamaño de cada dimensión, si se conocen, se representan en decimal. Si no
se especifica un límite inferior ni un tamaño, simplemente se omite. Si el límite inferior y el tamaño de una
dimensión particular se omiten, el signo ':' también se omite. Por ejemplo, una matriz de dos dimensiones con 1
como límites inferiores y sin tamaños especificados se representa como [1:,1:].
ELEMENT_TYPE_FNPTR se representa como "=FUNC:type (firma)", donde type es el tipo de valor devuelto y firma
corresponde a los argumentos del método. Si no existen argumentos, los paréntesis se omiten. El compilador de
C# nunca genera este resultado.
Los siguientes componentes de una firma no se representan porque nunca se utilizan para diferenciar métodos
sobrecargados:
convención de llamadas
tipo de valor devuelto
ELEMENT_TYPE_SENTINEL
Sólo para operadores de conversión (op_Implicit y op_Explicit), el valor devuelto del método se codifica como un signo
'~' seguido del tipo de valor devuelto.
En los tipos genéricos, el nombre del tipo va seguido de un acento invertido y de un número que indica el número de
parámetros de tipo genérico. Por ejemplo,
<member name="T:SampleClass`2"> es la etiqueta para un tipo definido como public class SampleClass<T, U>.
Para métodos que toman tipos genéricos como parámetros, los parámetros de tipo genérico se especifican como
números con un acento invertido antepuesto (por ejemplo `0, `1). Cada número representa una notación de matrices
basada en cero en los parámetros genéricos del tipo.
Ejemplos
Los siguientes ejemplos muestran cómo se generarían las cadenas de id. para una clase y sus miembros:
C#
///
///
namespace N // "N:N"
{
///
///
public unsafe class X // "T:N.X"
{
public X(){}
//----------------------------
// The result of the above is:
// "M:N.X.#ctor"
public string q;
//----------------------------
// The result of the above is:
// "F:N.X.q"
/// <returns></returns>
public const double PI = 3.14;
//----------------------------
// The result of the above is:
// "F:N.X.PI"
public event D d;
//----------------------------
// The result of the above is:
// "E:N.X.d"
Vea también
Tareas
Ejemplo XML Documentation
Referencia
/doc (Procesar comentarios de documentación) (Opciones del compilador de C#)
Conceptos
Guía de programación de C#
Comentarios de documentación XML (Guía de programación de C#)
Guía de programación de C#
Ésta es la forma que se muestra en los ejemplos de documentación y que usan las plantillas de proyectos de Visual C#.
Nota
El IDE de Visual Studio tiene una función llamada Edición de comentarios automática, que inserta automáticamente las etiq
uetas <summary> y </summary> y sitúa el cursor entre ambas después de que haya escrito el delimitador /// en el Edito
r de código. El acceso a esta característica se encuentra en Formato, C#/J#, Editor de texto, Opciones (Cuadro de diálogo) e
n sus páginas de propiedad del proyecto.
/** */
Si el resto de la línea que contiene el delimitador /** está en blanco, la línea no se procesa para comentarios. Si el
primer carácter es un espacio en blanco, éste se omite y se procesa el resto de la línea. En caso contrario, todo el texto de
la línea que se encuentra después del delimitador /** se procesa como parte del comentario.
Si en la línea que contiene el delimitador */ sólo hay espacio en blanco hasta dicho delimitador, se omite la línea. En caso
contrario, el texto que hay en la línea hasta el delimitador */ se procesa como parte del comentario, sujeto a las reglas
del patrón de coincidencia que se describen en el apartado siguiente:
Para las líneas que siguen a una que empieza con el delimitador /**, el compilador busca un patrón común al principio
de cada línea que consiste en espacios en blanco opcionales y un asterisco (*), seguido de más espacios en blanco
opcionales. Si el compilador encuentra un conjunto de caracteres común al principio de cada línea, omitirá este patrón
para todas las líneas que se encuentran después del delimitador /** hasta la línea que contiene el delimitador */ y,
posiblemente, incluyendo esta última.
Algunos ejemplos:
La única parte del siguiente comentario que se procesará es la línea que comienza con <summary>. Los dos formatos de
etiquetas siguientes producirán los mismos comentarios:
/**
<summary>text</summary>
*/
/** <summary>text</summary> */
El compilador aplica un patrón de " * " para omitir al principio de la segunda y tercera líneas.
/**
* <summary>
* text </summary>*/
El compilador no encuentra ningún patrón en este comentario porque no hay ningún asterisco en la segunda línea. Por
lo tanto, todo el texto que hay en la segunda y tercera líneas, hasta el delimitador */, se procesará como parte del
comentario.
/**
* <summary>
text </summary>*/
El compilador no encuentra ningún patrón en este comentario por dos razones. En primer lugar, ninguna línea comienza
con un número de espacios coherente delante del asterisco. En segundo lugar, la quinta línea comienza con una etiqueta,
que no coincide con los espacios. Por lo tanto, todo el texto que hay a partir de la segunda línea hasta el delimitador */ se
procesará como parte del comentario.
/**
* <summary>
* text
* text2
* </summary>
*/
Vea también
Tareas
Ejemplo XML Documentation
Referencia
/doc (Procesar comentarios de documentación) (Opciones del compilador de C#)
Conceptos
Guía de programación de C#
Comentarios de documentación XML (Guía de programación de C#)
Comentarios de documentación XML (Guía de programación de C#)
Guía de programación de C#
/// <summary>
/// Class level summary documentation goes here.</summary>
/// <remarks>
/// Longer comments can be associated with a type or member
/// through the remarks tag</remarks>
public class TestClass
{
/// <summary>
/// Store for the name property</summary>
private string _name = null;
/// <summary>
/// The class constructor. </summary>
public TestClass()
{
// TODO: Add Constructor Logic here
}
/// <summary>
/// Name property </summary>
/// <value>
/// A value tag is used to describe the property value</value>
public string Name
{
get
{
if (_name == null)
{
throw new System.Exception("Name is null");
}
return _name;
}
}
/// <summary>
/// Description for SomeMethod.</summary>
/// <param name="s"> Parameter description for s goes here</param>
/// <seealso cref="System.String">
/// You can use the cref attribute on any tag to reference a type or member
/// and the compiler will check that the reference exists. </seealso>
public void SomeMethod(string s)
{
}
/// <summary>
/// Some other method. </summary>
/// <returns>
/// Return results are described through the returns tag.</returns>
/// <seealso cref="SomeMethod(string)">
/// Notice the use of the cref attribute to reference a specific method </seealso>
public int SomeOtherMethod()
{
return 0;
}
/// <summary>
/// The entry point for the application.
/// </summary>
/// <param name="args"> A list of command line arguments</param>
static int Main(System.String[] args)
{
// TODO: Add code to start application here
return 0;
}
}
Compilar el código
Para compilar el ejemplo, escriba lo siguiente en la línea de comandos:
csc XMLsample.cs /doc:XMLsample.xml
Se creará el archivo XMLsample.xml, el cual se puede ver en el explorador o con el comando TYPE.
Programación eficaz
La documentación XML empieza con ///. Cuando se crea un proyecto nuevo, el asistente agrega automáticamente algunas
líneas iniciales con ///. El procesamiento de estos comentarios presenta algunas restricciones:
La documentación debe estar en XML bien formado. Si el XML no está bien formado, se generará un error de advertencia
y el archivo de documentación incluirá un comentario que mencione el error encontrado.
Los programadores pueden crear su propio conjunto de etiquetas. Existe un conjunto de etiquetas recomendado (vea la
sección Información adicional). Algunas de las etiquetas recomendadas tienen significados especiales:
La etiqueta <param> se usa para describir parámetros. Cuando se utiliza, el compilador comprueba si el
parámetro existe y si todos los parámetros están descritos en la documentación. Si la comprobación no tiene
éxito, el compilador emite una advertencia.
El atributo cref se puede asociar a cualquier etiqueta para proporcionar una referencia a un elemento de código.
El compilador comprobará si existe ese elemento de código. Si la comprobación no tiene éxito, el compilador
emite una advertencia. El compilador respeta cualquier instrucción using cuando busca un tipo descrito en el
atributo cref.
La etiqueta <summary> la utiliza IntelliSense, dentro de Visual Studio, para mostrar información adicional acerca
de un tipo o un miembro.
Nota
El archivo XML no proporciona información completa acerca del tipo y los miembros (por ejemplo, no contiene ninguna info
rmación de tipos). Para obtener información completa acerca de un tipo o miembro, el archivo de documentación debe utiliz
arse conjuntamente con el mecanismo de reflexión sobre el tipo o el miembro real.
Vea también
Tareas
Ejemplo XML Documentation
Referencia
/doc (Procesar comentarios de documentación) (Opciones del compilador de C#)
Conceptos
Guía de programación de C#
Comentarios de documentación XML (Guía de programación de C#)
Comentarios de documentación XML (Guía de programación de C#)
Guía de programación de C#
Para tener acceso al código desde otra aplicación, puede cargar el ensamblado en el dominio de aplicación actual o crear un
nuevo dominio de aplicación y cargarle el ensamblado. Si carga el ensamblado en el dominio de aplicación actual con
Assembly.LoadFrom, puede utilizar Assembly.CreateInstance para crear una instancia de la clase RemoteObject, lo que
hace que se ejecute el constructor del objeto.
C#
static void Main()
{
// Load the assembly into the current appdomain:
System.Reflection.Assembly newAssembly = System.Reflection.Assembly.LoadFrom(@"c:\Hello
WorldRemote.exe");
// Instantiate RemoteObject:
newAssembly.CreateInstance("HelloWorldRemote.RemoteObject");
}
Cuando cargue el ensamblado en un dominio de aplicación independiente, utilice AppDomain.ExecuteAssembly para tener
acceso al punto de entrada predeterminado o AppDomain.CreateInstance para crear una instancia de la clase
RemoteObject. La creación de la instancia hace que se ejecute el constructor.
C#
static void Main()
{
System.AppDomain NewAppDomain = System.AppDomain.CreateDomain("NewApplicationDomain");
Si no desea cargar el ensamblado mediante programación, utilice Agregar referencia del Explorador de soluciones para
especificar el ensamblado HelloWorldRemote.exe. A continuación, agregue una directiva using HelloWorldRemote; al bloque
using de la aplicación y utilice el tipo RemoteObject en el programa para declarar una instancia del objeto RemoteObject, de
la forma siguiente:
C#
static void Main()
{
// This code creates an instance of RemoteObject, assuming HelloWorldRemote has been ad
ded as a reference:
HelloWorldRemote.RemoteObject o = new HelloWorldRemote.RemoteObject();
}
Vea también
Referencia
Dominios de aplicación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Información general sobre dominios de aplicación
Dominios de aplicación y ensamblados
Programar con dominios de aplicación
Otros recursos
Dominios de aplicación
Programar con dominios de aplicación y ensamblados
Guía de programación de C#
La clase StrongNameIdentityPermission también proporciona la capacidad de compartir tipos, con las diferencias siguientes:
StrongNameIdentityPermission se aplica a un tipo individual, mientras que un ensamblado de confianza se aplica a
todo el ensamblado.
Si hay cientos de tipos en el ensamblado A que desea compartir con el ensamblado B, debe decorar cada uno de estos
tipos con StrongNameIdentityPermission, mientras que al utilizar un ensamblado de confianza, sólo deberá declarar
la relación de confianza una vez.
Con StrongNameIdentityPermission, los tipos que desea compartir se deben declarar como públicos. Con un
ensamblado de confianza, los tipos compartidos se declaran como privados.
Para obtener información sobre cómo generar un módulo .netmodule que pueda tener acceso a tipos no públicos en un
ensamblado, vea
/moduleassemblyname (Especificar un ensamblado de confianza para el módulo) (Opciones del compilador de C#).
Ejemplo
En este ejemplo, el ensamblado hace que los tipos y miembros internos sean visibles para el ensamblado denominado
cs_friend_assemblies_2.
// cs_friend_assemblies.cs
// compile with: /target:library
using System.Runtime.CompilerServices;
using System;
[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]
// internal by default
class Class1
{
public void Test()
{
Console.WriteLine("Class1.Test");
}
}
// cs_friend_assemblies_2.cs
// compile with: /reference:cs_friend_assemblies.dll /out:cs_friend_assemblies_2.exe
public class M
{
static void Main()
{
// access an internal type
Class1 a = new Class1();
a.Test();
Resultados
Class1.Test
Class2.Test
En este ejemplo se muestra cómo hacer que los tipos y miembros internos estén disponibles para los ensamblados que tienen
nombres seguros.
Para generar el archivo de claves y mostrar la clave pública, utilice la siguiente secuencia de comandos de sn.exe (para obtener
más información, vea Herramienta de nombre seguro (Sn.exe)):
sn -k friend_assemblies.snk // Genera la clave de nombre seguro
sn -p friend_assemblies.snk key.publickey // Extrae la clave pública de key.snk a key.publickey
sn -tp key.publickey // Muestra la clave pública almacenada en file'key.publickey
Pase el archivo de claves al compilador con /keyfile.
// cs_friend_assemblies_3.cs
// compile with: /target:library /keyfile:friend_assemblies.snk
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("cs_friend_assemblies_4, PublicKey=002400000480000094000000060
2000000240000525341310004000001000100031d7b6f3abc16c7de526fd67ec2926fe68ed2f9901afbc5f1b6b4
28bf6cd9086021a0b38b76bc340dc6ab27b65e4a593fa0e60689ac98dd71a12248ca025751d135df7b98c5f9d09
172f7b62dabdd302b2a1ae688731ff3fc7a6ab9e8cf39fb73c60667e1b071ef7da5838dc009ae0119a9cbff2c58
1fc0f2d966b77114b2c4")]
class Class1
{
public void Test()
{
System.Console.WriteLine("Class1.Test");
}
}
En este ejemplo se muestra cómo utilizar los tipos y miembros internos que están disponibles para los ensamblados que
tienen nombres seguros.
// cs_friend_assemblies_4.cs
// compile with: /keyfile:friend_assemblies.snk /reference:cs_friend_assemblies_3.dll /out:
cs_friend_assemblies_4.exe
public class M
{
static void Main()
{
Class1 a = new Class1();
a.Test();
}
}
Resultados
Class1.Test
Vea también
Conceptos
Guía de programación de C#
Ensamblados y Caché de ensamblados global (Guía de programación de C#)
Guía de programación de C#
catch (System.IO.FileNotFoundException e)
{
System.Console.WriteLine("The file cannot be found.");
}
catch (System.BadImageFormatException e)
{
System.Console.WriteLine("The file is not an Assembly.");
}
catch (System.IO.FileLoadException e)
{
System.Console.WriteLine("The Assembly has already been loaded.");
}
}
}
El método GetAssemblyName carga el archivo de prueba y, a continuación, lo libera una vez que se lee la información.
Resultados
The file is not an Assembly.
Vea también
Tareas
Solución de problemas de excepciones: System.BadImageFormatException
Referencia
AssemblyName
Conceptos
Guía de programación de C#
Ensamblados y Caché de ensamblados global (Guía de programación de C#)
Guía de programación de C#
Vea también
Tareas
Cómo: Cargar ensamblados en un dominio de aplicación
Referencia
Dominios de aplicación (Guía de programación de C#)
Conceptos
Guía de programación de C#
Ensamblados y Caché de ensamblados global (Guía de programación de C#)
Guía de programación de C#
Secciones relacionadas
Para obtener más información, vea:
Utilizar atributos (Guía de programación de C#)
Crear atributos personalizados (Guía de programación de C#)
Eliminar la ambigüedad de los destinos de atributos (Guía de programación de C#)
Acceso a atributos mediante reflexión (Guía de programación de C#)
Cómo: Crear una unión de C/C++ mediante atributos (Guía de programación de C#)
Atributos comunes (Guía de programación de C#)
Ejemplo de atributos
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#:
1.12 Atributos
17 Atributos
Vea también
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Información general sobre atributos
Usos comunes de los atributos
Guía de programación de C#
[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
El primer parámetro, el nombre de la DLL, es posicional y va siempre en primer lugar; los otros dos son parámetros con
nombre. En este caso, ambos parámetros con nombre se establecen como falso de forma predeterminada, por lo que se
pueden omitir. Consulte la documentación del atributo individual para obtener información sobre los valores de parámetro
predeterminados.
Una declaración puede incluir varios atributos, bien de forma separada, bien dentro del mismo grupo de corchetes:
C#
void MethodA([In][Out] ref double x) { }
void MethodB([Out][In] ref double x) { }
void MethodC([In, Out] ref double x) { }
Algunos atributos se pueden especificar varias veces para una entidad dada. Un ejemplo de este tipo de atributos multiuso es
Conditional:
C#
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
// ...
}
Nota
Por convención, todos los nombres de atributo finalizan con la palabra "Attribute" para distinguirlos de otros elementos de .
NET Framework. No obstante, no tiene que especificar el sufijo de atributo cuando utiliza atributos en el código. Por ejemplo,
[DllImport] equivale a [DllImportAttribute], pero DllImportAttribute es el nombre real del atributo en .NET Framework
.
Vea también
Referencia
Eliminar la ambigüedad de los destinos de atributos (Guía de programación de C#)
Crear atributos personalizados (Guía de programación de C#)
Acceso a atributos mediante reflexión (Guía de programación de C#)
Attribute
System.Reflection
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Atributos (Guía de programación de C#)
Guía de programación de C#
El nombre de la clase es el nombre del atributo, Author. Se deriva de System.Attribute, por lo tanto, se trata de una clase de
atributo personalizado. Los parámetros del constructor son los parámetros posicionales del atributo personalizado, en este
caso, name, mientras que cualquier propiedad o campo público de lectura y escritura es un parámetro con nombre, en este
caso, version es el único parámetro con nombre. Observe el uso del atributo AttributeUsage para validar el atributo Author
sólo en las declaraciones de class y struct.
Podría utilizar este nuevo atributo de la siguiente forma:
C#
[Author("H. Ackerman", version = 1.1)]
class SampleClass
{
// H. Ackerman's code goes here...
}
AttributeUsage tiene un parámetro con nombre, AllowMultiple, con el que se puede hacer que un atributo personalizado
sea de un solo uso o bien multiuso.
C#
[System.AttributeUsage(System.AttributeTargets.Class |
System.AttributeTargets.Struct,
AllowMultiple = true) // multiuse attribute
]
public class Author : System.Attribute
C#
[Author("H. Ackerman", version = 1.1)]
[Author("M. Knott", version = 1.2)]
class SampleClass
{
// H. Ackerman's code goes here...
// M. Knott's code goes here...
}
Vea también
Referencia
Utilizar atributos (Guía de programación de C#)
Eliminar la ambigüedad de los destinos de atributos (Guía de programación de C#)
Acceso a atributos mediante reflexión (Guía de programación de C#)
System.Reflection
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Atributos (Guía de programación de C#)
Guía de programación de C#
[SomeAttr]
int Method()
{
return 0;
}
Este tipo de situación se presenta frecuentemente al realizar el cálculo de referencias. Para resolver la ambigüedad, C# dispone
de un conjunto de destinos predeterminados para cada tipo de declaración, que se pueden reemplazar especificando
explícitamente otros destinos de atributos.
C#
// default: applies to method
[SomeAttr]
int Method1() { return 0; }
// applies to method
[method: SomeAttr]
int Method2() { return 0; }
Observe que esto es independiente de los destinos en los cuales SomeAttr se define como válido; es decir, incluso si SomeAttr
se definió para aplicarse sólo a valores devueltos, el destino return (valor devuelto) debería especificarse de todas formas.
Dicho de otra forma, el compilador no utilizará información de AttributeUsage para resolver destinos de atributo ambiguos.
Para obtener más información, vea AttributeUsage (Guía de programación de C#).
La sintaxis para destinos de atributo es la siguiente:
[target : attribute-list]
Parámetros
target
Uno de los siguientes tipos: assembly, field, event, method, module, param, property, return o type.
attribute-list
Lista de atributos aplicables.
En la tabla siguiente se muestran todas las declaraciones en las que se permiten atributos; para cada declaración, los posibles
destinos de atributos se muestran en la segunda columna. Los destinos en negrita son los predeterminados.
Declaración Destinos posibles
assembly assembly
module module
class type
struct type
interface type
enum type
parameter param
Field field
Los atributos de nivel de módulo y ensamblado no disponen de destino predeterminado. Para obtener más información, vea
Atributos globales.
Ejemplo
C#
using System.Runtime.InteropServices;
C#
[Guid("12345678-1234-1234-1234-123456789abc"), InterfaceType(ComInterfaceType.InterfaceIsIU
nknown)]
interface ISampleInterface
{
[DispId(17)] // set the DISPID of the method
[return: MarshalAs(UnmanagedType.Interface)] // set the marshaling on the return type
object DoWork();
}
Vea también
Referencia
Utilizar atributos (Guía de programación de C#)
Crear atributos personalizados (Guía de programación de C#)
Acceso a atributos mediante reflexión (Guía de programación de C#)
System.Reflection
Attribute
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Atributos (Guía de programación de C#)
Guía de programación de C#
equivale conceptualmente a:
C#
Author anonymousAuthorObject = new Author("H. Ackerman");
anonymousAuthorObject.version = 1.1;
Sin embargo, el código sólo se ejecuta cuando se consultan los atributos de SampleClass . Una llamada a
GetCustomAttributes en SampleClass hace que se construya un objeto Author y se inicialice como se indicó anteriormente.
Si la clase cuenta con otros atributos, se crean de forma similar otros objetos de atributo. A continuación,
GetCustomAttributes devuelve el objeto Author y cualquier otro objeto de atributo en una matriz. Es posible recorrer en
iteración esta matriz y determinar qué atributos se aplicaron según el tipo de cada elemento de la matriz, así como extraer
información de los objetos atributo.
Ejemplo
A continuación se muestra un ejemplo completo. Se define un atributo personalizado, que se aplica a varias entidades, y se
recupera por medio del mecanismo de reflexión.
C#
[System.AttributeUsage(System.AttributeTargets.Class |
System.AttributeTargets.Struct,
AllowMultiple = true) // multiuse attribute
]
public class Author : System.Attribute
{
string name;
public double version;
[Author("H. Ackerman")]
private class FirstClass
{
// ...
}
// No Author attribute
private class SecondClass
{
// ...
}
Resultado
Author information for FirstClass
H. Ackerman, version 1.00
Author information for SecondClass
Author information for ThirdClass
H. Ackerman, version 1.00
M. Knott, version 2.00
Vea también
Referencia
Utilizar atributos (Guía de programación de C#)
Eliminar la ambigüedad de los destinos de atributos (Guía de programación de C#)
Crear atributos personalizados (Guía de programación de C#)
System.Reflection
Attribute
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Atributos (Guía de programación de C#)
Guía de programación de C#
[System.Runtime.InteropServices.FieldOffset(0)]
public double d;
[System.Runtime.InteropServices.FieldOffset(0)]
public char c;
[System.Runtime.InteropServices.FieldOffset(0)]
public byte b;
}
A continuación se da otro ejemplo donde los campos comienzan en diferentes ubicaciones establecidas de manera explícita.
C#
[System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)]
struct TestExplicit
{
[System.Runtime.InteropServices.FieldOffset(0)]
public long lg;
[System.Runtime.InteropServices.FieldOffset(0)]
public int i1;
[System.Runtime.InteropServices.FieldOffset(4)]
public int i2;
[System.Runtime.InteropServices.FieldOffset(8)]
public double d;
[System.Runtime.InteropServices.FieldOffset(12)]
public char c;
[System.Runtime.InteropServices.FieldOffset(14)]
public byte b;
}
Los dos campos int, i1 e i2, comparten las mismas posiciones de memoria que lg. Esta clase de control sobre la organización
de una estructura es útil cuando se utilizan llamadas de la plataforma.
Vea también
Referencia
Utilizar atributos (Guía de programación de C#)
Eliminar la ambigüedad de los destinos de atributos (Guía de programación de C#)
Crear atributos personalizados (Guía de programación de C#)
Acceso a atributos mediante reflexión (Guía de programación de C#)
System.Reflection
Attribute
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Atributos (Guía de programación de C#)
Guía de programación de C#
#define TRACE_ON
using System;
using System.Diagnostics;
[Conditional("DEBUG")]
static void DebugMethod()
{
}
Comentarios
Cuando se llama a un método marcado como condicional, la presencia o ausencia del símbolo de preprocesamiento
especificado determina si la llamada se incluye o se omite. Si el símbolo se define, la llamada se incluye; en caso contrario, la
llamada se omite. El uso de Conditional es una alternativa más limpia, elegante y menos propensa a errores que agregar
métodos dentro de #if y #endif, como se indica a continuación:
#if DEBUG
void ConditionalMethod()
{
}
#endif
Un método condicional debe ser un método en una clase o declaración de estructura y debe tener un tipo de valor devuelto
void.
Uso de varios identificadores
Si un método presenta varios atributos Conditional, se incluye una llamada al método en el caso de que al menos uno de los
símbolos condicionales esté definido (es decir, los símbolos están conectados mediante una operación lógica OR). En este
ejemplo, la presencia de A o de B tendrá como resultado la llamada a un método:
C#
[Conditional("A"), Conditional("B")]
static void DoIfAorB()
{
// ...
}
Para conseguir el efecto de una operación lógica AND entre símbolos, se pueden definir métodos condicionales en serie. Por
ejemplo, el segundo método que se expone a continuación sólo se ejecutará si se definen A y B:
C#
[Conditional("A")]
static void DoIfA()
{
DoIfAandB();
}
[Conditional("B")]
static void DoIfAandB()
{
// Code to execute when both A and B are defined...
}
class SampleClass
{
// This attribute will only be included if DEBUG is defined.
[Documentation("This method displays an integer.")]
static void DoWork(int i)
{
System.Console.WriteLine(i.ToString());
}
}
Vea también
Referencia
Eliminar la ambigüedad de los destinos de atributos (Guía de programación de C#)
Crear atributos personalizados (Guía de programación de C#)
Acceso a atributos mediante reflexión (Guía de programación de C#)
System.Reflection
Attribute
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Atributos (Guía de programación de C#)
Guía de programación de C#
En este ejemplo, el atributo Obsolete se aplica a la clase A y al método B.OldMethod. Como el segundo argumento del
constructor del atributo aplicado a B.OldMethod se establece en true, el uso de este método genera un error de compilación,
mientras que el uso de la clase A sólo genera una advertencia. Sin embargo, llamar a B.NewMethod no genera ninguna
advertencia o error.
La cadena proporcionada como primer argumento al constructor de atributos se mostrará como parte de la advertencia o
error. Por ejemplo, cuando se utiliza con las definiciones anteriores, el código siguiente genera dos advertencias y un error:
// Generates 2 warnings:
A a = new A();
// Generate no errors or warnings:
B b = new B();
b.NewMethod();
// Generates an error, terminating compilation:
b.OldMethod();
Se generan dos advertencias para la clase A: uno para la declaración de la referencia de clase y otro para el constructor de
clase.
El atributo Obsolete se puede utilizar sin argumentos, pero incluyendo una explicación del motivo por el que el elemento está
obsoleto y una recomendación sobre qué utilizar en su lugar.
El atributo Obsolete es un atributo de uso único y se puede aplicar a cualquier entidad que permite el uso de atributos.
Obsolete es un alias para ObsoleteAttribute.
Vea también
Referencia
Eliminar la ambigüedad de los destinos de atributos (Guía de programación de C#)
Crear atributos personalizados (Guía de programación de C#)
Acceso a atributos mediante reflexión (Guía de programación de C#)
Attribute
System.Reflection
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Atributos (Guía de programación de C#)
Guía de programación de C#
[assembly: AssemblyVersion("1.0.0.0")]
Los atributos globales aparecen en el código fuente después de las directivas de nivel superior using y antes de las
declaraciones de tipo o de espacio de nombres. Los atributos globales pueden aparecer en varios archivos de código fuente,
pero los archivos se deben compilar en un paso de compilación único.
Éstos son algunos de los atributos del nivel de ensamblado de .NET Framework utilizados con más frecuencia:
AssemblyCompanyAttribute
AssemblyConfigurationAttribute
AssemblyCopyrightAttribute
AssemblyCultureAttribute
AssemblyDescriptionAttribute
AssemblyProductAttribute
AssemblyTitleAttribute
AssemblyTrademarkAttribute
Estos atributos se utilizan en proyectos basados en Visual Studio Plantilla Aplicación para formularios Windows Forms. Esta
plantilla incluye un archivo denominado AssemblyInfo.cs, que incluye estas instancias de atributo:
[assembly: AssemblyTitle("WindowsApplication1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("WindowsApplication1")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2005")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
Nota
Los atributos aplicables a un ensamblado se omiten si no se está creando un ensamblado.
[System.AttributeUsage(System.AttributeTargets.All,
AllowMultiple=false,
Inherited=true)]
class NewAttribute : System.Attribute { }
En este ejemplo, la clase NewAttribute se puede aplicar a cualquier entidad de código con atributo, pero sólo se puede aplicar
una vez a cada entidad. Cuando se aplica a una clase base, es heredada por las clases derivadas.
Los argumentos AllowMultiple y Inherited son opcionales, por lo que este código tiene el mismo efecto:
[System.AttributeUsage(System.AttributeTargets.All)]
class NewAttribute : System.Attribute { }
El primer argumento AttributeUsage debe ser uno o más elementos de la enumeración AttributeTargets. Se puede utilizar OR
con varios tipos de destino, de la manera siguiente:
using System;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
class NewPropertyOrFieldAttribute : Attribute { }
Si el argumento AllowMultiple se establece en true, el atributo resultante se puede aplicar más de una vez a una misma
entidad, como se indica a continuación:
using System;
[AttributeUsage(AttributeTargets.Class, AllowMultiple=true)]
class MultiUseAttr : Attribute { }
[MultiUseAttr]
[MultiUseAttr]
class Class1 { }
[MultiUseAttr, MultiUseAttr]
class Class2 { }
En este caso, se puede aplicar MultiUseAttr repetidamente porque AllowMultiple está establecido en true. Ambos formatos
son válidos para aplicar varios atributos.
Si Inherited se establece en false, el atributo no es heredado por las clases que se derivan de una clase atribuida. Por ejemplo:
using System;
[AttributeUsage(AttributeTargets.Class, Inherited=false)]
class Attr1 : Attribute { }
[Attr1]
class BClass { }
using System;
// Create some custom attributes:
[AttributeUsage(System.AttributeTargets.Class, Inherited=false)]
class A1 : System.Attribute { }
[AttributeUsage(System.AttributeTargets.Class)]
class A2 : System.Attribute { }
[AttributeUsage(System.AttributeTargets.Class, AllowMultiple=true)]
class A3 : System.Attribute { }
[A3,A3]
class DerivedClass : BaseClass { }
Vea también
Referencia
Utilizar atributos (Guía de programación de C#)
Eliminar la ambigüedad de los destinos de atributos (Guía de programación de C#)
Crear atributos personalizados (Guía de programación de C#)
Acceso a atributos mediante reflexión (Guía de programación de C#)
Attribute
System.Reflection
Conceptos
Guía de programación de C#
Reflexión (Guía de programación de C#)
Atributos (Guía de programación de C#)
Guía de programación de C#
C#
ArrayList list = new ArrayList();
list.Add(10);
list.Add(20);
En el ejemplo siguiente, Tokens divide la oración "This is a sample sentence." en símbolos con los separadores ' ' y '-', y
enumera esos símbolos con la instrucción foreach:
C#
Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});
Internamente, Tokens utiliza una matriz, la cual implementa IEnumerator e IEnumerable. El ejemplo de código podría haber
utilizado los métodos de enumeración de la matriz, pero eso iría en contra del propósito de este ejemplo.
En C#, no es estrictamente necesario que una clase de colección herede de IEnumerable e IEnumerator para que pueda ser
compatible con foreach; siempre que la clase disponga de los miembros GetEnumerator, MoveNext, Reset y Current
requeridos, funcionará con foreach. Omitir las interfaces tiene la ventaja de que permite definir el tipo de valor devuelto de
Current de modo que sea más específico que object, con lo que se consigue seguridad de tipos.
Por ejemplo, al principio del código de ejemplo anterior, cambie las líneas siguientes:
Ahora, debido a que Current devuelve una cadena, el compilador puede detectar cuándo se utiliza un tipo incompatible en una
instrucción foreach:
El inconveniente de omitir IEnumerable e IEnumerator es que la clase de colección ya no puede interactuar con las
instrucciones foreach (o equivalentes) de otros lenguajes compatibles con Common Language Runtime.
Puede combinar lo mejor de ambos enfoques (seguridad de tipos de C# e interoperabilidad con otros lenguajes compatibles
con Common Language Runtime) si hereda de IEnumerable e IEnumerator, y utiliza implementación de interfaces explícita,
tal como se muestra en el ejemplo siguiente.
Ejemplo
C#
using System.Collections;
// Declare the Tokens class:
public class Tokens : IEnumerable
{
private string[] elements;
public TokenEnumerator(Tokens t)
{
this.t = t;
}
// Declare the MoveNext method required by IEnumerator:
public bool MoveNext()
{
if (position < t.elements.Length - 1)
{
position++;
return true;
}
else
{
return false;
}
}
Resultados
This
is
a
sample
sentence.
Vea también
Referencia
System.Collections.Generic
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Clases de colección (Guía de programación de C#)
Otros recursos
Referencia de C#
Guía de programación de C#
throw ex;
}
Después de que se produzca una excepción, el motor en tiempo de ejecución comprueba la instrucción actual para ver si está
dentro de un bloque try. Si es así, cualquier bloque catch asociado al bloque try se comprueba para ver si puede detectar la
excepción. Los bloques Catch especifican generalmente los tipos de excepción; si el tipo del bloque catch es el mismo tipo de
la excepción o de una clase base de la excepción, el bloque catch puede controlar el método. Por ejemplo:
C#
static void TestCatch()
{
try
{
TestThrow();
}
catch (System.ApplicationException ex)
{
System.Console.WriteLine(ex.ToString());
}
}
Si la instrucción que produce una excepción no está dentro de un bloque try, o el bloque try que la encierra no tiene un bloque
catch coincidente, el motor en tiempo de ejecución comprueba el método de llamada a una instrucción try y a los bloques
catch. El motor en ejecución continúa hasta la pila de llamadas, en búsqueda de un bloque catch compatible. Después de
encontrar y ejecutar el bloque catch, el control se pasa a la primera instrucción después del bloque catch.
Una instrucción try puede contener más de un bloque catch. Se ejecuta la primera instrucción catch que puede controlar la
excepción; cualquier instrucción catch posterior, aun cuando sea compatible, se omite. Por ejemplo:
C#
static void TestCatch2()
{
try
{
TestThrow();
}
catch (System.ApplicationException ex)
{
System.Console.WriteLine(ex.ToString()); // this block will be executed
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.ToString()); // this block will NOT be executed
}
System.Console.WriteLine("Done"); // this statement is executed after the catch block
}
Antes de ejecutar el bloque catch, se comprueba que los bloques try que se han evaluado mediante el motor en tiempo de
ejecución, incluido el bloque try que contiene el bloque compatible catch, contienen bloques finally. Estos bloques Finally
permiten al programador limpiar cualquier estado ambiguo que haya quedado de un bloque try cancelado, o liberar cualquier
recurso externo (como controladores de gráficos, conexiones de base de datos o secuencias de archivos) sin esperar a que el
recolector de elementos no utilizados del motor en tiempo de ejecución finalice los objetos. Por ejemplo:
C#
static void TestFinally()
{
System.IO.FileStream file = null;
System.IO.FileInfo fileInfo = new System.IO.FileInfo("C:\\file.txt");
try
{
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Closing the file allows you to reopen it immediately - otherwise IOException is
thrown.
if (file != null)
{
file.Close();
}
}
try
{
file = fileInfo.OpenWrite();
System.Console.WriteLine("OpenWrite() succeeded");
}
catch (System.IO.IOException)
{
System.Console.WriteLine("OpenWrite() failed");
}
}
Si WriteByte() produjo una excepción, el código del segundo bloque try que intenta reabrir el archivo produciría un error si
no se llama a file.Close(), y el archivo permanecería bloqueado. Debido a que los bloques finally se ejecutan aunque se
produzca o no una excepción, el bloque finally en el ejemplo anterior permite al archivo cerrarse correctamente y ayuda a
evitar un error.
Si no se encuentra ningún bloque catch compatible en la pila de llamadas después de que se produzca una excepción, puede
suceder una de estas tres cosas:
Si la excepción está dentro de un destructor, el destructor se anula y se llama al destructor base, si existe.
Si la pila de llamadas contiene un constructor estático o un inicializador de campo estático, se produce una
TypeInitializationException, con la excepción original asignada a la propiedad InnerException de la nueva excepción.
Si se alcanza el comienzo del subproceso, éste finaliza.
Vea también
Referencia
Excepciones y control de excepciones (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
C#
try
{
// Code to try here.
}
finally
{
// Code to execute after try here.
}
C#
try
{
// Code to try here.
}
catch (System.Exception ex)
{
// Code to handle exception here.
}
finally
{
// Code to execute after try (and possibly catch) here.
}
Una instrucción try sin un bloque catch o finally producirá un error del compilador.
Bloques Catch
Un bloque catch puede especificar un tipo de excepción que se detectará. Este tipo se denomina filtro de excepción y debe ser
el tipo Exception o uno derivado de éste. Las excepciones definidas por la aplicación deberían derivarse de
ApplicationException.
Se pueden encadenar varios bloques catch con filtros de excepción diferentes. Los bloques catch múltiples se evalúan de
arriba a abajo, pero sólo se ejecuta un bloque catch para cada excepción iniciada. Se ejecutará el primer bloque catch que
especifique el tipo exacto o una clase base de la excepción que se haya producido. Si ningún bloque catch especifica un filtro de
excepción correspondiente, a continuación se ejecutará un bloque catch sin un filtro (si existe alguno). Es importante colocar
los bloques catch con las clases de excepción más concretas (más derivadas), en primer lugar.
Debe detectar excepciones cuando:
Tenga un conocimiento específico del motivo por el que se produjo la excepción y pueda implementar una recuperación
concreta, por ejemplo, detectar una excepción FileNotFoundException y solicitar al usuario que escriba un nuevo nombre
de archivo.
Pueda crear y producir una excepción nueva más específica. Por ejemplo:
C#
int GetInt(int[] array, int index)
{
try
{
return array[index];
}
catch(System.IndexOutOfRangeException e)
{
throw new System.ArgumentOutOfRangeException(
"Parameter index is out of range.");
}
}
Para controlar parcialmente una excepción. Por ejemplo, podría utilizar un bloque catch para agregar una entrada a un
registro de errores, pero después producir otra vez la excepción para permitir el control posterior de la excepción. Por
ejemplo:
C#
try
{
// try to access a resource
}
catch (System.UnauthorizedAccessException e)
{
LogError(e); // call a custom error logging procedure
throw e; // re-throw the error
}
Bloques Finally
Un bloque finally permite la limpieza de acciones realizada en un bloque try. Si el bloque finally está presente, se ejecuta
después de los bloques try y catch. Un bloque finally se ejecuta siempre, sin tener en cuenta si se produce una excepción o si
se encuentra un bloque catch que coincida con el tipo de excepción.
El bloque finally se puede utilizar para liberar recursos como secuencias de archivos, conexiones de base de datos y
controladores de gráficos sin esperar a que el recolector de elementos no utilizados del motor en tiempo de ejecución finalice
los objetos. Vea using (Instrucción, Referencia de C#) para obtener más información.
En este ejemplo, el bloque finally se utiliza para cerrar un archivo abierto en el bloque try. Observe que se comprueba el
estado del identificador del archivo antes de cerrarlo. Si el bloque try no puede abrir el archivo, el identificador del archivo
seguirá establecido en null. Opcionalmente, si se abre correctamente el archivo y no se produce una excepción, el bloque
finally se ejecutará y cerrará el archivo abierto.
C#
System.IO.FileStream file = null;
System.IO.FileInfo fileinfo = new System.IO.FileInfo("C:\\file.txt");
try
{
file = fileinfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// check for null because OpenWrite
// might have failed
if (file != null)
{
file.Close();
}
}
Se realiza una llamada inadecuada a un objeto, basada en el estado del objeto. Por ejemplo, al tratar de escribir en un
archivo de sólo lectura. En los casos en que el estado del objeto no permite realizar una operación, produzca una
instancia de InvalidOperationException o un objeto basado en una derivación de esta clase. Éste es un ejemplo de un
método que produce un objeto InvalidOperationException:
C#
class ProgramLog
{
System.IO.FileStream logFile = null;
void OpenLog(System.IO.FileInfo fileName, System.IO.FileMode mode) {}
void WriteLog()
{
if (!this.logFile.CanWrite)
{
throw new System.InvalidOperationException("Logfile cannot be read-only");
}
// Else write data to the log and return.
}
}
Cuando un argumento para un método provoca una excepción. En este caso, se debería detectar una excepción original y
se debería crear una instancia de ArgumentException. La excepción original se debería pasar al constructor de
ArgumentException como el parámetro InnerException:
C#
static int GetValueFromArray(int[] array, int index)
{
try
{
return array[index];
}
catch (System.IndexOutOfRangeException ex)
{
System.ArgumentException argEx = new System.ArgumentException("Index is out of
range", "index", ex);
throw argEx;
}
}
Las excepciones contienen una propiedad denominada StackTrace. Esta cadena contiene el nombre de los métodos en la pila
actual de llamadas, junto con el nombre del archivo y número de línea donde se produjo la excepción para cada método. CRL
crea automáticamente un objeto StackTrace desde el punto de la instrucción throw, de modo que las excepciones se deben
producir desde el punto donde debe comenzar el seguimiento de la pila.
Todas las excepciones contienen una propiedad denominada Message. Esta cadena se debería establecer para explicar la razón
de la excepción. Tenga en cuenta que no se debe colocar información confidencial de seguridad en el texto del mensaje.
Además de Message, ArgumentException contiene una propiedad llamada ParamName que se debe establecer en el
nombre del argumento que provocó que se produjera la excepción. En el caso de un establecedor de propiedades,
ParamName se debería establecer en value.
Los métodos públicos y protegidos deberían producir excepciones cada vez que no pueden finalizar su función deseada. La
clase de excepción producida debería ser la excepción más concreta disponible que se ajuste a las condiciones del error. Estas
excepciones se deberían documentar como parte de la funcionalidad de la clase y las clases derivadas o actualizaciones de la
clase original deberían mantener el mismo comportamiento para la compatibilidad con versiones anteriores.
Las excepciones no se deben utilizar para modificar el flujo de un programa como parte de la ejecución normal; sólo se deben
utilizar para informar de condiciones de error y controlarlas. Las excepciones no se deben devolver como un valor o parámetro
en lugar de iniciarse. Los programadores no deberían producir System.Exception, System.SystemException,
NullReferenceException o IndexOutOfRangeException intencionalmente.
Definir clases de excepción
Los programas pueden producir cualquiera de las clases de excepción predefinidas en el espacio de nombres System (excepto
donde se indicó anteriormente) o crear sus propias clases de excepción mediante la derivación de ApplicationException. Las
clases derivadas deberían definir al menos cuatro constructores: un constructor predeterminado, uno que establece la
propiedad del mensaje y otro que establece las propiedades Message y InnerException. El cuarto constructor se utiliza para
serializar la excepción. Las nuevas clases de excepción deberían ser serializables. Por ejemplo:
C#
public class InvalidDepartmentException : System.ApplicationException
{
public InvalidDepartmentException() {}
public InvalidDepartmentException(string message) {}
public InvalidDepartmentException(string message, System.Exception inner) {}
Las nuevas propiedades sólo se deberían agregar a la clase de excepción cuando los datos que proporcionan son útiles para
resolver la excepción. Si a la clase de excepción derivada se agregan nuevas propiedades, ToString() se debería reemplazar
para devolver la información agregada.
Especificación del lenguaje C#
Para obtener más información, vea las siguientes secciones en la Especificación del lenguaje C#:
8.9.5 La instrucción Throw
8.10 La instrucción Try
16 Excepciones
Vea también
Referencia
Excepciones y control de excepciones (Guía de programación de C#)
Control de excepciones (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
ArrayTypeMismatchException Se produce cuando una matriz no puede almacenar un elemento dado porque el tipo real del el
emento es incompatible con el tipo real de la matriz.
DivideByZeroException Se produce cuando tiene lugar un intento de dividir un valor integral por cero.
IndexOutOfRangeException Se produce cuando tiene lugar un intento de indizar una matriz cuando el índice es menor que c
ero o se encuentra fuera de los límites de la matriz.
InvalidCastException Se produce cuando tiene lugar un error en tiempo de ejecución en una conversión explícita de u
n tipo base a una interfaz o a un tipo derivado.
OutOfMemoryException Se produce cuando el intento de asignar memoria mediante el operador new da un error. Esto i
ndica que la memoria disponible en Common Language Runtime se ha agotado.
OverflowException Se produce cuando una operación aritmética en un contexto checked produce un desbordamien
to.
StackOverflowException Se produce cuando se agota la pila de excepciones debido a la existencia de demasiadas llamad
as al método pendientes; normalmente, suele indicar un nivel de recursividad muy profundo o i
nfinito.
TypeInitializationException Se produce cuando un constructor estático produce una excepción sin que haya cláusulas catch
compatibles para capturarla.
Vea también
Referencia
Excepciones y control de excepciones (Guía de programación de C#)
Control de excepciones (Guía de programación de C#)
try-catch (Referencia de C#)
try-finally (Referencia de C#)
try-catch-finally (Referencia de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
Comentarios
El código que produce una excepción está incluido en el bloque try. Una instrucción catch se agrega inmediatamente después
para controlar IndexOutOfRangeException, si se produce. El bloque catch controla IndexOutOfRangeException y en su lugar
produce la excepción ArgumentOutOfRangeException, más adecuada. Para proporcionar al llamador tanta información como
sea posible, considere la posibilidad de especificar la excepción original como InnerException de la nueva excepción. Dado que
la propiedad InnerException es de sólo lectura, debe asignarla en el constructor de la nueva excepción.
Vea también
Referencia
Excepciones y control de excepciones (Guía de programación de C#)
Control de excepciones (Guía de programación de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
file.Close();
}
Ejemplo
Para convertir el código anterior en una instrucción try-catch-finally, el código de limpieza está separado del código activo
como se muestra a continuación.
C#
static void CodeWithCleanup()
{
System.IO.FileStream file = null;
System.IO.FileInfo fileInfo = null;
try
{
fileInfo = new System.IO.FileInfo("C:\\file.txt");
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
catch(System.Exception e)
{
System.Console.WriteLine(e.Message);
}
finally
{
if (file != null)
{
file.Close();
}
}
}
Como puede producirse una excepción en cualquier momento dentro del bloque try antes de la llamada a OpenWrite() o la
propia llamada a OpenWrite() podría producir un error, no se garantiza que el archivo esté abierto cuando se intenta cerrarlo.
El bloque finally agrega una comprobación para asegurarse de que el objeto FileStream no es null antes de llamar al
método Close. Sin la comprobación de null, el bloque finally podría iniciar su propia excepción NullReferenceException, pero
se debería evitar producir excepciones en bloques finally si es posible.
Una conexión de base de datos también es un elemento que debería cerrarse en un bloque finally. Dado que el número de
conexiones permitido a un servidor de base de datos está limitado a veces, es importante cerrar las conexiones de base de
datos tan rápido como sea posible. Si se produce una excepción antes de poder cerrar la conexión, se trata de otro caso en el
que es preferible utilizar el bloque finally a esperar a la recolección de elementos no utilizados.
Vea también
Referencia
Excepciones y control de excepciones (Guía de programación de C#)
Control de excepciones (Guía de programación de C#)
using (Instrucción, Referencia de C#)
try-catch (Referencia de C#)
try-finally (Referencia de C#)
try-catch-finally (Referencia de C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
De forma predeterminada, un ensamblado Visual C# detecta las excepciones que no son CLS como excepciones
ajustadas. Utilice este método si necesita obtener acceso a la excepción original a través de la propiedad
WrappedException. En el procedimiento siguiente se explica cómo detectar excepciones de esta manera.
Dentro de un bloque catch general (un bloque catch sin tipo de excepción especificado) colocado detrás de un bloque
catch (Exception) o catch (Exception e).
Utilice este método si desea realizar alguna acción (como escribir en un archivo de registro) en respuesta a las
excepciones que no son CLS y no necesita obtener acceso a la información de excepción. De forma predeterminada,
Common Language Runtime ajusta todas las excepciones. Para deshabilitar este comportamiento, agregue este atributo
del nivel de ensamblado al código, normalmente en el archivo AssemblyInfo.cs: [assembly:
RuntimeCompatibilityAttribute(WrapNonExceptionThrows = false)].
try
{
// throws gcnew System::String(
// "I do not derive from System.Exception!");
myClass.TestThrow();
}
catch (Exception e)
{
RuntimeWrappedException rwe = e as RuntimeWrappedException;
if (rwe != null)
{
String s = rwe.WrappedException as String;
if (s != null)
{
Console.WriteLine(s);
}
}
else
{
// handle other System.Exception types
}
}
Vea también
Referencia
Excepciones y control de excepciones (Guía de programación de C#)
RuntimeWrappedException
Guía de programación de C#
Nota
Para utilizar las herramientas anteriores, por ejemplo, a fin de registrar un ensamblado administrado para COM interop, de
be tener permisos de seguridad de administrador o de usuario avanzado. Para obtener más información, vea
.NET Framework Security.
Nota
Los cuadros de diálogo y comandos de menú que se ven pueden diferir de los descritos en la Ayuda, en función de los valore
s de configuración o de edición activos. Para cambiar la configuración, elija la opción Importar y exportar configuraciones
del menú Herramientas. Para obtener más información, vea Valores de configuración de Visual Studio.
if (xlApp == null)
{
Console.WriteLine("EXCEL could not be started. Check that your office inst
allation and project references are correct.");
return;
}
xlApp.Visible = true;
Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
Worksheet ws = (Worksheet)wb.Worksheets[1];
if (ws == null)
{
Console.WriteLine("Worksheet could not be created. Check that your office
installation and project references are correct.");
}
if (aRange == null)
{
Console.WriteLine("Could not get a range. Check to be sure you have the co
rrect versions of the office DLLs.");
}
// Fill the cells in the C1 to C7 range of the worksheet with the number 6.
Object[] args = new Object[1];
args[0] = 6;
aRange.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, aRange,
args);
Seguridad
Para utilizar COM interop, debe tener permisos de seguridad de administrador o de usuario avanzado. Para obtener más
información sobre seguridad, vea .NET Framework Security.
Vea también
Tareas
Cómo: Utilizar la interoperabilidad COM para corregir la ortografía con Word (Guía de programación de C#)
Conceptos
Guía de programación de C#
Información general sobre interoperabilidad (Guía de programación de C#)
Otros recursos
Interoperabilidad en .NET Compact Framework
Ejemplos de interoperabilidad COM
Guía de programación de C#
C#
using System.Windows.Forms;
namespace WinSound
{
public partial class Form1 : Form
{
private TextBox textBox1;
private Button button1;
Compilar el código
Para compilar el código
1. Cree un nuevo proyecto de aplicación para Windows C# en Visual Studio y asígnele el nombre WinSound.
2. Copie el código anterior y péguelo sobre el contenido del archivo Form1.cs.
3. Copie el código siguiente y péguelo en el archivo Form1.Designer.cs, en el método InitializeComponent(), después de
cualquier código existente.
C#
this.button1 = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(192, 40);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(88, 24);
this.button1.TabIndex = 0;
this.button1.Text = "Browse";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(8, 40);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(168, 20);
this.textBox1.TabIndex = 1;
this.textBox1.Text = "FIle path";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Platform Invoke WinSound C#";
this.ResumeLayout(false);
this.PerformLayout();
4. Compile y ejecute el código.
Seguridad
Para obtener más información, vea .NET Framework Security.
Vea también
Tareas
Ejemplo de tecnología de invocación de plataformas
Conceptos
Guía de programación de C#
Información general sobre interoperabilidad (Guía de programación de C#)
Otros recursos
Calcular referencias de datos con invocación de plataforma
Guía de programación de C#
namespace WordSpell
{
public partial class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
int errors = 0;
if (textBox1.Text.Length > 0)
{
app.Visible = false;
doc1.CheckSpelling(
ref optional, ref optional, ref optional, ref optional, ref optional, r
ef optional,
ref optional, ref optional, ref optional, ref optional, ref optional, r
ef optional);
label1.Text = errors + " errors corrected ";
object first = 0;
object last = doc1.Characters.Count - 1;
textBox1.Text = doc1.Range(ref first, ref last).Text;
}
object saveChanges = false;
object originalFormat = Missing.Value;
object routeDocument = Missing.Value;
app.Quit(ref saveChanges, ref originalFormat, ref routeDocument);
}
}
}
Compilar el código
Este ejemplo requiere que Word esté instalado en el sistema y, dependiendo de la versión de Office, el ensamblado Word se
puede denominar Microsoft Office 10 Object Library o Word 11 Object Library.
Nota
Los cuadros de diálogo y comandos de menú que se ven pueden diferir de los descritos en la Ayuda, en función de los valore
s de configuración o de edición activos. Para cambiar la configuración, elija la opción Importar y exportar configuraciones
del menú Herramientas. Para obtener más información, vea Valores de configuración de Visual Studio.
4. Agregue el ensamblado Word como una referencia al proyecto. Haga clic con el botón secundario del mouse en el
proyecto (ratón), haga clic en Agregar referencia, haga clic en la ficha COM del cuadro de diálogo Agregar referencia.
Haga doble clic en Biblioteca de objetos de Microsoft Office 11 y presione Aceptar.
Observe que los cuadros de diálogo y comandos de menú que se ven pueden diferir de los descritos en la Ayuda, según
la edición o configuración activa. Para cambiar su configuración, elija Importar y exportar configuraciones en el menú
Herramientas. Para obtener más información, vea Configuración de Visual Studio.
Seguridad
Para utilizar la interoperabilidad COM, es necesario tener permisos de seguridad de usuario avanzado o de administrador. Para
obtener más información, vea .NET Framework Security.
Vea también
Tareas
Cómo: Utilizar la interoperabilidad COM para crear una hoja de cálculo Excel (Guía de programación de C#)
Conceptos
Guía de programación de C#
Información general sobre interoperabilidad (Guía de programación de C#)
Otros recursos
Ejemplos de interoperabilidad COM
Guía de programación de C#
namespace project_name
{
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
public interface ComClass1Interface
{
}
[Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA71"),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ComClass1Events
{
}
[Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(ComClass1Events))]
public class ComClass1 : ComClass1Interface
{
}
}
Vea también
Referencia
Interoperabilidad (Guía de programación de C#)
Generar (Página, Diseñador de proyectos) (C#)
Conceptos
Guía de programación de C#
Guía de programación de C#
namespace TaxTables
{
[ClassInterface(ClassInterfaceType.AutoDual)]
public class TaxTables
{
public static double Tax(double income)
{
if (income > 0 && income <= 7000) {return (.10 * income)
;}
if (income > 7000 && income <= 28400) {return 700.00 + (.15 * (income
- 7000));}
if (income > 28400 && income <= 68800) {return 3910.00 + (.25 * (income
- 28400));}
if (income > 68800 && income <= 143500) {return 14010.00 + (.28 * (income
- 68800));}
if (income > 143500 && income <= 311950) {return 34926.00 + (.33 * (income
- 143500));}
if (income > 311950) {return 90514.50 + (.35 * (income
- 311950));}
return 0;
}
[ComRegisterFunctionAttribute]
public static void RegisterFunction(System.Type t)
{
Microsoft.Win32.Registry.ClassesRoot.CreateSubKey
("CLSID\\{" + t.GUID.ToString().ToUpper() + "}\\Programmable");
}
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(System.Type t)
{
Microsoft.Win32.Registry.ClassesRoot.DeleteSubKey
("CLSID\\{" + t.GUID.ToString().ToUpper() + "}\\Programmable");
}
}
}
Ejecutar el código
Ejecutar el complemento de Excel
Genere el proyecto ExcelAddIn y presione F5 para compilarlo.
Abra un nuevo libro en Excel.
En el menú Herramientas, haga clic en Complementos y, a continuación, haga clic en Automatización.
En el cuadro de diálogo Servidores de automatización, seleccione ExcelAddIn de la lista de complementos y haga clic en
Aceptar.
En una celda del libro, escriba =Tax(23500). La celda muestra 3175.
Para registrar el archivo ExcelAddIn.dll después de moverlo a un directorio diferente, ejecute regasm con /codebase. Es
posible que aparezca una advertencia que indica que el ensamblado está sin firmar.
Seguridad
Para utilizar interoperabilidad COM, debe tener permisos de seguridad de administrador o de usuario avanzado. Para obtener
más información, vea .NET Framework Security.
Vea también
Tareas
Cómo: Utilizar la interoperabilidad COM para crear una hoja de cálculo Excel (Guía de programación de C#)
Conceptos
Guía de programación de C#
Información general sobre interoperabilidad (Guía de programación de C#)
Guía de programación de C#
El subprocesamiento múltiple soluciona problemas de capacidad de respuesta y ejecución de varias tareas, pero puede
representar problemas de sincronización y uso compartido de recursos porque los subprocesos se interrumpen y reanudan sin
generar advertencias de acuerdo con un mecanismo central de programación de subprocesos. Para obtener más información,
vea Sincronización de subprocesos (Guía de programación de C#). Vea Utilizar subprocesos y subprocesamiento para obtener
información general.
Información general
Los subprocesos tienen las siguientes propiedades:
Los subprocesos permiten al programa en C# realizar el procesamiento simultáneo.
El espacio de nombres System.Threading de .NET Framework facilita el uso de los subprocesos.
Los subprocesos comparten los recursos de la aplicación. Para obtener más información, vea
Utilizar subprocesos y subprocesamiento.
Secciones relacionadas
Vea los temas siguientes para obtener más información:
Utilizar el subprocesamiento (Guía de programación de C#)
Cómo: Crear y terminar subprocesos (Guía de programación de C#)
Cómo: Utilizar un grupo de subprocesos (Guía de programación de C#)
Cómo: Sincronizar un subproceso productor y un subproceso consumidor (Guía de programación de C#)
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#:
3.10 Orden de ejecución
8.12 La instrucción lock
10.4.3 Campos volátiles
10.7.1 Eventos de tipo campo
Vea también
Tareas
Ejemplo Monitor Synchronization Technology
Ejemplo Wait Synchronization Technology
Referencia
Mutex
Conceptos
Guía de programación de C#
Exclusiones mutuas (mutex)
Monitores
Operaciones de bloqueo
AutoResetEvent
Delegados (Guía de programación de C#)
Otros recursos
Thread (Clase)
CÓMO: Sincronizar el acceso a un recurso compartido en un entorno de subprocesamiento múltiple mediante Visual C# .NET
Guía de programación de C#
El argumento suministrado a la palabra clave lock tiene que ser un objeto basado en un tipo de referencia y se utiliza para definir
el ámbito del bloqueo. En el ejemplo anterior, el ámbito del bloqueo se limita a esta función porque no existe ninguna referencia
al objeto fuera de la función. Estrictamente, el objeto suministrado a lock sólo se utiliza para identificar únicamente el recurso
que varios subprocesos comparten, de modo que puede ser una instancia de clase arbitraria. Sin embargo, en la práctica, este
objeto normalmente representa el recurso para el que la sincronización de subprocesos es necesaria. Por ejemplo, si varios
subprocesos van a utilizar un objeto contenedor, se puede pasar el contenedor para bloquearlo. Entonces, el bloque de código
sincronizado que sigue al bloqueo tendría acceso al contenedor. Con tal de que otros subprocesos bloqueen el mismo
contenedor antes de tener acceso a él, el acceso al objeto se sincroniza de forma segura.
Generalmente, es mejor evitar el bloqueo en un tipo public o en instancias de objeto que estén fuera del control de la aplicación.
Por ejemplo, lock(this) puede ser problemático si se puede tener acceso a la instancia públicamente, ya que el código que está
fuera de su control también puede bloquear el objeto. Esto podría crear situaciones del interbloqueo, en las que dos o más
subprocesos esperan a que se libere el mismo objeto. El bloqueo de un tipo de datos público, como opuesto a un objeto, puede
producir problemas por la misma razón. El bloqueo de cadenas literales es especialmente arriesgado porque el Common
Language Runtime (CLR) interna las cadenas literales. Esto significa que hay una instancia de un literal de cadena determinado
para todo el programa, exactamente el mismo objeto representa el literal en todos los dominios de la aplicación en ejecución, en
todos los subprocesos. Como resultado, un bloqueo sobre una cadena que tiene el mismo contenido en cualquier parte del
proceso de la aplicación bloquea todas las instancias de esa cadena en la aplicación. Por tanto, es mejor bloquear un miembro
privado o protegido que no esté internado. Algunas clases proporcionan específicamente los miembros para bloquear. Por
ejemplo, el tipo Array proporciona SyncRoot. Muchos tipos de colección también proporcionan un miembro SyncRoot.
Para obtener más información sobre la palabra clave lock, vea:
lock (Instrucción, Referencia de C#)
Cómo: Sincronizar un subproceso productor y un subproceso consumidor (Guía de programación de C#)
Monitores
Al igual que la palabra clave lock, los monitores evitan que varios subprocesos ejecuten simultáneamente bloques de código. El
método Enter permite que un subproceso, y sólo uno, continué con las instrucciones siguientes; todos los demás subprocesos se
bloquean hasta que el subproceso en ejecución llama a Exit. Esto es similar a utilizar la palabra clave lock. De hecho, la palabra
clave lock se implementa con la clase Monitor. Por ejemplo:
C#
lock(x)
{
DoSomething();
}
Esto equivale a:
C#
System.Object obj = (System.Object)x;
System.Threading.Monitor.Enter(obj);
try
{
DoSomething();
}
finally
{
System.Threading.Monitor.Exit(obj);
}
Normalmente, es preferible utilizar la palabra clave lock en vez de utilizar directamente la clase Monitor, porque lock es más
conciso y garantiza que se libera el monitor subyacente aunque el código protegido produzca una excepción. Esto se logra con la
palabra clave finally, que ejecuta su bloque de código asociado independientemente de que se produzca una excepción.
Para obtener más información sobre los monitores, vea Ejemplo Monitor Synchronization Technology.
Eventos de sincronización y controladores de espera
El uso de un bloqueo o un monitor es útil para evitar la ejecución simultánea de bloques de código utilizados por varios
subprocesos, pero estas construcciones no permiten que un subproceso comunique un evento a otro. Esto requiere eventos de
sincronización, que son objetos que tienen uno de dos estados (señalizado y no señalizado) y se pueden utilizar para activar y
suspender subprocesos. Los subprocesos se pueden suspender haciendo que esperen a que se produzca un evento de
sincronización que no esté señalizado y se pueden activar cambiando el estado del evento a señalizado. Si un subproceso intenta
esperar a que se produzca un evento que ya está señalizado, el subproceso se sigue ejecutando sin retraso.
Hay dos tipos de eventos de sincronización: AutoResetEvent y ManualResetEvent. Sólo difieren en que AutoResetEvent cambia
automáticamente de señalizado a no señalizado siempre que activa un subproceso. A la inversa, ManualResetEvent permite
que cualquier número de subprocesos esté activado si su estado es señalizado y sólo vuelve al estado no señalizado cuando se
llama a su método Reset.
Se puede hacer que los subprocesos esperen a que se produzcan eventos si se llama a uno de los métodos de espera, como
WaitOne, WaitAny o WaitAll. System.Threading.WaitHandle.WaitOne hace que el subproceso espere hasta que se señalice un
único evento, System.Threading.WaitHandle.WaitAny bloquea un subproceso hasta que se señalicen uno o varios eventos
especificados y System.Threading.WaitHandle.WaitAll bloquea el subproceso hasta que se señalicen todos los eventos indicados.
Un evento se señaliza cuando se llama a su método Set.
En el ejemplo siguiente, la función Main crea e inicia un subproceso. El nuevo subproceso espera a que se produzca un evento
mediante el método WaitOne. Se suspende el subproceso hasta que el evento sea señalizado por el subproceso primario que
está ejecutando la función Main. Cuando el evento se señaliza, vuelve a ejecutarse el subproceso auxiliar. En este caso, como el
evento sólo se utiliza para una activación del subproceso, se podrían utilizar las clases AutoResetEvent o ManualResetEvent.
C#
using System;
using System.Threading;
class ThreadingExample
{
static AutoResetEvent autoEvent;
static void DoWork()
{
Console.WriteLine(" worker thread started, now waiting on event...");
autoEvent.WaitOne();
Console.WriteLine(" worker thread reactivated, now exiting...");
}
static void Main()
{
autoEvent = new AutoResetEvent(false);
Console.WriteLine("main thread starting worker thread...");
Thread t = new Thread(DoWork);
t.Start();
Console.WriteLine("main thrad sleeping for 1 second...");
Thread.Sleep(1000);
Console.WriteLine("main thread signaling worker thread...");
autoEvent.Set();
}
}
Para obtener más ejemplos del uso de eventos de sincronización de subprocesos, vea:
Ejemplo Monitor Synchronization Technology
Ejemplo Reader-Writer Synchronization Technology
Ejemplo Thread Pools Technology
Ejemplo Wait Synchronization Technology
Objeto Mutex
Una exclusión mutua es similar a un monitor; impide la ejecución simultánea de un bloque de código por más de un subproceso
a la vez. De hecho, el nombre "mutex" es una forma abreviada del término "mutuamente exclusivo". Sin embargo, a diferencia de
los monitores, una exclusión mutua se puede utilizar para sincronizar los subprocesos entre varios procesos. Una exclusión
mutua se representa mediante la clase Mutex.
Cuando se utiliza para la sincronización entre procesos, una exclusión mutua se denomina una exclusión mutua con nombre
porque va a utilizarla otra aplicación y, por tanto, no se puede compartir por medio de una variable global o estática. Se debe
asignar un nombre para que ambas aplicaciones puedan tener acceso al mismo objeto de exclusión mutua.
Aunque se puede utilizar una exclusión mutua para la sincronización de subprocesos dentro de un proceso, normalmente es
preferible utilizar Monitor porque los monitores se diseñaron específicamente para .NET Framework y, por tanto, hacen un
mejor uso de los recursos. Por el contrario, la clase Mutex es un contenedor para una construcción de Win32. Aunque es más
eficaz que un monitor, la exclusión mutua requiere transiciones de interoperabilidad, que utilizan más recursos del sistema que la
clase Monitor. Para obtener un ejemplo de uso de la exclusión mutua, vea Exclusiones mutuas (mutex).
Secciones relacionadas
Cómo: Crear y terminar subprocesos (Guía de programación de C#)
Cómo: Utilizar un grupo de subprocesos (Guía de programación de C#)
CÓMO: Sincronizar el acceso a un recurso compartido en un entorno de subprocesamiento múltiple mediante Visual C# .NET
CÓMO: Crear un subproceso utilizando Visual C# .NET
CÓMO: Enviar un elemento de trabajo al grupo de subprocesos utilizando Visual C# .NET
CÓMO: Sincronizar el acceso a un recurso compartido en un entorno de subprocesamiento múltiple mediante Visual C# .NET
Vea también
Referencia
Thread
WaitOne
WaitAny
WaitAll
Monitor
Mutex
AutoResetEvent
ManualResetEvent
Interlocked
WaitHandle
Conceptos
Guía de programación de C#
Guía de programación de C#
La clase Worker contiene un método adicional que se utiliza para indicar a DoWork que debe devolver un resultado. Este método
se denomina RequestStop y tiene la apariencia siguiente:
C#
public void RequestStop()
{
_shouldStop = true;
}
El método RequestStop asigna simplemente el miembro de datos _shouldStop a true. Como el método DoWork comprueba el
miembro de datos, esto tiene el efecto indirecto de que DoWork devuelva un resultado, con lo que termina el subproceso de
trabajo. Sin embargo, es importante tener en cuenta que DoWork y RequestStop son ejecutados por subprocesos diferentes. El
subproceso de trabajo ejecuta DoWork y el subproceso primario ejecuta RequestStop, por lo que el miembro de datos
_shouldStop se declara volatile, de la forma siguiente:
C#
private volatile bool _shouldStop;
La palabra clave volatile alerta al compilador de que varios subprocesos tendrán acceso al miembro de datos _shouldStop y,
en consecuencia, no debe asumir que el estado de optimización del miembro será óptimo. Para obtener más información, vea
volatile (Referencia de C#).
El uso de volatile con el miembro de datos _shouldStop permite el acceso seguro de varios subprocesos a este miembro sin
utilizar técnicas formales de sincronización de subprocesos, pero sólo porque _shouldStop es un valor de tipo bool. Esto
significa que sólo es necesario utilizar operaciones atómicas únicas para modificar _shouldStop. Sin embargo, si este miembro
de datos fuera una clase, estructura o matriz, el acceso a él de varios subprocesos probablemente produciría daños
intermitentes en los datos. Considere un subproceso que cambia los valores en una matriz. Windows interrumpe con
regularidad los subprocesos para permitir a otros subprocesos que se ejecuten, de modo que este subproceso se detendría
después de asignar ciertos elementos de la matriz pero antes de asignar otros. Esto significa que la matriz tiene ahora un
estado que el programador nunca previó y, como resultado, cuando otro subproceso lea la matriz se producirá un error.
Antes de crear realmente el subproceso de trabajo, la función Main crea un objeto Worker y una instancia de Thread. El objeto
de subproceso se configura para utilizar el método Worker.DoWork como punto de entrada mediante el paso de una referencia
a este método al constructor Thread, de la forma siguiente:
C#
Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);
En este momento, aunque el objeto de subproceso de trabajo existe y está configurado, no se ha creado el subproceso de
trabajo real todavía. Esto no ocurre hasta que Main llamada al método Start:
C#
workerThread.Start();
Entonces, el sistema inicia la ejecución del subproceso de trabajo, pero lo hace de forma asincrónica al subproceso primario.
Esto significa que la función Main continúa ejecutando el código inmediatamente, mientras el subproceso de trabajo realiza
simultáneamente la inicialización. Para garantizar que la función Main no intenta terminar el subproceso de trabajo antes de
que pueda ejecutarse, la función Main entra en un bucle hasta que la propiedad IsAlive del objeto de subproceso de trabajo se
establece en true:
C#
while (!workerThread.IsAlive);
A continuación, el subproceso primario se detiene brevemente con una llamada a Sleep. Esto asegura que la función DoWork
del subproceso de trabajo ejecutará el bucle dentro del método DoWork durante unos pocos recorridos antes de que la función
Main ejecute más comandos:
C#
Thread.Sleep(1);
Después de que transcurre un milisegundo, Main señala al objeto de subproceso de trabajo que debería finalizar utilizando el
método Worker.RequestStop que se introdujo previamente:
C#
workerObject.RequestStop();
También es posible terminar un subproceso desde otro con una llamada a Abort, pero esto termina a la fuerza el subproceso
afectado sin comprobar si ha completado su tarea y no proporciona ninguna oportunidad para la limpieza de recursos. Es
preferible la técnica mostrada en este ejemplo.
Por último, la función Main llama al método Join en el objeto de subproceso de trabajo. Este método hace que el subproceso
actual se bloquee, o espere, hasta que el subproceso que el objeto representa finalice. Por consiguiente, Join no devolverá
ningún resultado hasta que el subproceso de trabajo vuelva, con lo cual finaliza:
C#
workerThread.Join();
En este momento, sólo existe el subproceso primario que ejecuta Main. Muestra un mensaje final y, después, vuelve y finaliza
también el subproceso primario.
A continuación se muestra el ejemplo completo:
Ejemplo
C#
using System;
using System.Threading;
public class Worker
{
// This method will be called when the thread is started.
public void DoWork()
{
while (!_shouldStop)
{
Console.WriteLine("worker thread: working...");
}
Console.WriteLine("worker thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Volatile is used as hint to the compiler that this data
// member will be accessed by multiple threads.
private volatile bool _shouldStop;
}
Vea también
Tareas
Ejemplo de subprocesamiento
Referencia
Subprocesamiento (Guía de programación de C#)
Utilizar el subprocesamiento (Guía de programación de C#)
volatile (Referencia de C#)
Thread
Mutex
Monitor
Start
IsAlive
Sleep
Join
Abort
Conceptos
Guía de programación de C#
Otros recursos
Subprocesamiento administrado
Ejemplos de subprocesamiento
Guía de programación de C#
La clase AutoResetEvent se utiliza para el evento "nuevo elemento" porque es conveniente que este evento se restablezca
automáticamente cada vez que el subproceso consumidor responde a este evento. Alternativamente, la clase
ManualResetEvent se utiliza para el evento "salir" porque se desea que varios subprocesos respondan cuando se señala este
evento. Si se utilizara en su lugar AutoResetEvent, el evento revertiría a un estado no señalado después de que sólo un
subproceso respondiera al evento. El otro subproceso no respondería y, en ese caso, no podría finalizar.
La clase SyncEvents crea los dos eventos y los almacena de dos formas diferentes: como EventWaitHandle, que es la clase base
de AutoResetEvent y ManualResetEvent, y en una matriz basada en WaitHandle. Como verá en la descripción del
subproceso consumidor, esta matriz es necesaria para que el subproceso consumidor pueda responder a cualquier evento.
Los subprocesos consumidor y productor se representan con las clases denominadas Consumer y Producer, las cuales definen
un método denominado ThreadRun. Estos métodos se utilizan como puntos de entrada para los subprocesos de trabajo que el
método Main crea.
El método ThreadRun definido por la clase Producer tiene la apariencia siguiente:
C#
// Producer.ThreadRun
public void ThreadRun()
{
int count = 0;
Random r = new Random();
while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))
{
lock (((ICollection)_queue).SyncRoot)
{
while (_queue.Count < 20)
{
_queue.Enqueue(r.Next(0,100));
_syncEvents.NewItemEvent.Set();
count++;
}
}
}
Console.WriteLine("Producer thread: produced {0} items", count);
}
Este método recorre el código hasta que el evento "salir del subproceso" queda señalado. El estado de este evento se prueba
con el método WaitOne utilizando la propiedad ExitThreadEvent definida por la clase SyncEvents. En este caso, el estado del
evento se comprueba sin bloquear el subproceso actual porque el primer argumento utilizado con WaitOne es cero, lo que
indica que el método debe devolver un valor inmediatamente. Si WaitOne devuelve true, el evento en cuestión se señala
actualmente. En ese caso, se devuelve el método ThreadRun, que tiene el efecto de finalizar el subproceso de trabajo que
ejecuta este método.
Hasta que se señala el evento "salir del subproceso", el método Producer.ThreadStart intenta mantener 20 elementos en la
cola. Un elemento es simplemente un entero entre 0 y 100. La colección tiene que bloquearse antes de agregar nuevos
elementos para evitar que los subprocesos consumidor y primario tengan acceso simultáneamente a la colección. Esto se
realiza mediante la palabra clave lock. El argumento que se pasa a lock es el campo SyncRoot expuesto por medio de la
interfaz ICollection. Este campo se proporciona específicamente para sincronizar el acceso del subproceso. El acceso exclusivo a
la colección se concede para cualquier instrucción contenida en el bloque de código que sigue a lock. Para cada nuevo
elemento que el productor agrega a la cola, se realiza una llamada al método Set en el evento "nuevo elemento". Esto indica al
subproceso consumidor que emerja de su estado suspendido para procesar el nuevo elemento.
El objeto Consumer también define un método denominado ThreadRun. Al igual que en la versión del productor de ThreadRun,
un subproceso de trabajo creado por el método Main ejecuta este método. Sin embargo, la versión del consumidor de
ThreadStart debe responder a dos eventos. El método Consumer.ThreadRun tiene la apariencia siguiente:
C#
// Consumer.ThreadRun
public void ThreadRun()
{
int count = 0;
while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
{
lock (((ICollection)_queue).SyncRoot)
{
int item = _queue.Dequeue();
}
count++;
}
Console.WriteLine("Consumer Thread: consumed {0} items", count);
}
Este método utiliza WaitAny para bloquear el subproceso consumidor hasta que se señale cualquiera de los identificadores de
espera en la matriz suministrada. En este caso hay dos identificadores en la matriz: uno para terminar los subprocesos de
trabajo y otro para indicar que se ha agregado un nuevo elemento a la colección. WaitAny devuelve el índice del evento que
se ha señalado. El evento "nuevo elemento" es el primero en la matriz, por lo que un índice de cero indica un nuevo elemento.
En este caso se comprueba si hay un índice de 1, que indica el evento "salir del subproceso", y éste se utiliza para determinar si
el método sigue utilizando elementos. Si el evento "nuevo elemento" se ha señalado, se obtiene acceso exclusivo a la colección
con lock y se utiliza el nuevo elemento. Dado que este ejemplo genera y utiliza miles de elementos, no muestra cada elemento
utilizado. En su lugar se utiliza Main para mostrar periódicamente el contenido de la cola, como se mostrará.
El método Main empieza la creación de la cola cuyo contenido se generará y utilizará, y una instancia de SyncEvents, que se vio
anteriormente:
C#
Queue<int> queue = new Queue<int>();
SyncEvents syncEvents = new SyncEvents();
A continuación, Main configura los objetos Producer y Consumer para el uso con subprocesos de trabajo. Sin embargo, este
paso no crea o inicia los subprocesos de trabajo reales:
C#
Producer producer = new Producer(queue, syncEvents);
Consumer consumer = new Consumer(queue, syncEvents);
Thread producerThread = new Thread(producer.ThreadRun);
Thread consumerThread = new Thread(consumer.ThreadRun);
Observe que la cola y el objeto de evento de sincronización se pasan a los subprocesos Consumer y Producer como
argumentos de constructor. Esto proporciona a ambos objetos los recursos compartidos que necesitan para realizar sus tareas
respectivas. A continuación, se crean dos nuevos objetos Thread utilizando el método ThreadRun de cada objeto como un
argumento. Cada subproceso de trabajo, cuando se inicie, utilizará este argumento como punto de entrada para el subproceso.
Después Main inicia los dos subprocesos de trabajo con una llamada al método Start, de la forma siguiente:
C#
producerThread.Start();
consumerThread.Start();
En este momento, se crean los dos subprocesos de trabajo y se inicia la ejecución asincrónica, independientemente del
subproceso primario que está ejecutando actualmente el método Main. De hecho, lo siguiente que Main hace es suspender el
subproceso primario con una llamada al método Sleep. El método suspende el subproceso que está actualmente en ejecución
durante unos milisegundos. Una vez transcurrido este intervalo, se reactiva Main y, en ese momento, se muestra el contenido
de la cola. Main repite esto cuatro veces, de la forma siguiente:
C#
for (int i=0; i<4; i++)
{
Thread.Sleep(2500);
ShowQueueContents(queue);
}
Por último, Main indica a los subprocesos de trabajo que finalicen invocando al método Set del evento "salir del subproceso" y,
después, llama al método Join en cada subproceso de trabajo para bloquear el subproceso primario hasta que cada
subproceso de trabajo responde al evento y finaliza.
Hay un último ejemplo de sincronización de subprocesos: el método ShowQueueContents. Este método, como los subprocesos
consumidor y productor, utiliza lock para obtener acceso exclusivo a la cola. Sin embargo, en este caso el acceso exclusivo es
particularmente importante, porque ShowQueueContents enumera sobre la colección completa. La enumeración sobre una
colección es una operación especialmente propensa a dañar los datos con operaciones asincrónicas porque implica recorrer el
contenido de toda la colección. El método ShowQueueContents tiene la apariencia siguiente:
C#
syncEvents.ExitThreadEvent.Set();
producerThread.Join();
consumerThread.Join();
Finalmente, observe que el subproceso primario ejecuta ShowQueueContents porque Main lo llama. Esto significa que este
método, cuando obtiene acceso exclusivo a la cola de elementos, bloquea de hecho los subprocesos consumidor y productor
para evitar que tengan acceso a la cola. ShowQueueContents bloquea la cola y enumera el contenido:
C#
private static void ShowQueueContents(Queue<int> q)
{
lock (((ICollection)q).SyncRoot)
{
foreach (int item in q)
{
Console.Write("{0} ", item);
}
}
Console.WriteLine();
}
producerThread.Join();
consumerThread.Join();
}
Vea también
Tareas
Ejemplo Monitor Synchronization Technology
Ejemplo Wait Synchronization Technology
Referencia
Sincronización de subprocesos (Guía de programación de C#)
lock (Instrucción, Referencia de C#)
AutoResetEvent
ManualResetEvent
Set
Join
WaitOne
WaitAll
Queue
ICollection
Start
Sleep
WaitHandle
EventWaitHandle
Conceptos
Guía de programación de C#
Otros recursos
Thread (Clase)
Guía de programación de C#
Vea también
Tareas
Ejemplo Monitor Synchronization Technology
Ejemplo Wait Synchronization Technology
Referencia
Subprocesamiento (Guía de programación de C#)
Utilizar el subprocesamiento (Guía de programación de C#)
Mutex
WaitAll
ManualResetEvent
Set
ThreadPool
QueueUserWorkItem
ManualResetEvent
Conceptos
Guía de programación de C#
Monitores
Otros recursos
Seguridad en .NET Framework
CÓMO: Sincronizar el acceso a un recurso compartido en un entorno de subprocesamiento utilizando Visual C# .NET
Guía de programación de C#
El resultado es:
System.Int32
En este ejemplo, se utiliza la reflexión para obtener el nombre completo de un ensamblado cargado:
C#
// Using Reflection to get information from an Assembly:
System.Reflection.Assembly o = System.Reflection.Assembly.Load("mscorlib.dll");
System.Console.WriteLine(o.GetName());
El resultado es:
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
TestCode.cs: archivo que contiene el método Main. Utiliza los métodos del archivo DLL para calcular la suma y el
producto de los argumentos especificados en tiempo de ejecución.
Ejemplo
C#
// File: Add.cs
namespace UtilityMethods
{
public class AddClass
{
public static long Add(long i, long j)
{
return (i + j);
}
}
}
C#
// File: Mult.cs
namespace UtilityMethods
{
public class MultiplyClass
{
public static long Multiply(long x, long y)
{
return (x * y);
}
}
}
C#
// File: TestCode.cs
using UtilityMethods;
class TestCode
{
static void Main(string[] args)
{
System.Console.WriteLine("Calling methods from MathLibrary.DLL:");
if (args.Length != 2)
{
System.Console.WriteLine("Usage: TestCode <num1> <num2>");
return;
}
long num1 = long.Parse(args[0]);
long num2 = long.Parse(args[1]);
Este archivo contiene el algoritmo que utiliza los métodos de la DLL, Add y Multiply. Empieza analizando los argumentos
especificados en la línea de comandos, num1 y num2. A continuación, calcula la suma mediante el método Add de la clase
AddClass, y el producto mediante el método Multiply de la clase MultiplyClass.
Observe que la directiva using situada al principio del archivo permite utilizar los nombres de las clases sin calificar para hacer
referencia a los métodos de la DLL en tiempo de compilación, como se indica a continuación:
C#
MultiplyClass.Multiply(num1, num2);
Execution
Para ejecutar el programa, especifique el nombre del archivo EXE seguido de dos números, como se indica a continuación:
TestCode 1234 5678
Resultados
Calling methods from MathLibrary.DLL:
1234 + 5678 = 6912
1234 * 5678 = 7006652
Compilar el código
Para generar el archivo MathLibrary.DLL, compile los dos archivos Add.cs y Mult.cs mediante la siguiente línea de comandos:
csc /target:library /out:MathLibrary.DLL Add.cs Mult.cs
La opción /target:library indica al compilador que genere un archivo DLL en vez de un archivo EXE. La opción /out del
compilador seguida de un nombre de archivo se utiliza para especificar el nombre de archivo de la DLL. Si no se utiliza, el
compilador usa el primer archivo (Add.cs) como nombre de la DLL.
Para generar el archivo ejecutable, TestCode.exe, utilice la siguiente línea de comandos:
csc /out:TestCode.exe /reference:MathLibrary.DLL TestCode.cs
La opción /out indica al compilador que genere un archivo EXE y especifica el nombre del archivo (TestCode.exe). Esta opción
del compilador no es de uso obligatorio. La opción /reference del compilador especifica el archivo o archivos DLL que utiliza el
programa.
Vea también
Tareas
Cómo: Especificar una dirección base para un archivo DLL
Conceptos
Guía de programación de C#
Crear una clase para contener funciones de archivos DLL
Guía de programación de C#
Referencia de C#
En esta sección se proporciona material de referencia sobre las palabras clave, operadores, y errores y advertencias del
compilador de C#.
En esta sección
Palabras clave de C#
Palabras clave y sintaxis de C#.
Operadores de C#
Operadores y sintaxis de C#.
Directivas de preprocesador de C#
Comandos del compilador para incrustar en código fuente de C#.
Opciones del compilador de C#
Opciones del compilador y forma de utilizarlas.
Terminología de C#
Glosario de palabras y frases de C#.
Secciones relacionadas
Especificación del lenguaje C#
Proporciona punteros a la última versión de las características técnicas del lenguaje C# en formato Microsoft Word.
P+F sobre C#
Proporciona una lista actualizada de las preguntas más frecuentes sobre C# en el Centro para desarrolladores de C#.
Artículos de Knowledge Base de C# en Microsoft Knowledge Base
Búsqueda en tiempo real de artículos de Knowledge Base relacionados con C# y almacenados en MSDN.
Visual C#
Proporciona un portal de documentación sobre Visual C#.
Ejemplos de Visual C#
Proporciona una lista de ejemplos de Visual C# y vínculos a los mismos.
Características del editor de código de Visual C#
Proporciona vínculos a temas conceptuales y de tareas que describen el IDE y el Editor.
Escribir aplicaciones con Visual C#
Proporciona vínculos a temas que describen la forma de realizar algunas tareas de programación comunes.
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Visual C#
Referencia del lenguaje C#
Palabras clave de C#
Las palabras clave son identificadores predefinidos reservados que tienen un significado especial para el compilador. No se
pueden utilizar como identificadores en un programa a menos que incluyan el carácter @ como prefijo. Por ejemplo, @if es un
identificador válido pero if no, por ser una palabra clave.
do is sizeof while
int myInt;
no se podrá utilizar hasta que se inicialice. La inicialización se puede realizar mediante la siguiente instrucción:
que equivale a:
O bien
int myInt = 0;
Con el operador new, se realiza una llamada al constructor predeterminado del tipo específico y se asigna el valor
predeterminado a la variable. En el ejemplo anterior, el constructor predeterminado asigna a myInt el valor 0. Para obtener
más información sobre valores asignados mediante constructores predeterminados, vea Tabla de valores predeterminados.
Con los tipos definidos por el usuario, se utiliza new para invocar el constructor predeterminado. Por ejemplo, la siguiente
instrucción invoca el constructor predeterminado de la estructura Point:
Después de esta llamada, la estructura se considera definitivamente asignada; es decir, todos sus miembros se inicializan con
sus valores predeterminados.
Para obtener más información acerca del operador new, vea new.
Para obtener información sobre cómo dar formato a la presentación de tipos numéricos, vea
Tabla de formatos de presentación para valores numéricos.
Vea también
Referencia
Palabras clave de C#
Tipos de referencia (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Tipos (Referencia de C#)
Tablas de referencia de tipos (Referencia de C#)
Referencia del lenguaje C#
Literales
Puede asignar un valor booleano a una variable de tipo bool. También es posible asignar una expresión que se evalúa como
bool a una variable de tipo bool.
// keyword_bool.cs
using System;
public class MyClass
{
static void Main()
{
bool i = true;
char c = '0';
Console.WriteLine(i);
i = false;
Console.WriteLine(i);
Resultados
True
False
False
Conversiones
En C++, un valor de tipo bool se puede convertir a un valor de tipo int; es decir, false equivale a cero y true equivale a valores
distintos de cero. En C#, no es posible realizar la conversión del tipo bool a otros tipos o viceversa. Por ejemplo, la siguiente
instrucción if no es válida en C#, aunque sí lo es en C++:
int x = 123;
if (x) // Invalid in C#
{
printf_s("The value of x is nonzero.");
}
Para probar una variable de tipo int, hay que compararla explícitamente con un valor (por ejemplo, cero), como se indica a
continuación:
int x = 123;
if (x != 0) // The C# way
{
Console.Write("The value of x is nonzero.");
}
Ejemplo
En este ejemplo, se escribe un carácter desde el teclado y el programa comprueba si se trata de una letra. En ese caso,
comprueba si es minúscula o mayúscula. Estas comprobaciones se realizan con IsLetter y IsLower, que devuelven el tipo bool:
// keyword_bool_2.cs
using System;
public class BoolTest
{
static void Main()
{
Console.Write("Enter a character: ");
char c = (char)Console.Read();
if (Char.IsLetter(c))
{
if (Char.IsLower(c))
{
Console.WriteLine("The character is lowercase.");
}
else
{
Console.WriteLine("The character is uppercase.");
}
}
else
{
Console.WriteLine("Not an alphabetic character.");
}
}
}
Entrada
X
Resultados del ejemplo
Enter a character: X
The character is uppercase.
Additional sample runs might look as follow:
Enter a character: x
The character is lowercase.
Enter a character: 2
The character is not an alphabetic character.
En la declaración anterior, el literal entero 255 se convierte implícitamente del tipo int al tipo byte. Si el literal entero supera el
intervalo de valores del tipo byte, se producirá un error de compilación.
Conversiones
Hay una conversión implícita predefinida de byte a short, ushort, int, uint, longo, ulong, float, double o decimal.
No es posible convertir implícitamente a byte otros tipos numéricos no literales de mayor tamaño de almacenamiento. Para
obtener más información acerca de los tamaños de almacenamiento de tipos integrales, vea
Tabla de tipos integrales (Guía de programación de C#). Considere, por ejemplo, las dos variables siguientes de tipo byte, x e y:
La instrucción de asignación siguiente producirá un error de compilación, ya que la expresión aritmética del lado derecho del
operador de asignación se evalúa de forma predeterminada como int.
Sin embargo, es posible utilizar las instrucciones siguientes, donde la variable de destino tiene un tamaño de almacenamiento
igual o superior:
Sin embargo, no existe conversión implícita de tipos de punto flotante a tipo byte. Por ejemplo, la instrucción siguiente
generará un error de compilación, a menos que se utilice una conversión explícita:
Para llamar a métodos sobrecargados, debe utilizarse una conversión explícita de tipos. Considere, por ejemplo, los dos
métodos sobrecargados siguientes que utilizan parámetros de tipo byte e int:
Para obtener más información sobre expresiones aritméticas con tipos de punto flotante y tipos integrales, vea float y double.
Para obtener más información sobre reglas de conversión numéricas implícitas, vea
Tabla de conversiones numéricas implícitas (Referencia de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.3 Tipos y variables
4.1.5 Tipos integrales
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrales (Guía de programación de C#)
Tabla de tipos integrados (Referencia de C#)
Tabla de conversiones numéricas implícitas (Referencia de C#)
Tabla de conversiones numéricas explícitas (Referencia de C#)
Byte
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Conversiones
Un tipo char se puede convertir implícitamente en ushort, int, uint, long, ulong, float, double o decimal. Sin embargo, no
existen conversiones implícitas desde otros tipo al tipo char.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.3 Tipos y variables
2.4.4.4 Literales de caracteres
4.1.5 Tipos integrales
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrales (Guía de programación de C#)
Tabla de tipos integrados (Referencia de C#)
Tabla de conversiones numéricas implícitas (Referencia de C#)
Tabla de conversiones numéricas explícitas (Referencia de C#)
Char Structure
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Sin el sufijo m, el número se trata como double, lo cual genera un error del compilador.
Conversiones
Los tipos integrales se convierten implícitamente a decimal y el resultado se evalúa como decimal. Por consiguiente, es
posible inicializar una variable de tipo decimal mediante un literal entero sin el sufijo, de la manera siguiente:
No existe conversión implícita entre tipos de punto flotante y el tipo decimal; por lo tanto, se debe utilizar una conversión de
tipos para convertir estos dos tipos. Por ejemplo:
Además, se pueden combinar tipos integrales numéricos y decimal en la misma expresión. No obstante, si se combinan tipos
de punto flotante con el tipo decimal sin realizar una conversión de tipos, se producirá un error de compilación.
Para obtener más información sobre las conversiones numéricas implícitas, vea
Tabla de conversiones numéricas implícitas (Referencia de C#).
Para obtener más información sobre las conversiones numéricas explícitas, vea
Tabla de conversiones numéricas explícitas (Referencia de C#).
Dar formato a la presentación de valores de tipo decimal
Se puede dar formato a los resultados mediante el método String.Format o a través del método System.Console.Write, el cual
llama a String.Format(). El formato de moneda se especifica mediante la cadena del formato de moneda estándar "C" o "c",
como se muestra en el ejemplo 2. Para obtener más información sobre el método String.Format, vea
System.String.Format(System.String,System.Object).
Ejemplo
En este ejemplo, se combina un tipo decimal y un tipo int en la misma expresión. El resultado se evalúa como tipo decimal.
Si intenta agregar las variables double y decimal mediante una instrucción como ésta:
double x = 9;
Console.WriteLine(d + x); // Error
Resultados
12.1
En este ejemplo, se utiliza la cadena de formato de moneda para dar formato al resultado. Observe que x se redondea, ya que
los dígitos decimales superan $0,99. La variable y, que representa el número máximo de dígitos exactos, se muestra
exactamente en el formato adecuado.
// keyword_decimal2.cs
// Decimal type formatting
using System;
public class TestDecimalFormat
{
static void Main ()
{
decimal x = 0.999m;
decimal y = 9999999999999999999999999999m;
Console.WriteLine("My amount = {0:C}", x);
Console.WriteLine("Your amount = {0:C}", y);
}
}
Resultados
My amount = $1.00
Your amount = $9,999,999,999,999,999,999,999,999,999.00
double x = 3D;
Conversiones
Es posible combinar tipos numéricos integral y tipos de punto flotante en una expresión. En este caso, los tipos integrales se
convierten en tipos de punto flotante. La evaluación de la expresión se realiza según las siguientes reglas:
Si uno de los tipos de punto flotante es double, la expresión se evalúa como double o bool en el caso de expresiones
relacionales o booleanas.
Si no existe ningún tipo double en la expresión, ésta se evalúa como float, o bool en el caso de expresiones relacionales
o booleanas.
Una expresión de punto flotante puede contener los siguientes conjuntos de valores:
Cero negativo y positivo.
Infinito positivo y negativo.
Valor NaN (no es un número).
El conjunto finito de valores distintos de cero.
Para obtener más información sobre estos valores, consulte el estándar IEEE para aritmética binaria de punto flotante,
disponible en el sitio Web http://www.ieee.org/portal/index.jsp.
Ejemplo
En el ejemplo siguiente, se suman valores int, short, float y double que dan un resultado double.
// keyword_double.cs
// Mixing types in expressions
using System;
class MixedTypes
{
static void Main()
{
int x = 3;
float y = 4.5f;
short z = 5;
double w = 1.7E+3;
// Result of the 2nd argument is a double:
Console.WriteLine("The sum is {0}", x + y + z + w);
}
}
Resultados
The sum is 1712.5
En esta enumeración, Sat es 0, Sun es 1, Mon es 2 y así sucesivamente. Los enumeradores pueden tener inicializadores que
reemplazan a los valores predeterminados. Por ejemplo:
El tipo subyacente especifica el almacenamiento asignado para cada enumerador. No obstante, se necesita una conversión
explícita para convertir un tipo enum a un tipo integral. Por ejemplo, la siguiente instrucción asigna el enumerador Sun a una
variable de tipo int utilizando una conversión explícita para convertir de enum a int:
int x = (int)Days.Sun;
Cuando se aplica System.FlagsAttribute a una enumeración que contiene algunos elementos combinados con una operación
OR bit a bit, se observará que el atributo afecta el comportamiento de enum cuando se utiliza con algunas herramientas. Se
pueden observar estos cambios al utilizar herramientas tales como los métodos de la clase Console, el Evaluador de
expresiones, etc. (Vea el ejemplo 3).
Programación sólida
Asignar valores adicionales a nuevas versiones de enumeraciones o cambiar los valores de los miembros de enumeración en
una nueva versión, puede producir problemas para el código fuente dependiente. Es común que los valores enum se utilicen
en instrucciones switch y, si se han agregado elementos adicionales al tipo enum, la comprobación de los valores
predeterminados puede devolver true de forma inesperada.
Si otros desarrolladores van a utilizar su código, es importante proporcionar instrucciones sobre cómo su código debe
reaccionar si se agregan nuevos elementos a cualquier tipo enum.
Ejemplo
En este ejemplo, se declara la enumeración Days. Dos enumeradores se convierten explícitamente en un número entero y se
asignan a variables de número entero.
// keyword_enum.cs
// enum initialization:
using System;
public class EnumTest
{
enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};
static void Main()
{
int x = (int)Days.Sun;
int y = (int)Days.Fri;
Console.WriteLine("Sun = {0}", x);
Console.WriteLine("Fri = {0}", y);
}
}
Resultados
Sun = 2
Fri = 7
En este ejemplo, la opción de tipo base se utiliza para declarar un enum cuyos miembros son del tipo long. Observe que a
pesar de que el tipo subyacente de la enumeración es long, los miembros de la enumeración todavía deben convertirse
explícitamente al tipo long mediante una conversión de tipos.
// keyword_enum2.cs
// Using long enumerators
using System;
public class EnumTest
{
enum Range :long {Max = 2147483648L, Min = 255L};
static void Main()
{
long x = (long)Range.Max;
long y = (long)Range.Min;
Console.WriteLine("Max = {0}", x);
Console.WriteLine("Min = {0}", y);
}
}
Resultados
Max = 2147483648
Min = 255
El ejemplo de código siguiente ilustra el uso y efecto del atributo System.FlagsAttribute en una declaración enum.
// enumFlags.cs
// Using the FlagsAttribute on enumerations.
using System;
[Flags]
public enum CarOptions
{
SunRoof = 0x01,
Spoiler = 0x02,
FogLights = 0x04,
TintedWindows = 0x08,
}
class FlagTest
{
static void Main()
{
CarOptions options = CarOptions.SunRoof | CarOptions.FogLights;
Console.WriteLine(options);
Console.WriteLine((int)options);
}
}
Resultados
SunRoof, FogLights
5
Comentarios
Observe que si se quita el inicializador de Sat=1, el resultado será:
Sun = 1
Fri = 6
Comentarios
Observe que si elimina FlagsAttribute, el ejemplo generará lo siguiente:
5
5
float x = 3.5F;
Si no utiliza este sufijo en la declaración anterior, obtendrá un error de compilación, ya que está intentando almacenar un valor
de tipo double en una variable de tipo float.
Conversiones
Es posible combinar tipos numéricos integral y tipos de punto flotante en una expresión. En este caso, los tipos integrales se
convierten en tipos de punto flotante. La evaluación de la expresión se realiza según las siguientes reglas:
Si uno de los tipos de punto flotante es double, la expresión se evalúa como double o bool en el caso de expresiones
relacionales o booleanas.
Si no existe ningún tipo double en la expresión, ésta se evalúa como float o bool en el caso de expresiones relacionales o
booleanas.
Una expresión de punto flotante puede contener los siguientes conjuntos de valores:
Cero negativo y positivo
Infinito positivo y negativo
Valor NaN (no es un número)
El conjunto finito de valores distintos de cero
Para obtener más información sobre estos valores, consulte el estándar IEEE para aritmética binaria de punto flotante,
disponible en el sitio Web http://www.ieee.org/.
Ejemplo
En el siguiente ejemplo, una expresión matemática incluye valores de tipo int, short y float, y proporciona un resultado de tipo
float. Observe que la expresión no incluye ningún valor de tipo double.
// keyword_float.cs
// Mixing types in expressions
using System;
class MixedTypes
{
static void Main()
{
int x = 3;
float y = 4.5f;
short z = 5;
Console.WriteLine("The result is {0}", x * y / z);
}
}
Resultados
The result is 2.7
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
4.1.6 Tipos de punto flotante
6.2.1 Conversiones explícitas numéricas
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrales (Guía de programación de C#)
Tabla de tipos integrados (Referencia de C#)
Tabla de conversiones numéricas implícitas (Referencia de C#)
Tabla de conversiones numéricas explícitas (Referencia de C#)
Single Structure
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
int i = 123;
Cuando un literal entero no tiene sufijo, su tipo es el primero de estos tipos en el que se puede representar su valor: int, uint,
long, ulong. En este ejemplo, es del tipo int.
Conversiones
Existe una conversión implícita predefinida de int a long, float, double o decimal. Por ejemplo:
Existe una conversión implícita predefinida de sbyte, byte, short, ushort o char a int. Por ejemplo, la instrucción de asignación
siguiente genera un error de compilación si no se emplea una conversión explícita:
Observe que no existe conversión implícita de tipos de punto flotante a int. Por ejemplo, la instrucción siguiente generará un
error de compilación, a menos que se utilice una conversión explícita:
Para obtener más información sobre las expresiones aritméticas con tipos de punto flotante y tipos integrales, vea
float (Referencia de C#) y double (Referencia de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.3 Tipos y variables
4.1.5 Tipos integrales
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrales (Guía de programación de C#)
Tabla de tipos integrados (Referencia de C#)
Tabla de conversiones numéricas implícitas (Referencia de C#)
Tabla de conversiones numéricas explícitas (Referencia de C#)
Int32 Structure
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Cuando un literal entero no tiene sufijo, su tipo es el primero de estos tipos en el que se puede representar su valor: int, uint,
long, ulong. En el ejemplo anterior, es del tipo long, ya que supera el intervalo de uint (vea
Tabla de tipos integrales (Guía de programación de C#) para conocer los tamaños de almacenamiento de los tipos integrales).
También se puede utilizar el sufijo L con el tipo long de este modo:
Cuando se utiliza el sufijo L, el tipo del entero literal será long o ulong, según su tamaño. En este caso, es long, ya que es
menor que el intervalo de ulong.
El sufijo se utiliza habitualmente en las llamadas a métodos sobrecargados. Considere, por ejemplo, los dos métodos
sobrecargados siguientes que utilizan parámetros de tipo long e int:
El tipo long se puede utilizar con otros tipos integrales numéricos en la misma expresión, en cuyo caso la expresión se evalúa
como long (o bool en el caso de expresiones relacionales o booleanas). Por ejemplo, la siguiente expresión se evalúa como
long:
898L + 88
Nota
También se puede utilizar la letra minúscula "l" como sufijo. No obstante, el compilador generará una advertencia, ya que la l
etra "l" se confunde fácilmente con el dígito "1". Utilice "L" por motivos de claridad.
Para obtener más información sobre expresiones aritméticas con tipos de punto flotante y tipos integrales, vea float y double.
Conversiones
Existe una conversión implícita predefinida de long a float, double o decimal. En los demás casos, se debe utilizar una
conversión explícita. Por ejemplo, la instrucción siguiente genera un error de compilación si no se emplea una conversión
explícita:
En la declaración anterior, el literal entero 127 se convierte implícitamente del tipo int al tipo sbyte. Si el literal entero supera el
intervalo de valores del tipo sbyte, se producirá un error de compilación.
Debe utilizarse una conversión de tipos al llamar a métodos sobrecargados. Considere, por ejemplo, los dos métodos
sobrecargados siguientes que utilizan parámetros de tipo sbyte e int:
Si se utiliza la conversión explícita al tipo sbyte, se garantiza la llamada al tipo correcto; por ejemplo:
Conversiones
Existe una conversión implícita predefinida de sbyte a short, int, long, float, double o decimal.
No se pueden convertir implícitamente tipos numéricos no literales cuyo tamaño de almacenamiento sea superior a sbyte
(vea Tabla de tipos integrales (Guía de programación de C#) para conocer los tamaños de almacenamiento de los tipos
integrales). Considere, por ejemplo, las dos variables siguientes de tipo sbyte, x e y:
La instrucción de asignación siguiente producirá un error de compilación, ya que la expresión aritmética del lado derecho del
operador de asignación se evalúa como int de forma predeterminada.
Sin embargo, es posible utilizar las instrucciones siguientes, donde la variable de destino tiene un tamaño de almacenamiento
igual o superior:
Observe que no existe conversión implícita de tipos de punto flotante a sbyte. Por ejemplo, la instrucción siguiente generará
un error de compilación, a menos que se utilice una conversión explícita:
Para obtener más información sobre expresiones aritméticas con tipos de punto flotante y tipos integrales, vea float y double.
Para obtener más información sobre reglas de conversión numéricas implícitas, vea
Tabla de conversiones numéricas implícitas (Referencia de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.3 Tipos y variables
4.1.5 Tipos integrales
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrales (Guía de programación de C#)
Tabla de tipos integrados (Referencia de C#)
Tabla de conversiones numéricas implícitas (Referencia de C#)
Tabla de conversiones numéricas explícitas (Referencia de C#)
SByte Structure
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
short x = 32767;
En la declaración anterior, el literal entero 32767 se convierte implícitamente del tipo int al tipo short. Si el literal entero no
cabe en el espacio de almacenamiento reservado para un tipo short, se produce un error de compilación.
Debe utilizarse una conversión de tipos al llamar a métodos sobrecargados. Considere, por ejemplo, los dos métodos
sobrecargados siguientes que utilizan parámetros de tipo short e int:
Si se utiliza la conversión explícita al tipo short, se garantiza la llamada al tipo correcto; por ejemplo:
Conversiones
Existe una conversión implícita predefinida de short a int, long, float, double o decimal.
No se pueden convertir implícitamente tipos numéricos no literales cuyo tamaño de almacenamiento sea superior a short (vea
Tabla de tipos integrales (Guía de programación de C#) para conocer los tamaños de almacenamiento de los tipos integrales).
Considere, por ejemplo, las dos variables siguientes de tipo short, x e y:
short x = 5, y = 12;
La instrucción de asignación siguiente producirá un error de compilación, ya que la expresión aritmética del lado derecho del
operador de asignación se evalúa como int de forma predeterminada.
short z = x + y; // Error: no conversion from int to short
Sin embargo, es posible utilizar las instrucciones siguientes, donde la variable de destino tiene un tamaño de almacenamiento
igual o superior:
int m = x + y;
long n = x + y;
No existe conversión implícita de tipos de punto flotante a tipo short. Por ejemplo, la instrucción siguiente generará un error
de compilación, a menos que se utilice una conversión explícita:
Comentarios
Las estructuras también pueden contener constructores, constantes, campos, métodos, propiedades, indizadores, operadores,
eventos y tipos anidados, aunque si se requieren estos miembros, se debe considerar la posibilidad de crear una clase en vez
de un tipo.
Las estructuras pueden implementar una interfaz, pero no pueden heredar de otra estructura. Por esa razón, los miembros de
estructura no se pueden declarar como protected.
Para obtener más información, vea Estructuras (Guía de programación de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
11 Estructuras
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrados (Referencia de C#)
Tipos de valores (Referencia de C#)
class (Referencia de C#)
interface (Referencia de C#)
Objetos, clases y estructuras (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Tabla de valores predeterminados (Referencia de C#)
Tipos (Referencia de C#)
Referencia del lenguaje C#
Cuando un literal entero no tiene sufijo, su tipo es el primero de estos tipos en el que se puede representar su valor: int, uint,
long, ulong. En este ejemplo, es uint:
Cuando se utiliza el sufijo U o u, el tipo del literal puede ser uint o ulong según el valor numérico del literal. Por ejemplo:
Console.WriteLine(44U.GetType());
Console.WriteLine(323442434344U.GetType());
Este código muestra System.UInt32, seguido de System.UInt64 (los tipos subyacentes de uint y ulong, respectivamente),
porque el segundo literal es demasiado grande para que lo almacene el tipo uint.
Conversiones
Existe una conversión implícita predefinida de uint a long, ulong, float, double o decimal. Por ejemplo:
Existe una conversión implícita predefinida de byte, ushort o char a uint. En cualquier otro caso, se debe utilizar una
conversión explícita. Por ejemplo, la instrucción de asignación siguiente genera un error de compilación si no se emplea una
conversión explícita:
Observe que no existe conversión implícita de tipos de punto flotante a uint. Por ejemplo, la instrucción siguiente generará un
error de compilación, a menos que se utilice una conversión explícita:
Cuando un literal entero no tiene sufijo, su tipo es el primero de estos tipos en el que se puede representar su valor: int, uint,
long, ulong. En el ejemplo anterior, es del tipo ulong.
También se pueden utilizar sufijos para especificar el tipo del literal, de acuerdo con las siguientes reglas:
Cuando se utiliza el sufijo L o l, el tipo del entero literal será long o ulong, según su tamaño.
Nota
Se puede utilizar la letra minúscula "l" como sufijo. No obstante, el compilador generará una advertencia, ya que la letr
a "l" se confunde fácilmente con el dígito "1". Utilice "L" por motivos de claridad.
Cuando se utiliza el sufijo U o u, el tipo del entero literal será uint o ulong, según su tamaño.
Si se utiliza UL, ul, Ul, uL, LU, lu, Lu o lU, el tipo del entero literal será ulong.
Por ejemplo, el resultado de las tres instrucciones siguientes será el tipo UInt64, que corresponde al alias ulong:
Console.WriteLine(9223372036854775808L.GetType());
Console.WriteLine(123UL.GetType());
Console.WriteLine((123UL + 456).GetType());
El sufijo se utiliza habitualmente en las llamadas a métodos sobrecargados. Considere, por ejemplo, los dos métodos
sobrecargados siguientes que utilizan parámetros de tipo ulong e int:
Si se utiliza un sufijo con el parámetro ulong, se garantiza la llamada al tipo correcto; por ejemplo:
Conversiones
Existe una conversión implícita predefinida de ulong a float, double o decimal.
Sin embargo, no existe conversión implícita de ulong a cualquier tipo integral. Por ejemplo, la instrucción siguiente genera un
error de compilación si no se emplea una conversión explícita:
Existe una conversión implícita predefinida de byte, ushort, uint o char a ulong.
Sin embargo, no existe conversión implícita de tipos de punto flotante a tipo ulong. Por ejemplo, la instrucción siguiente
generará un error de compilación, a menos que se utilice una conversión explícita:
Para obtener más información sobre expresiones aritméticas con tipos de punto flotante y tipos integrales, vea float y double.
Para obtener más información sobre reglas de conversión numéricas implícitas, vea
Tabla de conversiones numéricas implícitas (Referencia de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.3 Tipos y variables
4.1.5 Tipos integrales
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrales (Guía de programación de C#)
Tabla de tipos integrados (Referencia de C#)
Tabla de conversiones numéricas implícitas (Referencia de C#)
Tabla de conversiones numéricas explícitas (Referencia de C#)
UInt64 Structure
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
En la declaración anterior, el literal entero 65535 se convierte implícitamente del tipo int al tipo ushort. Si el literal entero
supera el intervalo de valores del tipo ushort, se producirá un error de compilación.
Debe utilizarse una conversión de tipos al llamar a métodos sobrecargados. Considere, por ejemplo, los dos métodos
sobrecargados siguientes que utilizan parámetros de tipo ushort e int:
Si se utiliza la conversión explícita al tipo ushort, se garantiza la llamada al tipo correcto; por ejemplo:
Conversiones
Existe una conversión implícita predefinida de ushort a int, uint, long, ulong, float, double o decimal.
Existe una conversión implícita predefinida de byte o char a ushort. En cualquier otro caso, se debe utilizar una conversión
explícita. Considere, por ejemplo, las dos variables siguientes de tipo ushort, x e y:
ushort x = 5, y = 12;
La instrucción de asignación siguiente producirá un error de compilación, ya que la expresión aritmética del lado derecho del
operador de asignación se evalúa de forma predeterminada como int.
Sin embargo, es posible utilizar las instrucciones siguientes, donde la variable de destino tiene un tamaño de almacenamiento
igual o superior:
int m = x + y;
long n = x + y;
Observe que no existe conversión implícita de tipos de punto flotante a ushort. Por ejemplo, la instrucción siguiente generará
un error de compilación, a menos que se utilice una conversión explícita:
Para obtener más información sobre expresiones aritméticas con tipos de punto flotante y tipos integrales, vea float y double.
Para obtener más información sobre reglas de conversión numéricas implícitas, vea
Tabla de conversiones numéricas implícitas (Referencia de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.3 Tipos y variables
4.1.5 Tipos integrales
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrales (Guía de programación de C#)
Tabla de tipos integrados (Referencia de C#)
Tabla de conversiones numéricas implícitas (Referencia de C#)
Tabla de conversiones numéricas explícitas (Referencia de C#)
UInt16 Structure
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
class TestClass
{
// Methods, properties, fields, events, delegates
// and nested classes go here.
}
Comentarios
A diferencia de C++, en C# sólo se permite la herencia simple. En otras palabras, una clase puede heredar la implementación
de una sola clase base. Sin embargo, una clase puede implementar más de una interfaz. La siguiente tabla muestra ejemplos
de herencia de clases e implementación de interfaces:
Herencia Ejemplo
Ninguna class ClassA { }
// Default constructor:
public Kid()
{
name = "N/A";
}
// Constructor:
public Kid(string name, int age)
{
this.name = name;
this.age = age;
}
// Printing method:
public void PrintKid()
{
Console.WriteLine("{0}, {1} years old.", name, age);
}
}
class MainClass
{
static void Main()
{
// Create objects
// Objects must be created using the new operator:
Kid kid1 = new Kid("Craig", 11);
Kid kid2 = new Kid("Sally", 10);
// Create an object using the default constructor:
Kid kid3 = new Kid();
// Display results:
Console.Write("Kid #1: ");
kid1.PrintKid();
Console.Write("Kid #2: ");
kid2.PrintKid();
Console.Write("Kid #3: ");
kid3.PrintKid();
}
}
Resultados
Kid #1: Craig, 11 years old.
Kid #2: Sally, 10 years old.
Kid #3: N/A, 0 years old.
Comentarios
En el ejemplo anterior, observe que sólo se puede obtener acceso a los campos privados (name y age) a través de los métodos
públicos de la clase Kid. Por ejemplo, no es posible imprimir un valor name de la clase kid, desde el método Main, con una
instrucción como ésta:
Console.Write(kid1.name); // Error
El acceso a los miembros privados de Kid desde Main sólo sería posible si Main fuera un miembro de la clase.
Los tipos declarados en una clase sin un modificador de acceso tienen como valor predeterminado private, de modo que los
miembros de datos de este ejemplo seguirían siendo private aunque se quite la palabra clave.
Por último, observe que, para el objeto creado mediante el constructor predeterminado (kid3), el campo age se inicializó a cero
de forma predeterminada.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.6 Clases y objetos
3.4.4 Miembros de clase
4.2.1 Tipos de clase
10 Clases
Vea también
Referencia
Palabras clave de C#
Tipos de referencia (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
La palabra clave delegate se usa para declarar un tipo de referencia, que puede utilizarse para encapsular un método con
nombre o anónimo. Los delegados son similares a los punteros a funciones de C++, pero son más seguros y proporcionan
mayor seguridad de tipos. Para las aplicaciones de delegados, vea Delegados y Delegados genéricos.
Comentarios
Los delegados son la base de los eventos.
Se pueden crear instancias de un delegado asociándolo a un método con nombre o anónimo. Para obtener más información,
vea Métodos con nombre y Métodos anónimos.
Para el uso con métodos con nombre, se deben crear instancias del delegado con un método que tenga una firma aceptable.
Para obtener más información sobre el grado de variación permitida en la firma de método, vea
Covarianza y contravarianza en los delegados. Para el uso con métodos anónimos, el delegado y el código que se van a asociar
se declaran juntos. En esta sección se describen las dos formas de crear instancias de delegados.
using System;
// Declare delegate -- defines required signature:
delegate void SampleDelegate(string message);
class MainClass
{
// Regular method that matches signature:
static void SampleDelegateMethod(string message)
{
Console.WriteLine(message);
}
interface ISampleInterface
{
void SampleMethod();
}
Comentarios
Una interfaz puede ser miembro de un espacio de nombres o de una clase, y puede contener firmas de los siguientes
miembros:
Métodos
Propiedades
Indizadores
Eventos
Una interfaz puede heredar de una o varias interfaces base.
Cuando una lista de tipos base contiene una clase base e interfaces, la clase base debe aparecer primero en la lista.
Una clase que implementa una interfaz puede implementar explícitamente miembros de esa interfaz. Sólo se puede tener
acceso a un miembro explícitamente implementado mediante una instancia de la interfaz, y no mediante una instancia de
clase, por ejemplo:
Para obtener información más detallada y ejemplos de código de la implementación de interfaces explícita, vea
Implementación explícita de interfaz (Guía de programación de C#).
Ejemplo
En el siguiente ejemplo, se muestra la implementación de una interfaz. En este ejemplo, la interfaz IPoint contiene la
declaración de propiedades, la cual es responsable de establecer y obtener los valores de los campos. La clase Point contiene
la implementación de las propiedades.
// keyword_interface_2.cs
// Interface implementation
using System;
interface IPoint
{
// Property signatures:
int x
{
get;
set;
}
int y
{
get;
set;
}
}
// Property implementation:
public int x
{
get
{
return _x;
}
set
{
_x = value;
}
}
public int y
{
get
{
return _y;
}
set
{
_y = value;
}
}
}
class MainClass
{
static void PrintPoint(IPoint p)
{
Console.WriteLine("x={0}, y={1}", p.x, p.y);
}
Resultados
My Point: x=2, y=3
// keyword_object.cs
using System;
class SampleClass
{
public int i = 10;
}
class MainClass
{
static void Main()
{
object a;
a = 1; // an example of boxing
Console.WriteLine(a);
Console.WriteLine(a.GetType());
Console.WriteLine(a.ToString());
a = new SampleClass();
SampleClass classRef;
classRef = (SampleClass)a;
Console.WriteLine(classRef.i);
}
}
Resultados
1
System.Int32
1
10
string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine((object)a == (object)b);
Esto presenta "True" y, después, "False" porque el contenido de las cadenas es equivalente, pero a y b no hacen referencia a la
misma instancia de cadena.
El operador + concatena cadenas:
string b = "h";
b += "ello";
El operador [] se puede utilizar para tener acceso a caracteres individuales de un objeto string:
Los literales de cadena son objetos de tipo string que se pueden escribir de dos formas: entre comillas o entre comillas y
precedidos de @. Los literales de cadena se deben encerrar entre comillas ("):
Los literales de cadena pueden contener cualquier literal de carácter, incluidas las secuencias de escape:
string a = "\\\u0066\n";
Esta cadena contiene una barra diagonal inversa, la letra f y el carácter de nueva línea.
Nota
El código de escape \udddd (donde dddd es un número de cuatro dígitos) representa el carácter Unicode U+dddd. También
se reconocen los códigos de escape Unicode de 8 dígitos: \udddd\udddd.
Los literales de cadena entrecomillados y precedidos por @ empiezan con este símbolo y se encierran entre comillas. Por
ejemplo:
La ventaja de utilizar la combinación del signo @ y el entrecomillado es que las secuencias de escape no se procesan, lo que
facilita la escritura, por ejemplo, de un nombre de archivo completo:
Para incluir comillas tipográficas en una cadena precedida del símbolo @, escriba las comillas dos veces:
Otro uso del símbolo @ consiste en utilizar identificadores de referencia (/reference) que resulten ser palabras clave de C#.
Ejemplo
// keyword_string.cs
using System;
class TestClass
{
static void Main()
{
string a = "\u0068ello ";
string b = "world";
Console.WriteLine( a + b );
Console.WriteLine( a + b == "hello world" );
}
}
Resultados
hello world
True
void SampleMethod();
void también se utiliza en un contexto no seguro para declarar un puntero a un tipo desconocido. Para obtener más
información, vea Tipos de puntero (Guía de programación de C#).
void es un alias para el tipo System.Void de .NET Framework.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.6.5 Métodos
Vea también
Referencia
Palabras clave de C#
Tipos de referencia (Referencia de C#)
Tipos de valores (Referencia de C#)
Métodos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Código no seguro y punteros (Guía de programación de C#)
Otros recursos
Referencia de C#
Referencia del lenguaje C#
byte System.Byte
sbyte System.SByte
char System.Char
decimal System.Decimal
double System.Double
float System.Single
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
object System.Object
short System.Int16
ushort System.UInt16
string System.String
Comentarios
Todos los tipos de la tabla, excepto object y string, se conocen como tipos simples.
Las palabras clave de tipos de C# y sus alias son intercambiables. Por ejemplo, se puede declarar una variable entera de
cualquiera de estas dos formas:
int x = 123;
System.Int32 x = 123;
Para mostrar el tipo real de cualquier tipo de C#, utilice el método del sistema GetType(). Por ejemplo, la siguiente instrucción
muestra el alias de sistema que representa el tipo de myVariable:
Console.WriteLine(myVariable.GetType());
Si el valor representado por un literal entero supera el intervalo de valores del tipo ulong, se producirá un error de
compilación.
Vea también
Referencia
Palabras clave de C#
Tabla de tipos integrados (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Tabla de tipos de punto flotante (Referencia de C#)
Tabla de valores predeterminados (Referencia de C#)
Aplicar formato a la tabla de resultados numéricos (Referencia de C#)
Tablas de referencia de tipos (Referencia de C#)
Referencia del lenguaje C#
Vea también
Referencia
Tabla de tipos integrados (Referencia de C#)
Tabla de tipos integrales (Guía de programación de C#)
decimal (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Tabla de valores predeterminados (Referencia de C#)
Aplicar formato a la tabla de resultados numéricos (Referencia de C#)
Tablas de referencia de tipos (Referencia de C#)
Referencia del lenguaje C#
int myInt = 0;
byte 0
char '\0'
decimal 0,0M
double 0,0D
float 0,0F
int 0
long 0L
sbyte 0
short 0
struct El valor obtenido al asignar los valores predeterminados a los campos de tipo de valor y el valor null a los campo
s de tipo de referencia.
uint 0
ulong 0
ushort 0
Vea también
Referencia
Tipos de valores (Referencia de C#)
Tabla de tipos integrados (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Tablas de referencia de tipos (Referencia de C#)
Referencia del lenguaje C#
enum Enumeración
Vea también
Referencia
Tipos de valores (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Aplicar formato a la tabla de resultados numéricos (Referencia de C#)
Tablas de referencia de tipos (Referencia de C#)
Referencia del lenguaje C#
byte short, ushort, int, uint, long, ulong, float, double o decimal
float double
float sbyte, byte, short, ushort, int, uint, long, ulong, char o decimal
double sbyte, byte, short, ushort, int, uint, long, ulong, char, float o decimal
decimal sbyte, byte, short, ushort, int, uint, long, ulong, char, float o double
Comentarios
Las conversiones numéricas explícitas pueden producir pérdida de precisión o provocar excepciones.
Cuando se convierte un valor decimal en un tipo integral, este valor se redondea hacia cero al valor entero más
próximo. Si el valor entero resultante queda fuera del intervalo del tipo de destino, se produce una excepción
OverflowException.
Cuando se convierte un valor double o float en un tipo integral, el valor se trunca. Si el valor entero resultante queda
fuera del intervalo del valor de destino, el resultado depende del contexto de comprobación de desbordamiento. En un
contexto comprobado, se produce una excepción OverflowException, mientras que en un contexto no comprobado, el
resultado es un valor no especificado del tipo de destino.
Cuando se convierte double en float, el valor double se redondea al valor float más próximo. Si el valor de tipo
double es demasiado pequeño o demasiado grande para ajustarse al tipo de destino, el resultado será cero o infinito.
Cuando se convierte float o double en decimal, el valor de origen se convierte en una representación decimal y se
redondea al número más próximo después de la vigésimo octava posición decimal si es necesario. Según el valor de
origen, se puede producir uno de los siguientes resultados:
Si el valor de origen es demasiado pequeño para representarlo como decimal, el resultado se convierte en cero.
Si el valor de origen es NaN (no es un número), infinito o demasiado grande para ser representado como
decimal, se produce una excepción OverflowException.
Cuando se convierte decimal en float o double, el valor decimal se redondea al valor double o float más próximo.
Para obtener más información sobre conversión explícita, vea 6.2 Explícita en la Especificación del lenguaje C#. Para obtener
información sobre cómo tener acceso a la especificación, vea Especificación del lenguaje C#.
Vea también
Referencia
Tabla de tipos integrales (Guía de programación de C#)
Tabla de tipos integrados (Referencia de C#)
Tabla de conversiones numéricas implícitas (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Vea también
Referencia
string (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Tablas de referencia de tipos (Referencia de C#)
Referencia del lenguaje C#
abstract Indica que una clase está definida sólo como clase base de otras clases.
const Especifica que el valor del campo o de la variable local no se pueden modificar.
override Proporciona una nueva implementación de un miembro virtual heredado de una clase base.
readonly Declara un campo al cual sólo se pueden asignar valores como parte de la declaración o en un constr
uctor de la misma clase.
static Declara un miembro que pertenece al propio tipo en vez de a un objeto específico.
virtual Declara un método o un descriptor de acceso cuya implementación se puede cambiar mediante un m
iembro de reemplazo perteneciente a una clase derivada.
volatile Indica que un campo puede ser modificado en el programa por el sistema operativo, el hardware o u
n subproceso en ejecución de forma simultánea.
Vea también
Referencia
Palabras clave de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
protected Acceso limitado a la clase contenedora o a los tipos derivados de esta clase.
protected internal Acceso limitado al proyecto actual o a los tipos derivados de la clase contenedora.
Sólo se permite un modificador de acceso para un miembro o tipo, excepto cuando se utiliza la combinación protected
internal.
Los modificadores de acceso no se pueden utilizar en espacios de nombres. Los espacios de nombres no presentan
restricciones de acceso.
Según el contexto en el que se produce una declaración de miembro, sólo se permite declarar ciertos tipos de acceso. Si no se
especifica ningún modificador de acceso en una declaración de miembro, se utiliza el tipo de acceso predeterminado.
Los tipos de nivel superior, que no están anidados en otros tipos, sólo pueden tener accesibilidad internal o public. La
accesibilidad predeterminada para estos tipos es internal.
Los tipos anidados, que son miembros de otros tipos, pueden tener un tipo de acceso declarado como el que se indica en la
siguiente tabla.
Miembros de Accesibilidad predeterminada Accesibilidades declaradas permitidas
enum public Ninguna
La accesibilidad de un tipo anidado depende de su dominio de accesibilidad, el cual se determina mediante la accesibilidad
declarada para el miembro y el dominio de accesibilidad del tipo inmediato que lo contiene. Sin embargo, el dominio de
accesibilidad de un tipo anidado no puede exceder al del tipo contenedor.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
3.5.1 Accesibilidad declarada
3.5.3 Acceso protegido para miembros de instancia
3.5.4 Restricciones de accesibilidad
10.2.3 Modificadores de acceso
10.2.6.2 Accesibilidad declarada
Vea también
Referencia
Palabras clave de C#
Modificadores de acceso (Referencia de C#)
Dominio de accesibilidad (Referencia de C#)
Restricciones en el uso de los niveles de accesibilidad (Referencia de C#)
Modificadores de acceso (Guía de programación de C#)
public (Referencia de C#)
private (Referencia de C#)
protected (Referencia de C#)
internal (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
// cs_Accessibility_Domain.cs
using System;
namespace AccessibilityDomainNamespace
{
public class T1
{
public static int publicInt;
internal static int internalInt;
private static int privateInt = 0; // CS0414
public class M1
{
public static int publicInt;
internal static int internalInt;
private static int privateInt = 0; // CS0414
}
private class M2
{
public static int publicInt = 0;
internal static int internalInt = 0;
private static int privateInt = 0; // CS0414
}
}
class MainClass
{
static void Main()
{
// Access is unlimited:
T1.publicInt = 1;
// Accessible only in current assembly:
T1.internalInt = 2;
// Error: inaccessible outside T1:
// T1.myPrivateInt = 3;
// Access is unlimited:
T1.M1.publicInt = 1;
// Accessible only in current assembly:
T1.M1.internalInt = 2;
// Error: inaccessible outside M1:
// T1.M1.myPrivateInt = 3;
// Error: inaccessible outside T1:
// T1.M2.myPublicInt = 1;
// Error: inaccessible outside T1:
// T1.M2.myInternalInt = 2;
// Error: inaccessible outside M2:
// T1.M2.myPrivateInt = 3;
}
}
}
La siguiente tabla resume las restricciones de uso de los niveles de accesibilidad declarados.
Contexto Comentarios
Clases La clase base directa de un tipo de clase debe ser al menos tan accesible como el propio tipo de clase.
Interfaces Las interfaces base explícitas de un tipo de interfaz deben ser al menos tan accesibles como el propio tipo de int
erfaz.
Delegados El tipo de valor devuelto y los tipos de los parámetros de un tipo delegado deben ser al menos tan accesibles co
mo el propio tipo delegado.
Constantes El tipo de una constante debe ser al menos tan accesible como la propia constante.
Campos El tipo de un campo debe ser al menos tan accesible como el propio campo.
Métodos El tipo de valor devuelto y los tipos de parámetros de un método deben ser al menos tan accesibles como el pro
pio método.
Propiedades El tipo de una propiedad debe ser al menos tan accesible como la misma propiedad.
Eventos El tipo de un evento debe ser al menos tan accesible como el propio evento.
Indizadores El tipo y los tipos de parámetros de un indizador deben ser al menos tan accesibles como el propio indizador.
Operadores El tipo de valor devuelto y los tipos de parámetros de un operador deben ser al menos tan accesibles como el p
ropio operador.
Constructores Los tipos de parámetros de un constructor deben ser al menos tan accesibles como el propio constructor.
Ejemplo
El siguiente ejemplo contiene declaraciones erróneas de diferentes tipos. El comentario que sigue a cada declaración indica el
error esperado del compilador.
// Restrictions_on_Using_Accessibility_Levels.cs
// CS0052 expected as well as CS0053, CS0056, and CS0057
// To make the program work, change access level of both class B
// and MyPrivateMethod() to public.
using System;
// A delegate:
delegate int MyDelegate();
class B
{
// A private method:
static int MyPrivateMethod()
{
return 0;
}
}
public class A
{
// Error: The type B is less accessible than the field A.myField.
public B myField = new B();
public B MyMethod()
{
// Error: The type B is less accessible
// than the method A.MyMethod.
return new B();
}
// Error: The type B is less accessible than the property A.MyProp
public B MyProp
{
set
{
}
}
Encontrará una comparación de internal con los otros modificadores de acceso en Niveles de accesibilidad y
Modificadores de acceso (Guía de programación de C#).
Para obtener más información sobre los ensamblados, vea
Ensamblados y Caché de ensamblados global (Guía de programación de C#).
Un uso habitual del acceso de tipo interno se da en el desarrollo basado en componentes, ya que permite a un grupo de
componentes cooperar de manera privada sin estar expuesto al resto del código de la aplicación. Por ejemplo, una estructura
para crear interfaces gráficas de usuario podría proporcionar clases Control y Form que cooperan mediante miembros con
acceso de tipo internal. Como estos miembros son internos, no están expuestos al código que utiliza la estructura.
Si se hace referencia a un tipo o miembro con acceso interno fuera del ensamblado en el que se definió, produce un error.
Nota
El método internal virtual puede reemplazarse en algunos lenguajes, como en el Lenguaje intermedio de Microsoft (MSIL) t
extual mediante Ilasm.exe, aunque no se pueda reemplazar utilizando C#.
Ejemplo
Este ejemplo contiene dos archivos, Assembly1.cs y Assembly2.cs. El primer archivo contiene una clase base interna,
BaseClass. En el segundo archivo, un intento de crear instancias BaseClass generará un error.
// Assembly1.cs
// compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}
// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // CS0122
}
}
En este ejemplo, utilice los mismos archivos que utilizó en el primer ejemplo y cambie el nivel de accesibilidad de BaseClass a
public. Además cambie el nivel de accesibilidad del miembro IntM a internal. En este caso, puede crear instancias de la clase,
pero no puede tener acceso al miembro interno.
// Assembly2.cs
// compile with: /target:library
public class BaseClass
{
internal static int intM = 0;
}
// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // Ok.
BaseClass.intM = 444; // CS0117
}
}
class Employee
{
private int i;
double d; // private access by default
}
Los tipos anidados del mismo cuerpo también pueden tener acceso a esos miembros privados.
Hacer referencia a un miembro privado fuera de la clase o estructura en la que se declara produce un error de compilación.
Encontrará una comparación de private con los otros modificadores de acceso en Niveles de accesibilidad (Referencia de C#)
y Modificadores de acceso (Guía de programación de C#).
Ejemplo
En este ejemplo, la clase Employee contiene dos miembros de datos privados, name y salary. Como miembros privados, sólo
pueden tener acceso a ellos los métodos miembro; por tanto, hay que agregar los métodos públicos denominados GetName y
Salary para permitir el acceso controlado a los miembros privados. Se tiene acceso al miembro name a través del método
público y se tiene acceso al miembro salary a través de una propiedad pública de sólo lectura. (Vea
Propiedades (Guía de programación de C#) para obtener más información.)
// private_keyword.cs
using System;
class Employee
{
private string name = "FirstName, LastName";
private double salary = 100.0;
class MainClass
{
static void Main()
{
Employee e = new Employee();
// The data members are inaccessible (private), so
// then can't be accessed like this:
// string n = e.name;
// double s = e.salary;
// protected_keyword.cs
using System;
class A
{
protected int x = 123;
}
class B : A
{
static void Main()
{
A a = new A();
B b = new B();
Los miembros de una estructura no se pueden proteger, ya que la estructura no se puede heredar.
Ejemplo
En este ejemplo, la clase DerivedPoint se deriva de Point; por lo tanto, puede obtener acceso a los miembros protegidos de la
clase base directamente desde la clase derivada.
// protected_keyword_2.cs
using System;
class Point
{
protected int x;
protected int y;
}
class DerivedPoint: Point
{
static void Main()
{
DerivedPoint dp = new DerivedPoint();
Resultados
x = 10, y = 15
Comentarios
Si se cambian los niveles de acceso de x e y a private, el compilador producirá los siguientes mensajes de error:
'Point.y' is inaccessible due to its protection level.
'Point.x' is inaccessible due to its protection level.
class SampleClass
{
public int x; // No access restrictions.
}
Para obtener más información, vea Modificadores de acceso (Guía de programación de C#) y
Niveles de accesibilidad (Referencia de C#).
Ejemplo
En el siguiente ejemplo, se declaran dos clases, Point y MainClass. El acceso a los miembros públicos x e y de Point se realiza
directamente desde MainClass.
// protected_public.cs
// Public access
using System;
class Point
{
public int x;
public int y;
}
class MainClass
{
static void Main()
{
Point p = new Point();
// Direct access to public members:
p.x = 10;
p.y = 15;
Console.WriteLine("x = {0}, y = {1}", p.x, p.y);
}
}
Resultado
x = 10, y = 15
Si se cambia el nivel de acceso de public a private o protected, se aparecerá el siguiente mensaje de error:
'Point.y' is inaccessible due to its protection level.
La implementación la proporciona un método de reemplazooverride (Referencia de C#), que es miembro de una clase no
abstracta.
Utilizar los modificadores static o virtual en una declaración de método abstracto produce un error.
Las propiedades abstractas funcionan como los métodos abstractos, salvo las diferencias en la sintaxis de las declaraciones y
llamadas.
Es incorrecto utilizar el modificador abstract para una propiedad estática.
Una propiedad abstracta heredada se puede reemplazar en una clase derivada si se incluye una declaración de propiedad
que utilice el modificador override.
Una clase abstracta debe proporcionar implementaciones para todos los miembros de la interfaz.
Una clase abstracta que implementa una interfaz podría asignar los métodos de la interfaz a métodos abstractos. Por ejemplo:
interface I
{
void M();
}
abstract class C: I
{
public abstract void M();
}
Ejemplo
En este ejemplo, la clase DerivedClass se deriva de una clase abstracta BaseClass. La clase abstracta contiene un método
abstracto, AbstractMethod, y dos propiedades abstractas, X y Y.
// abstract_keyword.cs
// Abstract Classes
using System;
abstract class BaseClass // Abstract class
{
protected int _x = 100;
protected int _y = 150;
public abstract void AbstractMethod(); // Abstract method
public abstract int X { get; }
public abstract int Y { get; }
}
class DerivedClass : BaseClass
{
public override void AbstractMethod()
{
_x++;
_y++;
}
public override int X // overriding property
{
get
{
return _x + 10;
}
}
public override int Y // overriding property
{
get
{
return _y + 10;
}
}
static void Main()
{
DerivedClass o = new DerivedClass();
o.AbstractMethod();
Console.WriteLine("x = {0}, y = {1}", o.X, o.Y);
}
}
Resultados
x = 111, y = 161
Comentarios
En el ejemplo anterior, si intenta crear una instancia de la clase abstracta mediante una instrucción como la siguiente:
se obtendrá un error que indica que el compilador no puede crear una instancia de la clase abstracta 'BaseClass'.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.6.5.4 Métodos virtuales, abstractos y de reemplazo
10.1.1.1 Clases abstractas
Vea también
Referencia
Modificadores (Referencia de C#)
virtual (Referencia de C#)
override (Referencia de C#)
Palabras clave de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
const int x = 0;
public const double gravitationalConstant = 6.673e-11;
private const string productName = "Visual C#";
Comentarios
El tipo de una declaración de constantes especifica el tipo de los miembros que se incluyen en la declaración. Una expresión
constante debe dar un valor del tipo destino o de un tipo que se pueda convertir implícitamente en el tipo destino.
Una expresión constante es una expresión que se puede evaluar completamente en tiempo de compilación. Por consiguiente,
los únicos valores posibles para constantes de tipos de referencia son string, y null.
La declaración de constante puede declarar varias constantes, por ejemplo:
Nota
La palabra clave readonly es diferente de la palabra clave const. Un campo const sólo puede inicializarse en la declaración d
el campo. Un campo readonly puede inicializarse en la declaración o en un constructor. Por lo tanto, los campos readonly p
ueden tener diferentes valores en función del constructor que se utilice. Asimismo, mientras que un campo const es una con
stante en tiempo de compilación, el campo readonly puede utilizarse para constantes en tiempo de ejecución, como se mue
stra en la línea siguiente: public static readonly uint l1 = (uint)DateTime.Now.Ticks;
Ejemplo
// const_keyword.cs
using System;
public class ConstTest
{
class SampleClass
{
public int x;
public int y;
public const int c1 = 5;
public const int c2 = c1 + 5;
Resultados
x = 11, y = 22
c1 = 5, c2 = 10
// const_keyword_2.cs
using System;
public class MainClass
{
static void Main()
{
const int c = 707;
Console.WriteLine("My local constant = {0}", c);
}
}
Resultados
My local constant = 707
Los eventos son un tipo especial de delegado multidifusión que sólo se puede invocar desde dentro de la clase o estructura
donde se declaran (la clase de editor). Si otras clases o estructuras se suscriben al evento, se llamará a sus métodos de
controlador de eventos cuando la clase de editor genere el evento. Para obtener más información y ejemplos de código, vea
Eventos (Guía de programación de C#) y Delegados (Guía de programación de C#).
Los eventos se pueden marcar como public, private, protected, internal o protectedinternal. Estos modificadores de acceso
definen cómo los usuarios de la clase pueden tener acceso al evento. Para obtener más información, vea
Modificadores de acceso (Guía de programación de C#).
Palabras clave y eventos
Las palabras clave siguientes se aplican a los eventos.
Palabr Descripción Para obtener más información
a clave
static Hace que el evento esté siempre disponible para los ll Clases estáticas y sus miembros (Guía de programación de C#)
amadores, aunque no exista ninguna instancia de la cl
ase.
virtual Permite que las clases derivadas reemplacen el compo Herencia (Guía de programación de C#)
rtamiento del evento mediante la palabra clave
override.
Un evento puede declararse como evento estático mediante la palabra clave static. Esto hace que el evento esté siempre
disponible para los llamadores, aunque no exista ninguna instancia de la clase. Para obtener más información, vea
Clases estáticas y sus miembros (Guía de programación de C#).
Un evento puede marcarse como virtual mediante la palabra clave virtual. Esto permite que las clases derivadas reemplacen el
comportamiento del evento mediante la palabra clave override. Para obtener más información, vea
Herencia (Guía de programación de C#). Un evento que reemplaza un evento virtual también puede ser de tipo sealed, lo que
especifica que ya no es virtual para las clases derivadas. Por último, un evento se puede declarar como abstract, lo que significa
que el compilador no generará los bloques de descriptor de acceso a eventos add y remove y, por tanto, las clases derivadas
deben proporcionar su propia implementación.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.6.6.4 Eventos
7.13.3 Asignación de eventos
10.7 Eventos
13.2.3 Eventos de interfaz
Vea también
Tareas
Cómo: Combinar delegados (delegados de multidifusión) (Guía de programación de C#)
Referencia
Palabras clave de C#
Modificadores (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
[DllImport("avifil32.dll")]
private static extern void AVIFileInit();
Nota
La palabra clave extern también puede definir un alias de ensamblado externo, lo que hace posible hacer referencia a difere
ntes versiones del mismo componente desde un único ensamblado. Para obtener más información, vea
alias externo (Referencia de C#).
Es incorrecto utilizar simultáneamente los modificadores abstract (Referencia de C#) y extern para modificar el mismo
miembro. El uso del modificador extern significa que el método se implementa fuera del código de C#, mientras que el uso
del modificador abstract significa que la clase no incluye la implementación del método.
Nota
El uso de la palabra clave extern es más limitado que en C++. Para compararla con la palabra clave de C++, vea
Using extern to Specify Linkage en la Referencia del lenguaje C++.
Ejemplo
En este ejemplo, el programa recibe una cadena del usuario y la muestra dentro de un cuadro de mensaje. El programa utiliza
el método MessageBox importado de la biblioteca User32.dll.
using System;
using System.Runtime.InteropServices;
class MainClass
{
[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);
En este ejemplo se crea un archivo DLL desde un programa de C invocado desde el programa de C# del siguiente ejemplo.
// cmdll.c
// compile with: /LD
int __declspec(dllexport) SampleMethod(int i)
{
return i*10;
}
Este ejemplo utiliza dos archivos, CM.cs y Cmdll.c, para demostrar el uso de extern. El archivo C es un archivo DLL externo
creado en el ejemplo 2 que se invoca desde el programa escrito en C#.
// cm.cs
using System;
using System.Runtime.InteropServices;
public class MainClass
{
[DllImport("Cmdll.dll")]
public static extern int SampleMethod(int x);
static void Main()
{
Console.WriteLine("SampleMethod() returns {0}.", SampleMethod(5));
}
}
Resultados
SampleMethod() returns 50.
Comentarios
Para generar el proyecto:
Compile Cmdll.c como una DLL mediante la línea de comandos de Visual C++:
cl /LD Cmdll.c
De esta forma, se creará el archivo ejecutable CM.exe. Cuando ejecute este programa, SampleMethod pasará el valor 5 al archivo
DLL, el cual devolverá el valor multiplicado por 10.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
10.5.7 Métodos externos
Vea también
Referencia
Palabras clave de C#
Modificadores (Referencia de C#)
System.Runtime.InteropServices.DllImportAttribute
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Para obtener más información sobre el uso de la palabra clave override, vea
Control de versiones con las palabras clave Override y New (Guía de programación de C#) y
Saber cuándo utilizar las palabras clave Override y New (Guía de programación de C#).
Comentarios
El método override proporciona una nueva implementación de un miembro heredado de una clase base. El método
reemplazado por una declaración override se conoce como método base reemplazado. El método base reemplazado debe
tener la misma firma que el método override. Para obtener información sobre herencias, vea Herencia (Visual C#).
No se puede reemplazar un método estático o no virtual. El método base reemplazado debe ser virtual, abstract u override.
Una declaración override no puede cambiar la accesibilidad del método virtual. El método override y el método virtual
deben tener el mismo modificador de nivel de acceso.
No se pueden utilizar los modificadores new, static, virtual o abstract para modificar un método override.
Una declaración de propiedad de reemplazo debe especificar el mismo modificador de acceso, tipo y nombre que la propiedad
heredada, y la propiedad reemplazada debe ser virtual, abstract u override.
Ejemplo
Este ejemplo define una clase base denominada Employee y una clase derivada denominada SalesEmployee. La clase
SalesEmployee incluye una propiedad adicional, salesbonus, y reemplaza al método CalculatePay para tenerlo en cuenta.
using System;
class TestOverride
{
public class Employee
{
public string name;
// Basepay is defined as protected, so that it may be
// accessed only by this class and derrived classes.
protected decimal basepay;
// Constructor to set the name and basepay values.
public Employee(string name, decimal basepay)
{
this.name = name;
this.basepay = basepay;
}
// Declared virtual so it can be overridden.
public virtual decimal CalculatePay()
{
return basepay;
}
}
Resultados
Employee Alice earned: 1500
Employee Bob earned: 1200
class Age
{
readonly int _year;
Age(int year)
{
_year = year;
}
void ChangeYear()
{
_year = 1967; // Will not compile.
}
}
Comentarios
Sólo se puede asignar un valor a un campo readonly en los siguientes contextos:
Cuando la variable se inicializa en la declaración, por ejemplo:
Para un campo de instancia, en los constructores de instancia de la clase que contiene la declaración de campo; para un
campo estático, en el constructor estático de la clase que contiene la declaración de campo. Éstos son también los únicos
contextos en los que es válido pasar un campo readonly como parámetro out o ref.
Nota
La palabra clave readonly es diferente de la palabra clave const. Un campo const sólo puede inicializarse en la declaración d
el campo. Un campo readonly puede inicializarse en la declaración o en un constructor. Por lo tanto, los campos readonly p
ueden tener diferentes valores en función del constructor que se utilice. Además, mientras que un campo const es una const
ante en tiempo de compilación, el campo readonly puede utilizarse para constantes en tiempo de ejecución, como muestra
el siguiente ejemplo:
Nota
public static readonly uint l1 = (uint)DateTime.Now.Ticks;
Ejemplo
// cs_readonly_keyword.cs
// Readonly fields
using System;
public class ReadOnlyTest
{
class SampleClass
{
public int x;
// Initialize a readonly field
public readonly int y = 25;
public readonly int z;
public SampleClass()
{
// Initialize a readonly instance field
z = 24;
}
public SampleClass(int p1, int p2, int p3)
{
x = p1;
y = p2;
z = p3;
}
}
static void Main()
{
SampleClass p1 = new SampleClass(11, 21, 32); // OK
Console.WriteLine("p1: x={0}, y={1}, z={2}", p1.x, p1.y, p1.z);
SampleClass p2 = new SampleClass();
p2.x = 55; // OK
Console.WriteLine("p2: x={0}, y={1}, z={2}", p2.x, p2.y, p2.z);
}
}
Resultados
p1: x=11, y=21, z=32
p2: x=55, y=25, z=24
Comentarios
En el ejemplo anterior, si se utiliza una instrucción como:
p2.y = 66; // Error
que es el mismo error que se obtiene al intentar asignar un valor a una constante.
Especificación del lenguaje C#
Para obtener más información, vea la siguiente sección de Especificación del lenguaje C#.
10.4.2 Campos de sólo lectura
Vea también
Referencia
Palabras clave de C#
Modificadores (Referencia de C#)
const (Referencia de C#)
Campos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Es un error utilizar una clase sellada como una clase base o utilizar el modificador abstract con una clase sellada.
Las estructuras son tipos sealed implícitamente; por consiguiente, no se pueden heredar.
Para obtener más información sobre herencias, consulte Herencia (Guía de programación de C#).
Ejemplo
// cs_sealed_keyword.cs
using System;
sealed class SealedClass
{
public int x;
public int y;
}
class MainClass
{
static void Main()
{
SealedClass sc = new SealedClass();
sc.x = 110;
sc.y = 150;
Console.WriteLine("x = {0}, y = {1}", sc.x, sc.y);
}
}
Resultados
x = 110, y = 150
En el ejemplo anterior, si intenta heredar de la clase sealed mediante una instrucción como la siguiente:
class MyDerivedC: SealedClass {} // Error
Para obtener más información, vea Clases estáticas y sus miembros (Guía de programación de C#).
Comentarios
Una declaración de constante o tipo constituye, implícitamente, un miembro estático.
No se puede hacer referencia a un miembro estático por medio de una instancia. En vez de ello, se debe hacer referencia
por medio del nombre de tipo. Por ejemplo, considere la siguiente clase:
Para referirse al miembro estático x, use el nombre completo (a menos que sea accesible desde el mismo ámbito):
MyBaseC.MyStruct.x
Mientras que una instancia de una clase contiene una copia independiente de todos los campos de instancia de la clase,
sólo existe una copia de cada campo estático.
No es posible utilizar this para hacer referencia a descriptores de acceso de propiedades o métodos static.
Si la palabra clave static se aplica a una clase, todos los miembros de la clase deben ser estáticos.
Las clases, incluidas las clases estáticas, pueden tener constructores estáticos. Se llama a los constructores estáticos en
algún momento comprendido entre el inicio del programa y la creación de instancias de la clase.
Nota
El uso de la palabra clave static es más limitado que en C++. Para comparar con la palabra clave de C++, vea static.
Para comprender el uso de miembros estáticos, considere una clase que representa al empleado de una compañía. Suponga
que la clase contiene un método que cuenta empleados y un campo que almacena el número de empleados. Ni el método ni el
campo pertenecen a ninguna instancia de empleado. En vez de ello, pertenecen a la clase compañía. Por tanto, se deberían
declarar como miembros estáticos de la clase.
Ejemplo
Este ejemplo lee el nombre y el identificador de un nuevo empleado, incrementa en uno el contador de empleados y muestra
la información del nuevo empleado, así como el nuevo número de empleados. Por motivos de simplicidad, el programa lee el
número actual de empleados desde el teclado. En una aplicación real, esta información se leería desde un archivo.
// cs_static_keyword.cs
using System;
public class Employee
{
public string id;
public string name;
public Employee()
{
}
Entrada
Tara Strahan
AF643G
15
Resultados del ejemplo
Enter the employee's name: Tara Strahan
Enter the employee's ID: AF643G
Enter the current number of employees: 15
Name: Tara Strahan
ID: AF643G
New Number of Employees: 16
Este ejemplo muestra que aunque se puede inicializar un campo estático con otro campo estático aún sin declarar, el resultado
no estará definido hasta que no asigne explícitamente un valor al campo estático.
// cs_static_keyword_2.cs
using System;
class Test
{
static int x = y;
static int y = 5;
Test.x = 99;
Console.WriteLine(Test.x);
}
}
Resultados
0
5
99
El ámbito del contexto no seguro se extiende desde la lista de parámetros hasta el final del método, de modo que también se
pueden utilizar punteros en la lista de parámetros:
unsafe static void FastCopy ( byte* ps, byte* pd, int count ) {...}
También puede utilizar un bloque no seguro para habilitar el uso de código no seguro dentro del mismo. Por ejemplo:
unsafe
{
// Unsafe context: can use pointers here.
}
Para compilar código no seguro, se debe especificar la opción /unsafe del compilador. Common Language Runtime no puede
comprobar el código no seguro.
Ejemplo
// cs_unsafe_keyword.cs
// compile with: /unsafe
using System;
class UnsafeTest
{
// Unsafe method: takes pointer to int:
unsafe static void SquarePtrParam(int* p)
{
*p *= *p;
}
Resultados
25
La implementación de un miembro virtual puede reemplazarse por un miembro de reemplazo de una clase derivada. Para
obtener más información sobre cómo utilizar la palabra clave virtual, vea
Control de versiones con las palabras clave Override y New (Guía de programación de C#) y
Saber cuándo utilizar las palabras clave Override y New (Guía de programación de C#).
Comentarios
Cuando se invoca un método virtual, el tipo en tiempo de ejecución del objeto se comprueba para ver si existe un miembro de
reemplazo. Se realiza una llamada al miembro de reemplazo que está en la clase de mayor derivación, el cual puede ser el
miembro original, si no existe ninguna clase derivada que haya reemplazado el miembro.
De forma predeterminada, los métodos son no virtuales. No se puede reemplazar un método no virtual.
No puede utilizar el modificador virtual con los modificadores static, abstract, private u override.
Las propiedades virtuales funcionan como los métodos abstractos, salvo en lo que se refiere a las diferencias en la sintaxis de
las declaraciones e invocaciones.
Es incorrecto utilizar el modificador virtual para una propiedad estática.
Una propiedad virtual heredada se puede reemplazar en una clase derivada si se incluye una declaración de propiedad
que use el modificador override.
Ejemplo
En este ejemplo, la clase Dimensions contiene las dos coordenadas x, y, y el método virtual Area(). Las clases de las diferentes
figuras, como Circle, Cylinder y Sphere, heredan la clase Dimensions, que permite calcular el área de la superficie de cada
figura. Cada clase derivada dispone de su propia implementación de Area() (método de reemplazo). El programa calcula y
muestra el área apropiada para cada implementación del método Area() según el objeto asociado al método.
Observe que todas las clases heredadas Circle, Sphere y Cylinder utilizan constructores que inicializan la clase base, por
ejemplo:
// cs_virtual_keyword.cs
using System;
class TestClass
{
public class Dimensions
{
public const double PI = Math.PI;
protected double x, y;
public Dimensions()
{
}
public Dimensions(double x, double y)
{
this.x = x;
this.y = y;
}
public virtual double Area()
{
return x * y;
}
}
Resultados
Area of Circle = 28.27
Area of Sphere = 113.10
Area of Cylinder = 150.80
// csharp_volatile.cs
// compile with: /target:library
class Test
{
public volatile int i;
Test(int _i)
{
i = _i;
}
}
Comentarios
Si la expresión en el paréntesis se evalúa como true, a continuación se ejecuta la instrucción Console.WriteLine("The boolean
flag is set to ture."); . Después de ejecutar la instrucción if, el control se transfiere a la siguiente instrucción. Else no se
ejecuta en este ejemplo.
Si se desea ejecutar más de una instrucción, es posible ejecutar varias instrucciones en forma condicional al incluirlas en
bloques mediante {}, al igual que en el ejemplo anterior.
Las instrucciones que se van a ejecutar como resultado de comprobar la condición pueden ser de cualquier tipo, incluida otra
instrucción if anidada dentro de la instrucción if original. En las instrucciones if anidadas, la cláusula else pertenece a la última
instrucción if que no tiene una cláusula else correspondiente. Por ejemplo:
if (x > 10)
if (y > 20)
Console.Write("Statement_1");
else
Console.Write("Statement_2");
En este ejemplo, se mostrará Statement_2 si la condición (y > 20) se evalúa como false. No obstante, si desea asociar
Statement_2 a la condición (x >10), utilice llaves:
if (x > 10)
{
if (y > 20)
Console.Write("Statement_1");
}
else
Console.Write("Statement_2");
En este caso, se mostrará Statement_2 si la condición (x > 10) se evalúa como false.
Ejemplo 1
En este ejemplo, se escribe un carácter desde el teclado y el programa comprueba si se trata de un carácter alfabético. En ese
caso, comprueba si es minúscula o mayúscula. En cada caso, se muestra el mensaje apropiado.
// statements_if_else.cs
// if-else example
using System;
class IfTest
{
static void Main()
{
Console.Write("Enter a character: ");
char c = (char)Console.Read();
if (Char.IsLetter(c))
{
if (Char.IsLower(c))
{
Console.WriteLine("The character is lowercase.");
}
else
{
Console.WriteLine("The character is uppercase.");
}
}
else
{
Console.WriteLine("Not an alphabetic character.");
}
}
}
Resultado
2
Resultados del ejemplo
Enter a character: 2
The character is not an alphabetic character.
Ejecución Nº 3:
Enter a character: h
The character is lowercase.
También es posible extender la instrucción if de modo que puedan controlarse varias condiciones, mediante la construcción
else-if siguiente:
if (Condition_1)
{
// Statement_1;
}
else if (Condition_2)
{
// Statement_2;
}
else if (Condition_3)
{
// Statement_3;
}
else
{
// Statement_n;
}
Ejemplo 2
Este ejemplo comprueba si el carácter especificado es una letra minúscula, mayúscula o un número. En cualquier otro caso, se
tratará de un carácter no alfanumérico. El programa utiliza la anterior estructura else-if en escalera.
// statements_if_else2.cs
// else-if
using System;
public class IfTest
{
static void Main()
{
Console.Write("Enter a character: ");
char c = (char)Console.Read();
if (Char.IsUpper(c))
{
Console.WriteLine("Character is uppercase.");
}
else if (Char.IsLower(c))
{
Console.WriteLine("Character is lowercase.");
}
else if (Char.IsDigit(c))
{
Console.WriteLine("Character is a number.");
}
else
{
Console.WriteLine("Character is not alphanumeric.");
}
}
}
Resultado
E
Resultados del ejemplo
Enter a character: E
The character is uppercase.
Ejecución Nº 3:
Enter a character: 4
The character is a number.
Ejecución Nº 4:
Enter a character: $
The character is not alphanumeric.
int caseSwitch = 1;
switch (caseSwitch)
{
case 1:
Console.WriteLine("Case 1");
break;
case 2:
Console.WriteLine("Case 2");
break;
default:
Console.WriteLine("Default case");
break;
}
Comentarios
El control se transfiere a la instrucción case que coincide con el valor del modificador. La instrucción switch puede incluir
cualquier número de instancias case, sin embargo dos instrucciones case nunca pueden tener el mismo valor. La ejecución del
cuerpo de la instrucción empieza en la instrucción seleccionada y continúa hasta que la instrucción break transfiere el control
fuera del cuerpo case. Es necesario introducir una instrucción de salto como break después de cada bloque case, incluido el
último bloque, se trate de una instrucción case o de una instrucción default. Con una excepción, (a diferencia de la instrucción
switch de C++), C# no admite el paso implícito de una etiqueta case a otra. Esta excepción se produce si una instrucción case
no tiene ningún código.
Si ninguna expresión case coincide con el valor de la instrucción switch, entonces el control se transfiere a las instrucciones que
siguen la etiqueta default opcional. Si no existe ninguna etiqueta default, el control se transfiere fuera de la instrucción
switch.
Ejemplo
// statements_switch.cs
using System;
class SwitchTest
{
static void Main()
{
Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large");
Console.Write("Please enter your selection: ");
string s = Console.ReadLine();
int n = int.Parse(s);
int cost = 0;
switch(n)
{
case 1:
cost += 25;
break;
case 2:
cost += 25;
goto case 1;
case 3:
cost += 50;
goto case 1;
default:
Console.WriteLine("Invalid selection. Please select 1, 2, or 3.");
break;
}
if (cost != 0)
{
Console.WriteLine("Please insert {0} cents.", cost);
}
Console.WriteLine("Thank you for your business.");
}
}
Entrada
2
Resultados del ejemplo
Coffee sizes: 1=Small 2=Medium 3=Large
Please enter your selection: 2
Please insert 50 cents.
Thank you for your business.
El siguiente ejemplo muestra que se permite el paso de una etiqueta case a otra para etiquetas case vacías.
// statements_switch2.cs
using System;
class SwitchTest
{
static void Main()
{
int n = 2;
switch(n)
{
case 1:
case 2:
case 3:
Console.WriteLine("It's 1, 2, or 3.");
break;
default:
Console.WriteLine("Not sure what it is.");
break;
}
}
}
Resultados
It's 1, 2, or 3.
switch(s)
{
case "1":
// ...
case "2":
// ...
}
do (Referencia de C#)
La instrucción do ejecuta una instrucción o un bloque de instrucciones entre {} repetidamente hasta que una expresión
especificada se evalúe como false. En el ejemplo siguiente las instrucciones de bucle do-while se ejecutan con la condición de
que la variable y sea menor que 5.
Ejemplo
// statements_do.cs
using System;
public class TestDoWhile
{
public static void Main ()
{
int x = 0;
do
{
Console.WriteLine(x);
x++;
} while (x < 5);
}
}
Resultados
0
1
2
3
4
Comentarios
A diferencia de la instrucción while, un bucle do-while se ejecuta una vez antes de que se evalúe la expresión condicional.
En cualquier punto dentro del bloque do-while, puede salir del bucle utilizando la instrucción break. Puede pasar directamente
a la instrucción de evaluación de expresión while utilizando la instrucción continue; si la expresión se evalúa como true, la
ejecución continúa en la primera instrucción del bucle. Si la expresión se evalúa como false, la ejecución continúa en la primera
instrucción detrás del bucle do-while.
También se puede salir de un bucle do-while mediante las instrucciones goto, return o throw.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
5.3.3.8 Instrucciones Do
8.8.2 La instrucción do
Vea también
Referencia
Palabras clave de C#
The do-while Statement (C++)
Instrucciones de iteración (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
1
2
3
4
5
Comentarios
La instrucción for ejecuta la instrucción o instrucciones internas repetidamente del siguiente modo:
Primero, se evalúa el valor inicial de la variable i.
A continuación, mientras el valor de i sea menor o igual que 5, la condición se evalúa como true, se ejecuta la
instrucción Console.WriteLine y se vuelve a evaluar i.
Cuando i es mayor que 5, la condición se convierte en false y el control se transfiere fuera del bucle.
Puesto que la comprobación de la expresión condicional tiene lugar antes de la ejecución del bucle, las instrucciones internas
de un bucle for pueden no llegar a ejecutarse.
Todas las expresiones de la instrucción for son opcionales; por ejemplo, la siguiente instrucción se utiliza para crear un bucle
infinito:
for (;;)
{
// ...
}
// cs_foreach.cs
class ForEachTest
{
static void Main(string[] args)
{
int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
foreach (int i in fibarray)
{
System.Console.WriteLine(i);
}
}
}
Resultados
0
1
2
3
5
8
13
Resultados
Current value of n is 1
Current value of n is 2
Current value of n is 3
Current value of n is 4
Current value of n is 5
// statements_while_2.cs
using System;
class WhileTest
{
static void Main()
{
int n = 1;
while (n++ < 6)
{
Console.WriteLine("Current value of n is {0}", n);
}
}
}
Resultados
Current value of n is 2
Current value of n is 3
Current value of n is 4
Current value of n is 5
Current value of n is 6
Como la comprobación de la expresión while tiene lugar antes de la ejecución del bucle, las instrucciones internas de un bucle
while pueden no llegar a ejecutarse. Esto es diferente del bucle do que se ejecuta una o varias veces.
Un bucle while se puede terminar cuando una instrucción break, goto, return o throw transfiere el control fuera del bucle. Para
pasar el control a la siguiente iteración sin salir del bucle, use la instrucción continue. Observe la diferencia en los resultados de
los tres ejemplos anteriores con relación a dónde se incrementa int n. En el ejemplo siguiente no se genera ningún resultado.
// statements_while_3.cs
// no output is generated
using System;
class WhileTest
{
static void Main()
{
int n = 5;
while (++n < 6)
{
Console.WriteLine("Current value of n is {0}", n);
}
}
}
// statements_break.cs
using System;
class BreakTest
{
static void Main()
{
for (int i = 1; i <= 100; i++)
{
if (i == 5)
{
break;
}
Console.WriteLine(i);
}
}
}
Resultados
1
2
3
4
// statements_break2.cs
// break and switch
using System;
class Switch
{
static void Main()
{
Console.Write("Enter your selection (1, 2, or 3): ");
string s = Console.ReadLine();
int n = Int32.Parse(s);
switch (n)
{
case 1:
Console.WriteLine("Current value is {0}", 1);
break;
case 2:
Console.WriteLine("Current value is {0}", 2);
break;
case 3:
Console.WriteLine("Current value is {0}", 3);
break;
default:
Console.WriteLine("Sorry, invalid selection.");
break;
}
}
}
Entrada
1
Resultados del ejemplo
Enter your selection (1, 2, or 3): 1
Current value is 1
Comentarios
Si se escribió 4, el resultado sería:
// statements_continue.cs
using System;
class ContinueTest
{
static void Main()
{
for (int i = 1; i <= 10; i++)
{
if (i < 9)
{
continue;
}
Console.WriteLine(i);
}
}
}
Resultados
9
10
// statements_goto_switch.cs
using System;
class SwitchTest
{
static void Main()
{
Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large");
Console.Write("Please enter your selection: ");
string s = Console.ReadLine();
int n = int.Parse(s);
int cost = 0;
switch (n)
{
case 1:
cost += 25;
break;
case 2:
cost += 25;
goto case 1;
case 3:
cost += 50;
goto case 1;
default:
Console.WriteLine("Invalid selection.");
break;
}
if (cost != 0)
{
Console.WriteLine("Please insert {0} cents.", cost);
}
Console.WriteLine("Thank you for your business.");
}
}
Entrada
2
Resultados del ejemplo
Coffee sizes: 1=Small 2=Medium 3=Large
Please enter your selection: 2
Please insert 50 cents.
Thank you for your business.
El siguiente ejemplo muestra el uso de goto para salir de un conjunto de bucles anidados.
// statements_goto.cs
// Nested search loops
using System;
public class GotoTest1
{
static void Main()
{
int x = 200, y = 4;
int count = 0;
string[,] array = new string[x, y];
// Input a string:
string myNumber = Console.ReadLine();
// Search:
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
if (array[i, j].Equals(myNumber))
{
goto Found;
}
}
}
Found:
Console.WriteLine("The number {0} is found.", myNumber);
Finish:
Console.WriteLine("End of search.");
}
}
Entrada
44
Resultados del ejemplo
Enter the number to search for: 44
The number 44 is found.
End of search.
// statements_return.cs
using System;
class ReturnTest
{
static double CalculateArea(int r)
{
double area = r * r * Math.PI;
return area;
}
Resultados
The area is 78.54
Normalmente, la instrucción throw se utiliza con las instrucciones try-catch o try-finally. Cuando se produce una excepción, el
programa busca la instrucción catch que controla esa excepción.
También se puede volver a producir una excepción detectada mediante la instrucción throw. Para obtener más información,
incluidos ejemplos, vea try-catch e Producir excepciones.
Ejemplo
Este ejemplo muestra cómo provocar una excepción mediante la instrucción throw.
// throw example
using System;
public class ThrowTest
{
static void Main()
{
string s = null;
if (s == null)
{
throw new ArgumentNullException();
}
Resultados
Se produce la excepción ArgumentNullException.
Ejemplo de código
Vea los ejemplos de try-catch, try-finally y try-catch-finally.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
5.3.3.11 Instrucciones throw
8.9.5 La instrucción throw
Vea también
Tareas
Cómo: Iniciar excepciones explícitamente
Referencia
The try, catch, and throw Statements
Palabras clave de C#
Instrucciones para el control de excepciones (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
La cláusula catch se puede utilizar sin argumentos, en cuyo caso captura cualquier tipo de excepción y se conoce como
cláusula catch general. También puede aceptar un argumento de objeto derivado de System.Exception, en cuyo caso trata
una excepción específica. Por ejemplo:
catch (InvalidCastException e)
{
}
Es posible utilizar más de una cláusula catch específica en la misma instrucción try-catch. En este caso, el orden de las
cláusulas catch es importante, ya que las cláusulas catch se examinan por orden. Las excepciones más específicas se capturan
antes que las menos específicas.
Se puede utilizar una instrucción throw en el bloque catch para volver a producir la excepción, la cual ha sido capturada por la
instrucción catch. Por ejemplo:
catch (InvalidCastException e)
{
throw (e); // Rethrowing exception e
}
Si desea volver a producir la excepción que está siendo actualmente controlada por una cláusula catch sin parámetros, use la
instrucción throw sin argumentos. Por ejemplo:
catch
{
throw;
}
Dentro de un bloque try, inicialice sólo variables declaradas en su interior; en caso contrario, puede producirse una excepción
antes de que se complete la ejecución del bloque. Por ejemplo, en el siguiente ejemplo de código, la variable x se inicializa
dentro del bloque try. Al intentar utilizar esta variable fuera del bloque try en la instrucción Write(x), se generará el siguiente
error del compilador: Uso de variable local no asignada.
// try_catch_example.cs
using System;
class MainClass
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
En este ejemplo, se utilizan dos instrucciones catch. La excepción más específica, que aparece en primer lugar, se captura
primero.
// try_catch_ordering_catch_clauses.cs
using System;
class MainClass
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
Comentarios
En el ejemplo anterior, si empieza con la cláusula catch menos específica, aparecerá el mensaje de error: A previous catch
clause already catches all exceptions of this or a super type ('System.Exception')
No obstante, para capturar la excepción menos específica, debe reemplazar la instrucción throw por la siguiente:
throw new Exception();
// try-finally
using System;
public class MainClass
{
static void Main()
{
int i = 123;
string s = "Some string";
object o = s;
try
{
// Invalid conversion; o contains a string not an int
i = (int)o;
}
finally
{
Console.Write("i = {0}", i);
}
}
}
Comentarios
El ejemplo anterior hace que se produzca la excepción System.InvalidCastException.
A pesar de que se capturó una excepción, la instrucción de salida incluida en el bloque finally se ejecutará de todas formas, es
decir:
i = 123
// statements_checked.cs
using System;
class OverFlowTest
{
static short x = 32767; // Max short value
static short y = 32767;
unchecked
{
int val = 2147483647 * 2;
}
Como el cálculo anterior se realiza en un bloque unchecked, se pasa por alto que el resultado es demasiado grande para un
valor entero y se asigna a val el valor -2. De forma predeterminada, se habilita la detección del desbordamiento, que tiene el
mismo efecto que utilizar checked.
En el ejemplo anterior, si se hubiera omitido unchecked, ocurriría un error de compilación porque la expresión utiliza
constantes y el resultado se conoce en tiempo de compilación. La palabra clave unchecked también suprime la detección del
desbordamiento para expresiones no constantes, que de lo contrario producen una excepción OverflowException en tiempo de
ejecución.
La palabra clave unchecked también se puede utilizar como operador, de la manera siguiente:
Ejemplo
Este ejemplo muestra cómo utilizar la instrucción unchecked, utilizando unchecked con expresiones constantes.
// statements_unchecked.cs
using System;
class TestClass
{
const int x = 2147483647; // Max int
const int y = 2;
static void Main()
{
int z;
unchecked
{
z = x * y;
}
Console.WriteLine("Unchecked output value: {0}", z);
}
}
Resultados
Unchecked output value: -2
Se pueden inicializar varios punteros a la vez, siempre que sean del mismo tipo:
Después de ejecutar el código de la instrucción, se libera cualquier variable anteriormente fijada y queda sujeta al proceso de
recolección de elementos no utilizados. Por lo tanto, no se debe apuntar a esas variables desde fuera de la instrucción fixed.
Nota
Los punteros inicializados en instrucciones fixed no se pueden modificar.
En el modo no seguro (unsafe), se puede asignar memoria a la pila, donde no está sometida a recolección de elementos no
utilizados y, por lo tanto, no necesita fijarse. Para obtener más información, vea stackalloc (Referencia de C#).
Ejemplo
// statements_fixed.cs
// compile with: /unsafe
using System;
class Point
{
public int x, y;
}
class FixedTest
{
// Unsafe method: takes a pointer to an int.
unsafe static void SquarePtrParam (int* p)
{
*p *= *p;
}
Resultados
25 6
Para obtener más información, vea Sincronización de subprocesos (Guía de programación de C#).
Comentarios
La instrucción lock permite garantizar que un subproceso no va a entrar en una sección crucial de código mientras otro
subproceso ya se encuentre en ella. Si otro subproceso intenta entrar en un código bloqueado, esperará, o se bloqueará, hasta
que el objeto se libere.
En la sección Subprocesamiento (Guía de programación de C#) se describe el subprocesamiento.
La palabra clave lock llama a Enter al principio del bloque y a Exit al final del bloque.
En general evite bloquear un tipo public o instancias que estén fuera del control de su código. Las construcciones comunes
lock (this), lock (typeof (MyType)) y lock ("myLock") incumplen esta instrucción:
lock(“myLock”) se convierte en un problema puesto que cualquier otro código del proceso que utilice la misma cadena,
compartirá el mismo bloqueo.
El procedimiento recomendado es definir un objeto un objeto private para realizar el bloqueo o una variable de objeto
private static para proteger los datos comunes a todas las instancias.
Ejemplo
El siguiente ejemplo muestra un uso simple de subprocesos en C#.
// statements_lock.cs
using System;
using System.Threading;
class ThreadTest
{
public void RunMe()
{
Console.WriteLine("RunMe called");
}
static void Main()
{
ThreadTest b = new ThreadTest();
Thread t = new Thread(b.RunMe);
t.Start();
}
}
Resultados
RunMe called
El siguiente ejemplo utiliza subprocesos y lock. Con el uso de la instrucción lock, el bloque de instrucciones se convierte en
una sección crítica y balance nunca tomará un valor negativo.
// statements_lock2.cs
using System;
using System.Threading;
class Account
{
private Object thisLock = new Object();
int balance;
// Comment out the next line to see the effect of leaving out
// the lock keyword:
lock(thisLock)
{
if (balance >= amount)
{
Console.WriteLine("Balance before Withdrawal : " + balance);
Console.WriteLine("Amount to Withdraw : -" + amount);
balance = balance - amount;
Console.WriteLine("Balance after Withdrawal : " + balance);
return amount;
}
else
{
return 0; // transaction rejected
}
}
}
public void DoTransactions()
{
for (int i = 0; i < 100; i++)
{
Withdraw(r.Next(1, 100));
}
}
}
class Test
{
static void Main()
{
Thread[] threads = new Thread[10];
Account acc = new Account(1000);
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}
}
}
Resultados
1
2
3
1
a
test
10
11
12
class RefExample
{
static void Method(ref int i)
{
i = 44;
}
static void Main()
{
int val = 0;
Method(ref val);
// val is now 44
}
}
Para pasar un argumento a un parámetro ref, primero debe inicializarse. Esto es diferente de out, cuyo argumento no tiene
que inicializarse explícitamente antes de pasarlo. (Vea out (Referencia de C#).)
Aunque ref y out se tratan de manera diferente en tiempo de ejecución, se tratan de la misma manera en tiempo de
compilación. Por consiguiente no se pueden sobrecargar los métodos si un método toma un argumento ref y el otro toma un
argumento out. Por ejemplo, estos dos métodos son idénticos en lo referente a la compilación, por lo que este código no se
compilará:
class CS0663_Example
{
// compiler error CS0663: "cannot define overloaded
// methods that differ only on ref and out"
public void SampleMethod(ref int i) { }
public void SampleMethod(out int i) { }
}
Sin embargo, se puede realizar la sobrecarga si un método toma un argumento ref u out y el otro no utiliza ninguno de los
dos, de la manera siguiente:
class RefOutOverloadExample
{
public void SampleMethod(int i) { }
public void SampleMethod(ref int i) { }
}
Comentarios
Las propiedades no son variables y, por consiguiente, no se pueden pasar como parámetros ref.
Para obtener información sobre el paso de matrices, vea Pasar matrices mediante Ref y Out (Guía de programación de C#).
Ejemplo
Como se mostró anteriormente, el paso de tipos de valor por referencia es útil, pero ref también es útil para pasar los tipos de
referencia. Esto permite a los métodos llamados modificar el objeto al que se refiere la referencia porque la propia referencia
se pasa por referencia. El ejemplo siguiente muestra que cuando un tipo de referencia se pasa como parámetro ref, se puede
cambiar el objeto mismo.
class RefRefExample
{
static void Method(ref string s)
{
s = "changed";
}
static void Main()
{
string str = "original";
Method(ref str);
// str is now "changed"
}
}
class OutExample
{
static void Method(out int i)
{
i = 44;
}
static void Main()
{
int value;
Method(out value);
// value is now 44
}
}
Aunque las variables pasadas como argumentos out no tienen que inicializarse antes de pasarlas, el método de llamada es
necesario para asignar un valor antes de que el método devuelva un valor.
Las palabras clave ref y out se tratan de manera diferente en tiempo de ejecución, pero se tratan del mismo modo en tiempo
de compilación. Por consiguiente no se pueden sobrecargar los métodos si un método toma un argumento ref y el otro toma
un argumento out. Por ejemplo, estos dos métodos son idénticos en lo referente a la compilación, por lo que este código no se
compilará:
class CS0663_Example
{
// compiler error CS0663: "cannot define overloaded
// methods that differ only on ref and out"
public void SampleMethod(out int i) { }
public void SampleMethod(ref int i) { }
}
Sin embargo, se puede realizar la sobrecarga si un método toma un argumento ref u out y el otro no utiliza ninguno de los
dos, de la manera siguiente:
class RefOutOverloadExample
{
public void SampleMethod(int i) { }
public void SampleMethod(out int i) { }
}
Comentarios
Las propiedades no son variables y, por consiguiente, no se pueden pasar como parámetros out.
Para obtener información sobre el paso de matrices, vea Pasar matrices mediante Ref y Out (Guía de programación de C#).
Ejemplo
Declarar un método como out es útil cuando se desea que devuelva varios valores. Un método que utiliza un parámetro out
puede utilizar una variable como tipo de datos devuelto (vea return) pero también puede devolver uno o más objetos a un
método de llamada como parámetros out. Este ejemplo utiliza out para devolver tres variables con una única llamada al
método. Observe que el tercer argumento se asigna a null. Esto permite que los métodos devuelvan valores opcionalmente.
class OutReturnExample
{
static void Method(out int i, out string s1, out string s2)
{
i = 44;
s1 = "I've been returned";
s2 = null;
}
static void Main()
{
int value;
string str1, str2;
Method(out value, out str1, out str2);
// value is now 44
// str1 is now "I've been returned"
// str2 is (still) null;
}
}
namespace SampleNamespace
{
class SampleClass{}
interface SampleInterface{}
struct SampleStruct{}
enum SampleEnum{a,b}
delegate void SampleDelegate(int i);
namespace SampleNamespace.Nested
{
class SampleClass2{}
}
}
Comentarios
Dentro de un espacio de nombres, se pueden declarar uno o varios de los siguientes tipos:
otro espacio de nombres
clase (class)
interfaz
struct
enum
delegado (delegate)
Aunque declare explícitamente un espacio de nombres en un archivo de código fuente de C#, el compilador agrega un espacio
de nombres predeterminado. Este espacio de nombres sin denominación, a veces denominado espacio de nombres global,
está presente en todos los archivos. Cualquier identificador del espacio de nombres global puede utilizarse también en un
espacio de nombres declarado.
Los espacios de nombres disponen implícitamente de un acceso público que no puede modificarse. Para obtener una
descripción de los modificadores de acceso que se pueden asignar a los elementos de un espacio de nombres, consulte
Modificadores de acceso (Referencia de C#).
Un espacio de nombres se puede definir en dos o más declaraciones. Por ejemplo, en el siguiente ejemplo se definen dos
clases como parte del espacio de nombres MyCompany:
// cs_namespace_keyword.cs
// compile with: /target:library
namespace MyCompany.Proj1
{
class MyClass
{
}
}
namespace MyCompany.Proj1
{
class MyClass1
{
}
}
Ejemplo
El siguiente ejemplo muestra cómo realizar una llamada a un método estático en un espacio de nombres anidado.
// cs_namespace_keyword_2.cs
using System;
namespace SomeNameSpace
{
public class MyClass
{
static void Main()
{
Nested.NestedNameSpaceClass.SayHello();
}
}
// a nested namespace
namespace Nested
{
public class NestedNameSpaceClass
{
public static void SayHello()
{
Console.WriteLine("Hello");
}
}
}
}
Resultados
Hello
using System.Text;
La palabra clave using también se utiliza para crear instrucciones using que definen cuándo se eliminará un objeto. Vea
using (Instrucción, Referencia de C#) para obtener más información.
Comentarios
El ámbito de una directiva using se limita al archivo en el cual aparece.
Cree un alias using para que sea más fácil especificar un identificador de un espacio de nombres o tipo.
Cree una directiva using para utilizar los tipos de un espacio de nombres sin tener que especificar el espacio de nombres. Una
directiva using no proporciona acceso a ningún espacio de nombres anidado en el espacio de nombres especificado.
Los espacios de nombres se dividen en dos categorías: definidos por el usuario y definidos por el sistema. Los espacios de
nombres definidos por el usuario se definen en el código fuente. Para obtener una lista de los espacios de nombres definidos
por el sistema, vea Referencia de la biblioteca de clases de .NET Framework.
Para ver ejemplos sobre cómo hacer referencia a métodos en otros ensamblados, vea Crear y utilizar archivos DLL de C#.
Ejemplo 1
El siguiente ejemplo muestra cómo definir y utilizar un alias using para un espacio de nombres:
namespace PC
{
// Define an alias for the nested namespace.
using Project = PC.MyCompany.Project;
class A
{
void M()
{
// Use the alias
Project.MyClass mc = new Project.MyClass();
}
}
namespace MyCompany
{
namespace Project
{
public class MyClass{}
}
}
}
Ejemplo 2
El siguiente ejemplo muestra cómo definir una directiva using y un alias using para una clase:
// cs_using_directive2.cs
// Using directive.
using System;
// Using alias for a class.
using AliasToMyClass = NameSpace1.MyClass;
namespace NameSpace1
{
public class MyClass
{
public override string ToString()
{
return "You are in NameSpace1.MyClass";
}
}
}
namespace NameSpace2
{
class MyClass
{
}
}
namespace NameSpace3
{
// Using directive:
using NameSpace1;
// Using directive:
using NameSpace2;
class MainClass
{
static void Main()
{
AliasToMyClass somevar = new AliasToMyClass();
Console.WriteLine(somevar);
}
}
}
Resultados
You are in NameSpace1.MyClass
Comentarios
C#, a través de Common Language Runtime (CLR) de .NET Framework, libera automáticamente la memoria utilizada para
almacenar objetos que ya no son necesarios. La liberación de memoria no es determinista; se libera cuando CLR decide realizar
la recolección de elementos no utilizados. Sin embargo, normalmente es mejor liberar los recursos limitados, como
identificadores de archivos y conexiones de red, tan rápido como sea posible.
La instrucción using permite al programador especificar cuándo los objetos que utilizan recursos deben liberarlos. El objeto
proporcionado a la instrucción using debe implementar la interfaz IDisposable. Esta interfaz proporciona el método Dispose,
que debería liberar los recursos del objeto.
Es posible salir de una instrucción using cuando se alcanza el final de la instrucción using o cuando se produce una excepción
y el control abandona el bloque de la instrucción antes de llegar al final.
El objeto se puede declarar en la instrucción using, como se mostró anteriormente, a delante de ella, del modo siguiente:
Se pueden utilizar varios objetos con una instrucción using, pero se deben declarar dentro de la instrucción using, como
sigue:
Ejemplo
El ejemplo siguiente muestra cómo una clase definida por el usuario puede implementar su propio comportamiento Dispose.
Observe que su tipo debe heredarse de IDisposable.
using System;
class C : IDisposable
{
public void UseLimitedResource()
{
Console.WriteLine("Using limited resource...");
}
void IDisposable.Dispose()
{
Console.WriteLine("Disposing limited resource.");
}
}
class Program
{
static void Main()
{
using (C c = new C())
{
c.UseLimitedResource();
}
Console.WriteLine("Now outside using statement.");
Console.ReadLine();
}
}
Para hacer referencia a dos ensamblados con los mismos nombres completos del tipo, un alias se debe especificar en la línea
de comandos, del modo siguiente:
/r:GridV1=grid.dll
/r:GridV2=grid20.dll
Esto crea los alias externos GridV1 y GridV2. Para utilizar estos alias desde dentro de un programa, haga referencia a ellos
mediante la palabra clave extern. Por ejemplo:
extern alias GridV1;
extern alias GridV2;
Cada declaración de alias externo introduce un espacio de nombres de nivel de raíz adicional que crea un paralelo (pero no se
encuentra dentro de él) al espacio de nombres global. De este modo, es posible hacer referencia a los tipos de cada
ensamblado sin ambigüedades, mediante su nombre completo, arraigado en el alias de espacio de nombres adecuado
En el ejemplo anterior, GridV1::Grid sería el control de cuadrícula de grid.dll y GridV2::Grid sería el control de cuadrícula
de grid20.dll.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
25.4 Alias externos
Vea también
Referencia
Palabras clave de C#
Palabras clave del espacio de nombres (Referencia de C#)
Operador :: (Referencia de C#)
/reference (Importar metadatos) (Opciones del compilador de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
as (Referencia de C#)
Se utiliza para realizar conversiones entre tipos de referencia compatibles. Por ejemplo:
Comentarios
El operador as es similar a una operación de conversión de tipos; sin embargo, si la conversión no es posible, as devuelve null
en lugar de producir una excepción. Más formalmente, una expresión de la forma,
expression as type
equivale a,
class Class2
{
}
class MainClass
{
static void Main()
{
object[] objArray = new object[6];
objArray[0] = new Class1();
objArray[1] = new Class2();
objArray[2] = "hello";
objArray[3] = 123;
objArray[4] = 123.4;
objArray[5] = null;
for (int i = 0; i < objArray.Length; ++i)
{
string s = objArray[i] as string;
Console.Write("{0}:", i);
if (s != null)
{
Console.WriteLine("'" + s + "'");
}
else
{
Console.WriteLine("not a string");
}
}
}
}
Resultados
0:not a string
1:not a string
2:'hello'
3:not a string
4:not a string
5:not a string
is (Referencia de C#)
Comprueba si un objeto es compatible con un tipo determinado. Por ejemplo, se puede determinar si un objeto es compatible
con el tipo string de la forma siguiente:
if (obj is string)
{
}
Comentarios
Una expresión is se evalúa como true si la expresión proporcionada no es NULL y el objeto proporcionado se puede convertir
al tipo proporcionado sin producir una excepción. Para obtener más información, vea 7.6.6 Cast expressions.
La palabra clave is tiene como resultado una advertencia en tiempo de compilación si se sabe que la expresión siempre será
true o siempre será false, pero normalmente evalúa la compatibilidad de tipos en tiempo de ejecución.
El operador is no se puede sobrecargar.
Observe que el operador is solamente tiene en cuenta las conversiones de referencia, las conversiones boxing y las
conversiones unboxing. No se tienen en cuenta otras conversiones, tales como las conversiones definidas por el usuario.
Ejemplo
// cs_keyword_is.cs
// The is operator.
using System;
class Class1
{
}
class Class2
{
}
class IsTest
{
static void Test(object o)
{
Class1 a;
Class2 b;
if (o is Class1)
{
Console.WriteLine("o is Class1");
a = (Class1)o;
// Do something with "a."
}
else if (o is Class2)
{
Console.WriteLine("o is Class2");
b = (Class2)o;
// Do something with "b."
}
else
{
Console.WriteLine("o is neither Class1 nor Class2.");
}
}
static void Main()
{
Class1 c1 = new Class1();
Class2 c2 = new Class2();
Test(c1);
Test(c2);
Test("a string");
}
}
Resultados
o is Class1
o is Class2
o is neither Class1 nor Class2.
El operador new también se utiliza para invocar el constructor predeterminado de los tipos de valor. Por ejemplo:
En la instrucción anterior se inicializa i con el valor 0, que es el predeterminado para el tipo int. Esa instrucción tiene el mismo
efecto que:
int i = 0;
Para obtener una lista completa de valores predeterminados, vea Tabla de valores predeterminados.
Recuerde que es un error declarar un constructor predeterminado para un tipo struct, ya que todos los tipos de valores poseen
implícitamente un constructor público predeterminado. Es posible declarar constructores parametrizados en un tipo struct
para establecer sus valores iniciales, pero sólo es necesario si se requieren valores distintos del predeterminado.
Los objetos de tipo valor, tales como las estructuras, se crean en la pila, mientras que los objetos de tipo referencia, tales como
las clases, se crean en el montón. Ambos tipos de objetos se destruyen automáticamente, pero los objetos basados en tipos de
valor se destruyen cuando salen del ámbito, mientras que los objetos basados en tipos de referencia se destruyen en un
momento no especificado después de quitar la última referencia a ellos. En los tipos de referencia que consumen ciertos
recursos, como grandes cantidades de memoria, identificadores de archivo o conexiones de red, a veces es conveniente
emplear la finalización determinista para asegurarse de que el objeto se destruirá lo antes posible. Para obtener más
información, vea using (Instrucción, Referencia de C#).
El operador new no se puede sobrecargar.
Si el operador new no puede asignar memoria, producirá la excepción OutOfMemoryException.
Ejemplo
En el siguiente ejemplo, se crean e inicializan, mediante el operador new, un objeto struct y un objeto class y, a continuación,
se les asignan valores. Se muestran los valores predeterminados y asignados.
// cs_operator_new.cs
// The new operator.
using System;
struct SampleStruct
{
public int x;
public int y;
public SampleStruct(int x, int y)
{
this.x = x;
this.y = y;
}
}
class SampleClass
{
public string name;
public int id;
public SampleClass() {}
class MainClass
{
static void Main()
{
// Create objects using default constructors:
SampleStruct Location1 = new SampleStruct();
SampleClass Employee1 = new SampleClass();
// Display values:
Console.WriteLine("Default values:");
Console.WriteLine(" Struct members: {0}, {1}",
Location1.x, Location1.y);
Console.WriteLine(" Class members: {0}, {1}",
Employee1.name, Employee1.id);
// Create objects using parameterized constructors:
SampleStruct Location2 = new SampleStruct(10, 20);
SampleClass Employee2 = new SampleClass(1234, "John Martin Smith");
// Display values:
Console.WriteLine("Assigned values:");
Console.WriteLine(" Struct members: {0}, {1}",
Location2.x, Location2.y);
Console.WriteLine(" Class members: {0}, {1}",
Employee2.name, Employee2.id);
}
}
Resultados
Default values:
Struct members: 0, 0
Class members: , 0
Assigned values:
Struct members: 10, 20
Class members: John Martin Smith, 1234
Comentarios
Observe en el ejemplo que el valor predeterminado de una cadena es null. Por lo tanto, no se muestra.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
7.5.10 El operador new
Vea también
Referencia
Palabras clave de C#
Palabras clave de operadores (Referencia de C#)
new (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
En este ejemplo, DerivedC.Invoke oculta BaseC.Invoke. El campo x no se ve afectado porque no lo oculta un nombre similar.
La ocultación de nombres por medio de la herencia toma una de las siguientes formas:
Constante, campo, propiedad o tipo introducido en una clase o estructura que oculta todos los miembros de la clase base
con el mismo nombre.
Método introducido en una clase o estructura que oculta propiedades, campos y tipos, con el mismo nombre, en la clase
base. También oculta todos los métodos de la clase base con la misma firma.
Indizador introducido en una clase o estructura que oculta todos los indizadores de la clase base con la misma firma.
Es un error utilizar new y override en el mismo miembro, ya que los dos modificadores tienen significados mutuamente
exclusivos. Al utilizar new, se crea un nuevo miembro con el mismo nombre y el miembro original queda oculto, mientras que
override amplía la implementación de un miembro heredado.
Si se utiliza el modificador new en una declaración que no oculta un miembro heredado, se genera una advertencia.
Ejemplo
En este ejemplo, una clase base, BaseC, y una clase derivada, DerivedC, utilizan el mismo nombre de campo x, lo que produce la
ocultación del valor del campo heredado. El ejemplo muestra el uso del modificador new. También muestra cómo obtener
acceso a los miembros ocultos de la clase base mediante sus nombres completos.
// cs_modifier_new.cs
// The new modifier.
using System;
public class BaseC
{
public static int x = 55;
public static int y = 22;
}
public class DerivedC : BaseC
{
// Hide field 'x'
new public static int x = 100;
Resultados
100
55
22
En este ejemplo, una clase anidada oculta una clase con el mismo nombre en la clase base. El ejemplo muestra el uso del
modificador new para eliminar el mensaje de advertencia, así como el acceso a los miembros ocultos de la clase mediante sus
nombres completos.
// cs_modifer_new_nested.cs
// Using the new modifier with nested types.
using System;
public class BaseC
{
public class NestedC
{
public int x = 200;
public int y;
}
}
Resultados
100
200
Comentarios
Si quita el modificador new, el programa seguirá compilándose y ejecutándose, pero aparecerá la siguiente advertencia:
The keyword new is required on 'MyDerivedC.x' because it hides inherited member 'MyBaseC.x'
.
También puede utilizar el modificador new para modificar un tipo anidado si éste está ocultando otro tipo, como se muestra
en el ejemplo siguiente.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
10.2.2 El modificador new
Vea también
Referencia
Palabras clave de C#
Palabras clave de operadores (Referencia de C#)
Modificadores (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Cuando se utiliza la restricción new() con otras restricciones, se debe especificar en último lugar:
using System;
public class ItemFactory<T>
where T : IComparable, new()
{
}
Para obtener más información, vea Restricciones de tipos de parámetros (Guía de programación de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
19.1.4 Restricciones
Vea también
Referencia
Palabras clave de C#
Palabras clave de operadores (Referencia de C#)
System.Collections.Generic
Conceptos
Guía de programación de C#
Genéricos (Guía de programación de C#)
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Comentarios
El operador sizeof sólo se puede aplicar a tipos de valor, no a tipos de referencia.
Nota
A partir de la versión 2.0 de C# en adelante, la aplicación de sizeof a los tipos predefinidos, ya no requiere la utilización del
modo unsafe.
El operador sizeof no puede sobrecargarse. Los valores devueltos por el operador sizeof son del tipo int. La tabla siguiente
muestra los valores constantes que representan los tamaños de ciertos tipos predefinidos.
Expresión Resultado
sizeof(sbyte) 1
sizeof(byte) 1
sizeof(short) 2
sizeof(ushort) 2
sizeof(int) 4
sizeof(uint) 4
sizeof(long) 8
sizeof(ulong) 8
sizeof(char) 2 (Unicode)
sizeof(float) 4
sizeof(double) 8
sizeof(bool) 1
Para todos los otros tipos, entre ellos las estructuras, el operador sizeof se puede utilizar sólo en bloques de código no
seguros. Aunque se puede utilizar el método SizeOf, el valor devuelto por este método no siempre es igual al valor devuelto
por sizeof. Marshal.SizeOf devuelve el tamaño después de calcular las referencias del tipo, mientras que sizeof devuelve el
tamaño cuando éste ha sido asignado por Common Language Runtime, incluido cualquier valor de relleno.
Ejemplo
// cs_operator_sizeof.cs
// compile with: /unsafe
using System;
class MainClass
{
unsafe static void Main()
{
Console.WriteLine("The size of short is {0}.", sizeof(short));
Console.WriteLine("The size of int is {0}.", sizeof(int));
Console.WriteLine("The size of long is {0}.", sizeof(long));
}
}
Resultados
The size of short is 2.
The size of int is 4.
The size of long is 8.
Comentarios
Para obtener el tipo de una expresión en tiempo de ejecución, puede utilizar el método GetType de .NET Framework de la
manera siguiente.
int i = 0;
System.Type type = i.GetType();
El operador typeof también se puede utilizar en tipos de genéricos abiertos. Los tipos con más de un parámetro de tipo deben
tener el número adecuado de comas en la especificación. El operador typeof no se puede sobrecargar.
Ejemplo
// cs_operator_typeof.cs
using System;
using System.Reflection;
Console.WriteLine("Methods:");
MethodInfo[] methodInfo = t.GetMethods();
Console.WriteLine("Members:");
MemberInfo[] memberInfo = t.GetMembers();
Resultados
Methods:
Void SampleMethod()
System.Type GetType()
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
Members:
Void SampleMethod()
System.Type GetType()
System.String ToString()
Boolean Equals(System.Object)
Int32 GetHashCode()
Void .ctor()
Int32 sampleMember
En este ejemplo se utiliza el método GetType para determinar el tipo utilizado para contener el resultado de un cálculo
numérico. Esto depende de los requisitos de almacenamiento del número resultante.
// cs_operator_typeof2.cs
using System;
class GetTypeTest
{
static void Main()
{
int radius = 3;
Console.WriteLine("Area = {0}", radius * radius * Math.PI);
Console.WriteLine("The type is {0}",
(radius * radius * Math.PI).GetType()
);
}
}
Resultados
Area = 28.2743338823081
The type is System.Double
Resultados
yes
Resultados
no
Comentarios
En el ejemplo anterior, un bloque de memoria de tamaño suficiente para contener 100 elementos de tipo int se reserva en la
pila y no en el montón; la dirección del bloque se almacena en el puntero fib. Esta memoria no está sometida a reciclaje y, por
lo tanto, no necesita fijarse (por medio de fixed). El período de duración del bloque de memoria se limita al período de
duración del método en el que está definido (no hay forma de liberar la memoria antes de la devolución del método).
El operador stackalloc sólo es válido en inicializadores de variables locales.
Dado que intervienen los tipos de puntero, stackalloc requiere el contexto unsafe. Vea
Código no seguro y punteros (Guía de programación de C#).
stackalloc es similar a _alloca de la biblioteca en tiempo de ejecución de C.
Seguridad
El código no seguro es inherentemente menos seguro que las alternativas seguras. Sin embargo, el uso de stackalloc habilita
automáticamente las características de detección de saturación del búfer en Common Language Runtime (CLR). Si se detecta
una saturación del búfer, el proceso se finaliza tan rápidamente como sea posible para reducir la oportunidad de que se
ejecute código malintencionado.
Ejemplo
// cs_keyword_stackalloc.cs
// compile with: /unsafe
using System;
class Test
{
static unsafe void Main()
{
int* fib = stackalloc int[100];
int* p = fib;
*p++ = *p++ = 1;
for (int i = 2; i < 100; ++i, ++p)
{
*p = p[-1] + p[-2];
}
for (int i = 0; i < 10; ++i)
{
Console.WriteLine(fib[i]);
}
}
}
Resultados
1
1
2
3
5
8
13
21
34
55
Comentarios
El operador de conversión convierte un tipo de origen en un tipo de destino. El tipo de origen proporciona el operador de
conversión. A diferencia de la conversión implícita, los operadores de conversión explícita deben invocarse mediante una
conversión de tipo (cast). Si una operación de conversión puede producir excepciones o pérdida de información, debe
marcarse como explicit. De esta forma, se evita que el compilador realice la conversión automáticamente y se produzcan
posibles consecuencias no deseadas.
Si no se utiliza esta conversión explícita, se produce el error de compilación Error del compilador CS0266.
Para obtener más información, vea Utilizar operadores de conversión (Guía de programación de C#).
Ejemplo
El ejemplo siguiente proporciona una clase Fahrenheit y una clase Celsius, cada una de las cuales proporciona un operador
de conversión explícito a la otra clase.
// cs_keyword_explicit_temp.cs
using System;
class Celsius
{
public Celsius(float temp)
{
degrees = temp;
}
public static explicit operator Fahrenheit(Celsius c)
{
return new Fahrenheit((9.0f / 5.0f) * c.degrees + 32);
}
public float Degrees
{
get { return degrees; }
}
private float degrees;
}
class Fahrenheit
{
public Fahrenheit(float temp)
{
degrees = temp;
}
public static explicit operator Celsius(Fahrenheit f)
{
return new Celsius((5.0f / 9.0f) * (f.degrees - 32));
}
public float Degrees
{
get { return degrees; }
}
private float degrees;
}
class MainClass
{
static void Main()
{
Fahrenheit f = new Fahrenheit(100.0f);
Console.Write("{0} fahrenheit", f.Degrees);
Celsius c = (Celsius)f;
Console.Write(" = {0} celsius", c.Degrees);
Fahrenheit f2 = (Fahrenheit)c;
Console.WriteLine(" = {0} fahrenheit", f2.Degrees);
}
}
Resultados
100 fahrenheit = 37.77778 celsius = 100 fahrenheit
El siguiente ejemplo define una estructura, Digit, que representa un único dígito decimal. Se define un operador para
conversiones de byte a Digit, pero como no todos los bytes se pueden convertir en Digit, la conversión es explícita.
// cs_keyword_explicit_2.cs
using System;
struct Digit
{
byte value;
public Digit(byte value)
{
if (value > 9)
{
throw new ArgumentException();
}
this.value = value;
}
class MainClass
{
static void Main()
{
try
{
byte b = 3;
Digit d = (Digit)b; // explicit conversion
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
}
}
Resultados
conversion occurred
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
6.2 Conversiones explícitas
Vea también
Tareas
Cómo: Implementar conversiones entre estructuras definidas por el usuario (Guía de programación de C#)
Referencia
Palabras clave de C#
implicit (Referencia de C#)
operator (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
class Digit
{
public Digit(double d) { val = d; }
public double val;
// ...other members
Comentarios
Si se eliminan las conversiones de tipo explícitas innecesarias y se utilizan conversiones implícitas, la legibilidad del código
mejora. Sin embargo, como las conversiones implícitas no requieren que los programadores conviertan explícitamente un tipo
en otro, deben tomarse las medidas adecuadas para impedir que se produzcan resultados imprevistos. En general, los
operadores de conversión implícita nunca deberían producir excepciones ni pérdida de información, de modo que puedan
utilizarse de forma segura sin intervención del programador. Si un operador de conversión no cumple esos criterios, debería
marcarse como explicit. Para obtener más información, vea Utilizar operadores de conversión (Guía de programación de C#).
// cs_keyword_operator.cs
using System;
class Fraction
{
int num, den;
public Fraction(int num, int den)
{
this.num = num;
this.den = den;
}
// overload operator +
public static Fraction operator +(Fraction a, Fraction b)
{
return new Fraction(a.num * b.den + b.num * a.den,
a.den * b.den);
}
// overload operator *
public static Fraction operator *(Fraction a, Fraction b)
{
return new Fraction(a.num * b.num, a.den * b.den);
}
class Test
{
static void Main()
{
Fraction a = new Fraction(1, 2);
Fraction b = new Fraction(3, 7);
Fraction c = new Fraction(2, 3);
Console.WriteLine((double)(a * b + c));
}
}
Resultados
0.880952380952381
// keywords_base.cs
// Accessing base class members
using System;
public class Person
{
protected string ssn = "444-55-6666";
protected string name = "John L. Malgraine";
Este ejemplo muestra cómo especificar el constructor de la clase base al que se realiza la llamada cuando se crean instancias
de una clase derivada.
// keywords_base2.cs
using System;
public class BaseClass
{
int num;
public BaseClass()
{
Console.WriteLine("in BaseClass()");
}
public BaseClass(int i)
{
num = i;
Console.WriteLine("in BaseClass(int i)");
}
Resultados
Name: John L. Malgraine
SSN: 444-55-6666
Employee ID: ABC567EFG
CalcTax(this);
Debido a que las funciones miembro estáticas existen en el nivel de clase y no como parte de un objeto, no tienen un puntero
this. Es un error hacer referencia a this en un método estático.
Ejemplo
En este ejemplo, this se utiliza para calificar los miembros de la clase Employee, name y alias, que presentan ambigüedad con
nombres similares. También se utiliza para pasar un objeto al método CalcTax, el cual pertenece a otra clase.
// keywords_this.cs
// this example
using System;
class Employee
{
private string name;
private string alias;
private decimal salary = 3000.00m;
// Constructor:
public Employee(string name, string alias)
{
// Use this to qualify the fields, name and alias:
this.name = name;
this.alias = alias;
}
// Printing method:
public void printEmployee()
{
Console.WriteLine("Name: {0}\nAlias: {1}", name, alias);
// Passing the object to the CalcTax method by using this:
Console.WriteLine("Taxes: {0:C}", Tax.CalcTax(this));
}
class MainClass
{
static void Main()
{
// Create objects:
Employee E1 = new Employee("John M. Trainer", "jtrainer");
// Display results:
E1.printEmployee();
}
}
Resultados
Name: John M. Trainer
Alias: jtrainer
Taxes: $240.00
class TimePeriod
{
private double _seconds;
public double Seconds
{
get { return _seconds; }
set { _seconds = value; }
}
}
namespace PC
{
partial class A { }
}
En Archivo2.cs:
namespace PC
{
partial class A { }
}
Comentarios
Dividir una clase, estructura o tipo de interfaz en varios archivos puede ser útil al trabajar con proyectos grandes o código
generado automáticamente como el que proporciona el Diseñador de Windows Forms. Para obtener más información, vea
Definiciones de clase parciales (Guía de programación de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
19.4 Tipos parciales
23 tipos parciales
Vea también
Referencia
Modificadores (Referencia de C#)
Introducción a los genéricos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
class TimePeriod
{
private double _seconds;
public double Seconds
{
get { return _seconds; }
set { _seconds = value; }
}
}
Además de las restricciones de interfaz, una cláusula where puede incluir una restricción de clase base, que establece que un
tipo debe tener la clase especificada como clase base (o ser la propia clase) para poder utilizarlo como argumento de tipo para
ese tipo genérico. Si se utiliza una restricción semejante, debe aparecer antes que cualquier otra restricción sobre ese
parámetro de tipo.
// cs_where.cs
// compile with: /target:library
using System;
La cláusula where también puede incluir una restricción de constructor. Es posible crear una instancia de un parámetro de tipo
utilizando el operador new; sin embargo, para ello el parámetro de tipo debe estar restringido por la restricción de constructor,
new(). La restricción new() permite que el compilador sepa que cualquier argumento de tipo que se proporcione debe tener
un constructor sin parámetros accesible, o predeterminado. Por ejemplo:
// cs_where_2.cs
// compile with: /target:library
using System;
public class MyGenericClass <T> where T: IComparable, new()
{
// The following line is not possible without new() constraint:
T item = new T();
}
// cs_where_3.cs
// compile with: /target:library
using System;
using System.Collections;
interface MyI
{
}
class Dictionary<TKey,TVal>
where TKey: IComparable, IEnumerable
where TVal: MyI
{
public void Add(TKey key, TVal val)
{
}
}
También puede adjuntar restricciones a parámetros de tipo de métodos genéricos, como el siguiente:
public bool MyMethod<T>(T t) where T : IMyInterface { }
Observe que la sintaxis para describir las restricciones de parámetros de tipo en delegados es igual que la sintaxis de métodos.
Para obtener información sobre delegados genéricos, vea Delegados genéricos (Guía de programación de C#).
Para obtener información detallada sobre la sintaxis y el uso de restricciones, vea
Restricciones de tipos de parámetros (Guía de programación de C#).
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
19.1.4 Restricciones
Vea también
Referencia
Introducción a los genéricos (Guía de programación de C#)
Restricción new (Referencia de C#)
Restricciones de tipos de parámetros (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Comentarios
La expresión se evalúa y se devuelve como valor al objeto enumerador; expression se debe poder convertir implícitamente al
tipo yield del iterador.
La instrucción yield sólo puede aparecer dentro de un bloque iterator que podría utilizarse como cuerpo de un método,
operador o descriptor de acceso. El cuerpo de dicho método, operador o descriptor de acceso se controla mediante las
siguientes restricciones:
No se permiten bloques unsafe.
Los parámetros del método, operador o descriptor de acceso no pueden ser ref ni out.
Una instrucción yield no puede aparecer en un método anónimo. Para obtener más información, vea
Métodos anónimos (Guía de programación de C#).
Cuando se utiliza con expression, una instrucción yield return no puede aparecer en un bloque catch ni en un bloque try que
tengan una o más cláusulas catch. Para obtener más información, vea
Instrucciones para el control de excepciones (Referencia de C#).
Ejemplo
En el siguiente ejemplo, la instrucción yield se utiliza dentro de un bloque de iteradores, que es el método Power(int number,
int power). Cuando se invoca al método Power, este devuelve un objeto enumerable que contiene las potencias de un
número. Observe que el tipo de valor devuelto del método Power es IEnumerable, un tipo de interfaz de iteradores.
// yield-example.cs
using System;
using System.Collections;
public class List
{
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
Resultados
2 4 8 16 32 64 128 256
Operadores de C#
C# proporciona un amplio conjunto de operadores, que son símbolos que especifican las operaciones que se deben realizar en
una expresión. Generalmente se permiten en las enumeraciones las operaciones de tipos integrales como ==, !=, <, >, <=, >=,
binary +, binary -, ^, &, |, ~, ++, -- y sizeof(). Además, el usuario puede sobrecargar muchos de los operadores, es decir,
cambiar su significado al aplicarlos a un tipo definido por el usuario.
En la tabla siguiente se muestran los operadores de C# agrupados por orden de prioridad. Los operadores dentro de cada de
grupo tienen la misma prioridad.
Categorías Operadores
Principal x.y
f(x)
a[x]
x++
x--
new
typeof
checked
unchecked
->
Unario +
-
!
~
++x
--x
(T)x
true
false
&
sizeof
Multiplicativo *
/
%
Sumatorio +
-
Desplazamiento <<
>>
Comprobación de tipos y relacionales <
>
<=
>=
is
as
Igualdad ==
!=
XOR lógico ^
OR lógico |
OR condicional ||
Condicional ?:
Asignación =
+=
-=
*=
/=
%=
&=
|=
^=
<<=
>>=
??
Desbordamiento aritmético
Los operadores aritméticos (+, -, *, /) pueden producir resultados fuera del intervalo de valores posibles para el tipo numérico
implicado. Aunque para encontrar información detallada, debe consultar la sección acerca del operador específico; en general,
podemos decir:
El desbordamiento aritmético de enteros produce una excepción de desbordamiento (OverflowException) o bien elimina
los bits más significativos del resultado. La división de enteros por cero siempre produce una excepción
DivideByZeroException.
El desbordamiento aritmético o la división por cero en punto flotante no producen una excepción, ya que los tipos de
punto flotante se basan en el estándar IEEE 754, que proporciona una representación para los valores infinito y NaN (Not
a Number, no es un número).
El desbordamiento aritmético de valores de tipo decimal siempre produce una excepción OverflowException. La
división de decimales por cero siempre produce una excepción DivideByZeroException.
Cuando se produce un desbordamiento de enteros, lo que ocurre depende del contexto de la ejecución, el cual puede ser
checked o unchecked. En un contexto checked (comprobado), se produce una excepción OverflowException. En un contexto
unchecked (no comprobado), los bits más significativos del resultado no se tienen en cuenta y la ejecución continúa. De esta
forma, C# permite elegir entre atender o desatender el desbordamiento.
Además de los operadores aritméticos, las conversiones entre tipos integrales también pueden producir desbordamiento; por
ejemplo, al convertir un tipo long en un tipo int, y están sometidas al tipo de ejecución checked o unchecked. Sin embargo, los
operadores bit a bit y los operadores de desplazamiento nunca producen desbordamiento.
Vea también
Tareas
Ejemplo Operator Overloading
Referencia
Operadores sobrecargables (Guía de programación de C#)
Palabras clave de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Visual C#
Referencia del lenguaje C#
Para obtener acceso a un elemento de la matriz, el índice del elemento deseado se encierra entre corchetes:
fib[0] = fib[1] = 1;
for( int i=2; i<100; ++i ) fib[i] = fib[i-1] + fib[i-2];
Se produce una excepción si el índice de la matriz está fuera del intervalo declarado.
El operador de indización de la matriz no se puede sobrecargar; no obstante, los tipos pueden definir indizadores y
propiedades que aceptan uno o varios parámetros. Los parámetros de un indizador van entre corchetes, como los índices de
una matriz, pero se pueden declarar de cualquier tipo, a diferencia de los índices de una matriz, que sólo pueden ser de tipo
integral.
Por ejemplo, .NET Framework define un tipo Hashtable que asocia claves y valores de tipo arbitrario:
Los corchetes también se utilizan para especificar Atributos (Guía de programación de C#):
[attribute(AllowMultiple=true)]
public class Attr
{
}
No obstante, tenga en cuenta que no se realiza una comprobación de los límites del índice.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.6.6.5 Operadores
7.2 Operadores
Vea también
Referencia
Operadores de C#
Indizadores (Guía de programación de C#)
unsafe (Referencia de C#)
fixed (Instrucción, Referencia de C#)
Conceptos
Guía de programación de C#
Matrices (Guía de programación de C#)
Otros recursos
Referencia de C#
Referencia del lenguaje C#
double x = 1234.7;
int a;
a = (int)x; // cast double to int
Comentarios
Una conversión de tipos invoca explícitamente el operador de conversión de un tipo a otro; se producirá un error en la
conversión si no se ha definido ese operador. Para definir un operador de conversión, vea explicit (Referencia de C#) e
implicit (Referencia de C#).
El operador () no se puede sobrecargar.
Para obtener más información, vea Conversión (Guía de programación de C#).
Una expresión de conversión de tipos puede llevar a una sintaxis ambigua. Por ejemplo, la expresión (x)–y puede interpretarse
como una expresión de conversión de tipos (una conversión del tipo –y al tipo x) o como una expresión de suma combinada
con una expresión entre paréntesis, que calcula el valor de x – y.
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
1.6.6.5 Operadores
7.2 Operadores
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Comentarios
Por ejemplo, considere la siguiente clase:
class Simple
{
public int a;
public void b()
{
}
}
Simple s = new Simple();
La variable s tiene dos miembros, a y b; para tener acceso a ellos, use el operador de punto:
El punto también se utiliza para formar nombres completos, que son nombres que especifican el espacio de nombres o la
interfaz, por ejemplo, a la que pertenecen.
La directiva using hace que la calificación de nombres sea opcional en algunos casos:
using System;
// ...
System.Console.WriteLine("hello");
Console.WriteLine("hello"); // same thing
using System;
// A namespace containing another Console class:
using OtherSystem;
// ...
// Must qualify Console:
System.Console.WriteLine( "hello" );
global::System.Console.WriteLine("Hello World");
Comentarios
El calificador de alias de espacio de nombres puede ser global. Éste invoca una búsqueda del espacio de nombres global, en
lugar de un espacio de nombres con alias.
Para obtener más información
Para obtener un ejemplo de uso del operador ::, vea la siguiente sección:
Cómo: Utilizar el calificador de alias del espacio de nombres (Guía de programación de C#)
Especificación del lenguaje C#
Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.
20.9.5 Nombres sencillos
25.3 Calificadores de alias del espacio de nombres
Vea también
Referencia
Operadores de C#
Palabras clave del espacio de nombres (Referencia de C#)
Operador . (Referencia de C#)
alias externo (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
5
10
5.5
55
55
Resultados
-5
4
4.5
Resultados
10
-0.1
-0.10
// cs_operator_ptr.cs
// compile with: /unsafe
public class MainClass
{
unsafe static void Main()
{
int i = 5;
int* j = &i;
System.Console.WriteLine(*j);
}
}
Resultados
5
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Código no seguro y punteros (Guía de programación de C#)
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
-2
-2.5
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
1
-1
0.6
0.6
-1.2
Comentarios
Observe los errores de redondeo que presenta el tipo double.
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
int i = 0;
if (false & ++i == 1)
{
// i is incremented, but the conditional
// expression evaluates to false, so
// this block does not execute.
}
Los tipos definidos por el usuario pueden sobrecargar el operador binario & (vea operator (Referencia de C#)). Las
operaciones en tipos integrales se suelen permitir en enumeraciones. Cuando se sobrecarga un operador binario, el operador
de asignación correspondiente, si existe, también se sobrecarga de modo implícito.
Ejemplo
// cs_operator_ampersand.cs
using System;
class MainClass
{
static void Main()
{
Console.WriteLine(true & false); // logical and
Console.WriteLine(true & true); // logical and
Console.WriteLine("0x{0:x}", 0xf8 & 0x3f); // bitwise and
}
}
Resultados
False
True
0x38
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
True
False
0xff
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
True
False
0xc7
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
False
True
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
~0x00000000 = 0xffffffff
~0x00000111 = 0xfffffeee
~0x000fffff = 0xfff00000
~0x00008888 = 0xffff7777
~0x22000022 = 0xddffffdd
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
i is 5, x is 5
boxed value = 5, type is System.Int32
unboxed: 5
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
True
False
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
True
False
Vea también
Referencia
Operadores de C#
explicit (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Comentarios
Si la condición es true, se evalúa la primera expresión y se convierte en el resultado; si es false, se evalúa la segunda expresión
y se convierte en el resultado. Sólo se evalúa una de las dos expresiones.
Los cálculos que, en cualquier otro caso, podrían requerir un bloque de decisión if-else se pueden expresar más concisa y
elegantemente mediante el operador condicional. Por ejemplo, para evitar una división por cero en el cálculo de la función sin,
podría escribirse
El operador condicional es asociativo por la derecha, de modo que una expresión de la forma:
a ? b : c ? d : e
se evalúa como
a ? b : (c ? d : e)
y no como
(a ? b : c) ? d : e
Resultados
0.993346653975306
0.998334166468282
1
Vea también
Referencia
Operadores de C#
if-else (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
2.5
1.5
2.5
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
0.5
1.5
0.5
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x && y
x & y
excepto que si x es false, y no se evalúa (ya que el resultado de la operación AND será false independientemente del valor de
y ). Esto se conoce como evaluación "cortocircuitada".
El operador AND condicional no se puede sobrecargar, pero las sobrecargas de los operadores lógicos normales y los
operadores true y false también se consideran, con ciertas restricciones, sobrecargas de los operadores lógicos condicionales.
Ejemplo
En el siguiente ejemplo, observe que la expresión que utiliza && sólo evalúa el primer operando.
// cs_operator_logical_and.cs
using System;
class MainClass
{
static bool Method1()
{
Console.WriteLine("Method1 called");
return false;
}
Resultados
regular AND:
Method1 called
Method2 called
result is False
short-circuit AND:
Method1 called
result is False
x || y
x | y
salvo que si x es true, y no se evalúa (ya que el resultado de la operación OR será true independientemente del valor de y).
Esto se conoce como evaluación "cortocircuitada".
El operador OR condicional no se puede sobrecargar, pero las sobrecargas de los operadores lógicos normales y los
operadores true y false se consideran también, con ciertas restricciones, sobrecargas de los operadores lógicos condicionales.
Ejemplo
En el siguiente ejemplo, observe que la expresión que utiliza || sólo evalúa el primer operando.
// cs_operator_short_circuit_OR.cs
using System;
class MainClass
{
static bool Method1()
{
Console.WriteLine("Method1 called");
return true;
}
Resultados
regular OR:
Method1 called
Method2 called
result is True
short-circuit OR:
Method1 called
result is True
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
0x2
0x2
0x200000000
Comentarios
Observe que i<<1 e i<<33 dan el mismo resultado, ya que 1 y 33 tienen los mismos cinco bits de orden inferior.
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
-125
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
True
False
True
False
True
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
False
True
False
False
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
True
True
Vea también
Referencia
Operadores de C#
explicit (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
True
True
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x += y
equivale a
x = x + y
salvo que x sólo se evalúa una vez. El significado del operador + depende de los tipos de x e y (suma para operandos
numéricos, concatenación para operandos de tipo cadena, etc.).
El operador += no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador + (vea operator (Referencia de C#)).
El operador + = se utiliza también para especificar un método al que se llama en respuesta a un evento; estos métodos se
denominan controladores de eventos. Como los controladores de eventos se encapsulan dentro de un tipo de delegado, el uso
del operador + = en este contexto se denomina concatenación de delegados. Para obtener más información, vea
event (Referencia de C#) y Delegados (Guía de programación de C#).
Ejemplo
// cs_operator_addition_assignment.cs
using System;
class MainClass
{
static void Main()
{
//addition
int a = 5;
a += 6;
Console.WriteLine(a);
//string concatenation
string s = "Micro";
s += "soft";
Console.WriteLine(s);
}
}
Resultados
11
Microsoft
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x -= y
equivale a
x = x - y
salvo que x sólo se evalúa una vez. El significado del operador - depende de los tipos de x e y (resta para operandos
numéricos, eliminación delegada para operandos delegados, etc.).
El operador -= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador - (vea operador).
Ejemplo
// cs_operator_subtraction_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 5;
a -= 6;
Console.WriteLine(a);
}
}
Resultado
-1
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x *= y
equivale a
x = x * y
salvo que x sólo se evalúa una vez. El operador * está predefinido con la multiplicación para tipos numéricos.
El operador *= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador * (vea operador).
Ejemplo
// cs_operator_multiplication_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 5;
a *= 6;
Console.WriteLine(a);
}
}
Resultados
30
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x /= y
equivale a
x = x / y
salvo que x sólo se evalúa una vez. El operador / está predefinido con la división para tipos numéricos.
El operador /= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador / (vea operator (Referencia de C#)). En todos los operadores de asignación compuesta, al sobrecargar el operador
binario implícitamente se sobrecarga la asignación compuesta equivalente.
Ejemplo
// cs_operator_division_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 5;
a /= 6;
Console.WriteLine(a);
double b = 5;
b /= 6;
Console.WriteLine(b);
}
}
Resultados
0
0.833333333333333
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x %= y
equivale a
x = x % y
salvo que x sólo se evalúa una vez. El operador % está predefinido en tipos numéricos para calcular el resto de la división.
El operador %= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador % (vea operator (Referencia de C#)).
Ejemplo
// cs_operator_modulus_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 5;
a %= 3;
Console.WriteLine(a);
}
}
Resultados
2
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x &= y
equivale a
x = x & y
salvo que x sólo se evalúa una vez. El operador & realiza una operación AND bit a bit lógica sobre operandos integrales y una
operación AND lógica sobre operandos bool.
El operador &= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador & binario (vea operator (Referencia de C#).
Ejemplo
// cs_operator_and_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 0x0c;
a &= 0x06;
Console.WriteLine("0x{0:x8}", a);
bool b = true;
b &= false;
Console.WriteLine(b);
}
}
Resultados
0x00000004
False
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x |= y
equivale a
x = x | y
salvo que x sólo se evalúa una vez. El operador | realiza una operación lógica OR bit a bit sobre operandos integrales y una
operación lógica OR sobre operandos de tipo bool.
El operador |= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador | (vea operator (Referencia de C#).
Ejemplo
// cs_operator_or_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 0x0c;
a |= 0x06;
Console.WriteLine("0x{0:x8}", a);
bool b = true;
b |= false;
Console.WriteLine(b);
}
}
Resultados
0x0000000e
True
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x ^= y
se evalúa como
x = x ^ y
salvo que x sólo se evalúa una vez. El operador ^ realiza una operación OR exclusiva bit a bit sobre operandos integrales y una
operación OR exclusiva lógica sobre operandos de tipo bool.
El operador ^= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador ! (vea operator (Referencia de C#)).
Ejemplo
// cs_operator_xor_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 0x0c;
a ^= 0x06;
Console.WriteLine("0x{0:x8}", a);
bool b = true;
b ^= false;
Console.WriteLine(b);
}
}
Resultados
0x0000000a
True
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x <<= y
se evalúa como
x = x << y
salvo que x sólo se evalúa una vez. El operador << desplaza x a la izquierda el número de bits especificado por y.
El operador <<= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador << (vea operador).
Ejemplo
// cs_operator_left_shift_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 1000;
a <<= 4;
Console.WriteLine(a);
}
}
Resultados
16000
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x >>= y
se evalúa como
x = x >> y
salvo que x sólo se evalúa una vez. El operador >> desplaza x a la derecha el número de bits especificado por y.
El operador >>= no se puede sobrecargar directamente, pero los tipos definidos por el usuario sí pueden sobrecargar el
operador >> (vea operator (Referencia de C#)).
Ejemplo
// cs_operator_right_shift_assignment.cs
using System;
class MainClass
{
static void Main()
{
int a = 1000;
a >>= 4;
Console.WriteLine(a);
}
}
Resultados
62
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
x->y
(*x).y
class MainClass
{
unsafe static void Main()
{
Point pt = new Point();
Point* pp = &pt;
pp->x = 123;
pp->y = 456;
Console.WriteLine ( "{0} {1}", pt.x, pt.y );
}
}
Resultados
123 456
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
string s = GetStringValue();
// ?? also works with reference types.
// Display contents of s, unless s is null,
// in which case display "Unspecified".
Console.WriteLine(s ?? "Unspecified");
}
}
Vea también
Referencia
Operadores de C#
Conceptos
Guía de programación de C#
Tipos que aceptan valores NULL (Guía de programación de C#)
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Directivas de preprocesador de C#
Esta sección describe las directivas de preprocesador del lenguaje de C#:
#if
#else
#elif
#endif
# define
#undef
#warning
#error
#line
#region
#endregion
#pragma
#pragma warning
#pragma checksum
Aunque el compilador no dispone de un preprocesador independiente, las directivas descritas en esta sección se procesan
como si hubiera uno; estas directivas se utilizan para facilitar la compilación condicional. A diferencia de las directivas de C y
C++, no es posible utilizar estas directivas para crear macros.
Una directiva de preprocesador debe ser la única instrucción de una línea.
Vea también
Tareas
Ejemplo de métodos condicionales
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
#define DEBUG
// ...
#if DEBUG
Console.WriteLine("Debug version");
#endif
Se pueden utilizar los operadores == (igualdad), != (desigualdad), && (y) o || (o) para evaluar varios símbolos. Es posible
agrupar símbolos y operadores mediante paréntesis.
Comentarios
#if, junto con las directivas #else, #elif, #endif, #define y #undef, permite incluir o excluir código basándose en la condición de
uno o más símbolos. Esto puede ser de gran utilidad si se compila código para una versión de depuración o para una
configuración específica.
Una directiva condicional que empieza con una directiva #if debe terminarse explícitamente con una directiva #endif.
#define permite definir un símbolo tal que, si se utiliza como expresión de la directiva #if, la expresión se evaluará como true.
También se puede definir un símbolo con la opción /define del compilador. La definición de un símbolo se puede anular
mediante la directiva #undef.
Un símbolo definido mediante /define o #define no debe entrar en conflicto con una variable del mismo nombre. Es decir, no
se debería utilizar un nombre de variable en una directiva de preprocesador ni evaluar un símbolo (constante simbólica) fuera
de una directiva de preprocesador.
El ámbito de un símbolo creado mediante #define corresponde al archivo en el que se ha definido.
Ejemplo
// preprocessor_if.cs
#define DEBUG
#define VC_V7
using System;
public class MyClass
{
static void Main()
{
#if (DEBUG && !VC_V7)
Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && VC_V7)
Console.WriteLine("VC_V7 is defined");
#elif (DEBUG && VC_V7)
Console.WriteLine("DEBUG and VC_V7 are defined");
#else
Console.WriteLine("DEBUG and VC_V7 are not defined");
#endif
}
}
Resultados
DEBUG and VC_V7 are defined
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
#define VC7
//...
#if debug
Console.Writeline("Debug build");
#elif VC7
Console.Writeline("Visual Studio 7");
#endif
Se pueden utilizar los operadores == (igualdad), != (desigualdad), && (y), así como || (o) para evaluar varios símbolos. Es
posible agrupar símbolos y operadores mediante paréntesis.
Comentarios
#elif equivale a utilizar:
#else
#if
El uso de #elif es más simple ya que cada #if requiere un #endif, mientras que un #elif se puede utilizar sin el #endif
correspondiente.
Vea #if (Referencia de C#) para obtener un ejemplo de cómo utilizar #elif.
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
#define DEBUG
// ...
#if DEBUG
Console.WriteLine("Debug version");
#endif
Comentarios
Una directiva condicional, que empieza con una directiva #if, debe terminarse explícitamente con una directiva #endif. Vea
#if (Referencia de C#) para obtener un ejemplo de cómo utilizar #endif.
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Comentarios
Los símbolos se pueden utilizar para especificar condiciones de compilación. Puede comprobar el símbolo tanto con #if como
con #elif. También se puede utilizar el atributo conditional para llevar a cabo una compilación condicional.
Es posible definir símbolos, pero no asignar valores a símbolos. La directiva #define debe aparecer en el archivo antes de
cualquier instrucción que no sea una directiva.
También se puede definir un símbolo con la opción /define del compilador. La definición de un símbolo se puede anular
mediante la directiva #undef.
Un símbolo definido mediante /define o #define no debe entrar en conflicto con una variable del mismo nombre. Es decir, no
se debería utilizar un nombre de variable en una directiva de preprocesador ni evaluar un símbolo (constante simbólica) fuera
de una directiva de preprocesador.
El ámbito de un símbolo creado mediante #define corresponde al archivo en el que se ha definido.
Vea #if para obtener un ejemplo de cómo utilizar #define.
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Resultados
DEBUG is not defined
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Comentarios
#warning se utiliza normalmente en una directiva condicional. También es posible generar un error definido por el usuario
mediante #error (Referencia de C#).
Ejemplo
// preprocessor_warning.cs
// CS1030 expected
#define DEBUG
class MainClass
{
static void Main()
{
#if DEBUG
#warning DEBUG is defined
#endif
}
}
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Comentarios
#error se utiliza normalmente en una directiva condicional.
También es posible generar una advertencia definida por el usuario mediante #warning (Referencia de C#).
Ejemplo
// preprocessor_error.cs
// CS1029 expected
#define DEBUG
class MainClass
{
static void Main()
{
#if DEBUG
#error DEBUG is defined
#endif
}
}
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
class MainClass
{
static void Main()
{
#line 200
int i; // CS0168 on line 200
#line default
char c; // CS0168 on line 9
}
}
Comentarios
La directiva #line podría utilizarse en un paso intermedio automatizado del proceso de generación. Por ejemplo, si se
eliminaron las líneas del archivo de código fuente original, pero aún se desea que el compilador genere unos resultados
basados en la numeración de líneas original del archivo, se pueden eliminar las líneas y, a continuación, simular la numeración
original mediante #line.
La directiva #line hidden oculta las sucesivas líneas del depurador, de manera que cuando el desarrollador avanza por el
código, evita cualquier línea que haya entre una directiva #line hidden y la siguiente directiva #line (suponiendo que no haya
otra directiva #line hidden). Esta opción también puede utilizarse para permitir a ASP.NET que diferencie entre el código
definido por el usuario y el generado por el equipo. Aunque ASP.NET es el primer usuario de esta característica, es probable
que más generadores de código fuente hagan uso de ella.
Una directiva #line hidden no afecta ni a los nombres de los archivos ni a los números de líneas en la generación de informes
de error. Es decir, si se encuentra un error en un bloque oculto, el compilador informará del nombre del archivo en uso y del
número de la línea en que se encuentra el error.
La directiva #line filename especifica el nombre del archivo que debe aparecer en los resultados del compilador. El nombre
predeterminado es el nombre real del archivo de código fuente. El nombre de archivo debe aparecer entre comillas dobles ("").
Un archivo de código fuente puede tener cualquier número de directivas #line.
Ejemplo 1
En el ejemplo siguiente se muestra cómo el depurador omite las líneas ocultas en el código. Cuando ejecute el ejemplo,
mostrará tres líneas de texto. Sin embargo, cuando establezca un punto de interrupción, como se muestra en el ejemplo, y
presione F10 para avanzar por el código, observará que el depurador omite la línea oculta. Observe también que incluso si
establece un punto de interrupción en la línea oculta, el depurador seguirá omitiéndola.
// preprocessor_linehidden.cs
using System;
class MainClass
{
static void Main()
{
Console.WriteLine("Normal line #1."); // Set break point here.
#line hidden
Console.WriteLine("Hidden line.");
#line default
Console.WriteLine("Normal line #2.");
}
}
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Comentarios
Un bloque #region debe terminarse con una directiva #endregion.
Un bloque #region no se puede solapar con un bloque #if. Sin embargo, un bloque #region puede estar anidado en un
bloque #if y un bloque #if puede estar anidado en un bloque #region.
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Parámetros
pragma-name
El nombre de una directiva pragma reconocida.
pragma-arguments
Argumentos específicos del pragma.
Vea también
Referencia
Directivas de preprocesador de C#
#pragma warning (Referencia de C#)
#pragma checksum (Referencia del programador de C#)
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Parámetros
warning-list
Es una lista de números de advertencia separados por coma. Escriba los números solos, sin el prefijo "CS".
Cuando no se especifica ningún número de advertencia, disable deshabilita todas las advertencias y restore las habilita
todas.
Ejemplo
// pragma_warning.cs
using System;
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Parámetros
"filename"
Nombre del archivo al que hay que supervisar los cambios o actualizaciones.
"{guid}"
Identificador único global (GUID) del archivo.
"checksum_bytes"
La cadena de dígitos hexadecimales representa a los bytes de la suma de comprobación. Esta cadena debe tener un número
par de dígitos hexadecimales, ya que un número impar de dígitos produce una advertencia de error de compilación y, como
consecuencia, se omite la directiva.
Comentarios
El depurador de Visual Studio utiliza una suma de comprobación para asegurarse de que siempre encuentra el código de
fuente correcto. El compilador calcula la suma de comprobación del archivo de código fuente y, a continuación, emite el
resultado al archivo de base de datos de programa (PDB). El depurador utiliza el archivo PDB para comparar la suma de
comprobación calculada del archivo de código fuente.
Esta solución no funciona para proyectos ASP.NET, porque la suma de comprobación calculada es del archivo de código fuente
generado, en vez del archivo .aspx. Para solucionar este problema, #pragma checksum ofrece compatibilidad con la suma de
comprobación de páginas ASP.NET.
Al crear un proyecto ASP.NET en Visual C#, el archivo de código fuente generado contiene una suma de comprobación del
archivo .aspx, a partir del cual se genera el código fuente. Seguidamente, el compilador escribe esta información en el archivo
PDB.
Si el compilador no encuentra ninguna directiva #pragma checksum en el archivo, calcula la suma de comprobación y
escribe el valor en el archivo PDB.
Ejemplo
class TestClass
{
static int Main()
{
#pragma checksum "file.cs" "{3673e4ca-6098-4ec1-890f-8fceb2a794a2}" "{012345678AB}"
// New checksum
}
}
Vea también
Referencia
Directivas de preprocesador de C#
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
csc File.cs
Compila todos los archivos de C# del directorio actual, con optimizaciones activadas, y define el símbolo DEBUG. Como
resultado se genera el archivo File2.exe:
Compila todos los archivos de C# del directorio actual, generando una versión de depuración de File2.dll. No se muestra
logotipo ni ningún tipo de advertencias:
Compila todos los archivos de C# del directorio actual, generando Something.xyz (una DLL):
Vea también
Conceptos
Generar mediante la línea de comandos
Referencia del lenguaje C#
Implementación de aplicaciones de C#
Cuando se haya terminado de generar la aplicación de C#, el paso siguiente es distribuirla. C# es un lenguaje .NET; por
consiguiente, para distribuir archivos ejecutables de C# a otros equipos es necesario que .NET Framework esté instalado en
todos los equipos de ejecución (y, en su caso, en otras dependencias específicas de la aplicación de que se trate). Dispone de
varias opciones para distribuir .NET Framework. Para obtener información general, vea Redistribuir .NET Framework.
El traslado de aplicaciones completas a otros equipos se suele denominar implementación. El entorno de desarrollo de
Microsoft proporciona mecanismos para la implementación; para obtener más información, vea
Implementar aplicaciones y componentes.
Si la generación y distribución se realizan principalmente desde la línea de comandos, podría ser conveniente estudiar otros
métodos de implementación y redistribución de las dependencias.
Vea también
Conceptos
Generar mediante la línea de comandos
Referencia del lenguaje C#
/target Especifica el formato del archivo de resultados mediante una de las cuatro opciones
siguientes:
/target:exe/target:library/target:module/target:winexe
Ensamblados de .NET Framework
Opción Propósito
/addmodule Especifica uno o varios módulos como parte del ensamblado.
/delaysign Indica al compilador que agregue la clave pública pero que deje el ensamblado sin firmar.
/lib Especifica la ubicación de los ensamblados a los que se hace referencia mediante /reference.
/checked Especifica si, en caso de que la aritmética de enteros desborde los límites del tipo de datos, se producirá una exce
pción en tiempo de ejecución.
/fullpaths Especifica la ruta de acceso absoluta al archivo en los resultados del compilador.
/nowarn Suprime la generación del compilador de advertencias especificadas.
/baseaddress Especifica la dirección base preferente en la que se debe cargar un archivo DLL.
/codepage Especifica la página de códigos que debe utilizarse para todos los archivos de código fuente en la compilación.
/unsafe Permite la compilación del código que utiliza la palabra clave unsafe.
/bugreport Crea un archivo 'Informe de errores'. Este archivo se enviará junto con la información de bloqueo si se utiliza co
n /errorreport:prompt o /errorreport:send.
/codepage Especifica la página de códigos que se utilizará al abrir los archivos de código fuente.
/delaysign Retarda la firma del ensamblado utilizando sólo la parte pública de la clave de nombre seguro.
/errorreport Especifica cómo controlar errores internos del compilador: prompt, send o none. El valor predeterminado es no
ne.
/filealign Especifica la alineación utilizada para las secciones del archivo de resultados.
/main Especifica el tipo que contiene el punto de entrada (se pasa por alto los demás puntos de entrada posibles).
/noconfig Indica al compilador que no debe incluir automáticamente el archivo CSC.RSP.
/out Especifica el nombre del archivo de resultados (nombre predeterminado: nombre base de archivo con la clase p
rincipal o del primer archivo).
/platform Limita las plataformas en las que se puede ejecutar este código: x86, Itanium, x64 o Cualquier CPU. El valor pred
eterminado es Cualquier CPU.
/recurse Incluye todos los archivos del directorio y subdirectorios actuales de acuerdo con las especificaciones de los co
modines.
/target Especifica el formato del archivo de resultados mediante una de las cuatro opciones
siguientes:/target:exe/target:library/target:module/target:winexe
@response_file
Argumentos
response_file
Archivo que especifica opciones del compilador o archivos de código fuente para compilar.
Comentarios
El compilador procesará las opciones del compilador y los archivos de código fuente como si se hubiesen especificado en la
línea de comandos.
Para especificar varios archivos de respuesta en una compilación, hay que especificar varias opciones de archivo de respuesta.
Por ejemplo:
@file1.rsp @file2.rsp
En una misma línea de un archivo de respuesta, pueden aparecer varias opciones del compilador y archivos de código fuente.
Una especificación de opción del compilador debe aparecer en una única línea (no puede abarcar varias líneas). Los archivos
de respuesta pueden contener comentarios que empiezan con el símbolo #.
Especificar opciones del compilador desde un archivo de respuesta produce el mismo efecto que incluir esas opciones en la
línea de comandos. Para obtener más información, vea Generar desde la línea de comandos.
El compilador procesa las opciones de comandos según las encuentra. Por consiguiente, los argumentos de la línea de
comandos pueden reemplazar opciones enumeradas anteriormente en archivos de respuesta. A la inversa, las opciones de un
archivo de respuesta reemplazarán opciones incluidas previamente en la línea de comandos o en otros archivos de respuesta.
C# proporciona el archivo csc.rsp, que se encuentra en el mismo directorio que el archivo csc.exe. Para obtener más
información acerca de csc.rsp, vea /noconfig.
Esta opción del compilador no se puede establecer en el entorno de desarrollo de Visual Studio, ni se puede cambiar mediante
programación.
Ejemplo
A continuación, se muestran algunas líneas de un archivo de respuesta de ejemplo:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/addmodule:file[;file2]
Argumentos
file, file2
Archivo de resultados que contiene metadatos. Este archivo no puede contener un manifiesto de ensamblado. Para importar
más de un archivo, hay que separar los nombres de archivo con comas o puntos y comas.
Comentarios
Todos los módulos agregados mediante /addmodule deben hallarse en el mismo directorio que el archivo de resultados en
tiempo de ejecución. Es decir, se puede especificar un módulo de cualquier directorio en el momento de la compilación, pero el
módulo debe encontrarse en el directorio de la aplicación en tiempo de ejecución. Si dicho módulo no se encuentra en el
directorio de la aplicación en tiempo de ejecución, se obtiene la excepción TypeLoadException.
file no puede contener un ensamblado. Por ejemplo, si el archivo de resultados se creó con /target:module, se pueden importar
sus metadatos con /addmodule.
Si se creó el archivo de resultados con una opción /target diferente de /target:module, no se podrán importar sus metadatos
con /addmodule, pero sí con /reference.
Esta opción del compilador no está disponible en Visual Studio; en un proyecto no se puede hacer referencia a un módulo.
Además, esta opción del compilador no se puede modificar mediante programación.
Ejemplo
Para compilar el archivo de código fuente input.cs y agregar metadatos de metad1.netmodule y metad2.netmodule para
generar out.exe, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/baseaddress:address
Argumentos
address
Dirección base para el archivo DLL. Esta dirección puede especificarse como número decimal, hexadecimal u octal.
Comentarios
La dirección base predeterminada de un archivo DLL la establece Common Language Runtime de .NET Framework.
Hay que tener en cuenta que se redondeará la palabra de orden inferior de esta dirección. Por ejemplo, si se especifica
0x11110001, quedará redondeada como 0x11110000.
Para completar el proceso de firma para un archivo DLL, utilice la opción –R de SN.EXE.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Haga clic en el botón Avanzadas.
4. Modifique la propiedad Dirección base del archivo DLL.
Para establecer esta opción del compilador mediante programación, vea BaseAddress.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/bugreport:file
Argumentos
file
Nombre del archivo que va a contener el informe de error.
Comentarios
La opción /bugreport especifica que la siguiente información se debe colocar en file:
Una copia de todos los archivos de código fuente de la compilación.
Una lista de las opciones del compilador utilizadas en la compilación.
Información de versión acerca del compilador, el motor en tiempo de ejecución y el sistema operativo.
Los ensamblados y módulos a los que se hace referencia (guardados como dígitos hexadecimales), excepto los
ensamblados que se distribuyen con .NET Framework y el SDK.
Resultados del compilador, si existen.
Descripción del problema, que debe rellenar el usuario.
Descripción de cómo se debería resolver el problema, que debe rellenar el usuario.
Si se utiliza esta opción con /errorreport:prompt o /errorreport:send, se enviará la información del archivo a Microsoft
Corporation.
Puesto que se colocará una copia de todos los archivos de código fuente en file, es recomendable reproducir el defecto de
código que se sospecha en el programa más corto posible.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Observe que el contenido del archivo generado expone código fuente que podría producir la revelación inadvertida de
información.
Vea también
Referencia
/errorreport (Establecer el comportamiento de notificación de errores) (Opciones del compilador de C#)
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/checked[+ | <U>-</U>]
Comentarios
Una instrucción de aritmética de enteros que pertenece al ámbito de las palabras clave checked o unchecked no se ve
afectada por la opción /checked.
Si una instrucción de aritmética de enteros no comprendida en el ámbito de las palabras clave checked o unchecked da
como resultado un valor situado fuera del intervalo del tipo de datos, y se utiliza /checked+ (/checked) en la compilación,
esa instrucción causará una excepción en tiempo de ejecución. Si se utiliza /checked- en la compilación, la instrucción no
causará ninguna excepción en tiempo de ejecución.
El valor predeterminado de esta opción es /checked-, por lo que puede obtener el mismo efecto con tan sólo omitir la opción.
Un posible escenario para utilizar /checked- es la generación de grandes aplicaciones: a veces se utilizan herramientas
automatizadas para generar dichas aplicaciones que podrían establecer /checked como + de forma automática: en estos
casos, puede reemplazar el valor predeterminado global especificando /checked-.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener más información, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Haga clic en el botón Avanzadas.
4. Modifique la propiedad Comprobar el desbordamiento y subdesbordamiento aritmético.
Para tener acceso a esta opción del compilador mediante programación, vea CheckForOverflowUnderflow.
Ejemplo
Compile t2.cs y especifique que cualquier instrucción de aritmética de enteros que no pertenezca al ámbito de las palabras
clave checked o unchecked y dé como resultado un valor situado fuera del intervalo del tipo de datos causará una excepción
en tiempo de ejecución.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/codepage:id
Argumentos
id
Identificador de la página de códigos para todos los archivos de código fuente en la compilación.
Comentarios
Si se compilan uno o varios archivos de código fuente que no se crearon para utilizar la página de códigos predeterminada en
el equipo, se podrá utilizar la opción /codepage para especificar la página de códigos que debe utilizarse. /codepage se
aplica a todos los archivos de código fuente de la compilación.
Si los archivos de código fuente se crearon con la misma página de códigos que está activada en el equipo o se crearon con
UNICODE o UTF-8, no es preciso utilizar /codepage.
Para obtener más información sobre cómo averiguar qué páginas de códigos admite el sistema, vea GetCPInfo.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/debug[+ | <U>-</U>]
/debug:{<U>full</U> | pdbonly}
Argumentos
+|-
Si se especifica +, o simplemente /debug, el compilador genera información de depuración y la incluye en una base de
datos de programa (archivo .pdb). Si se especifica -, que es la opción predeterminada cuando no se especifica /debug, no se
crea información de depuración.
full | pdbonly
Especifica el tipo de información de depuración generada por el compilador. El argumento full, que es la opción
predeterminada si no se especifica /debug:pdbonly, permite asociar un depurador al programa que se ejecuta. Al
especificar la opción pdbonly, se permite depurar el código fuente cuando se inicia el programa en el depurador, pero sólo
muestra el ensamblador cuando el programa que se ejecuta está asociado al depurador.
Comentarios
Utilice esta opción para generar versiones de depuración. Si no se especifica /debug, /debug+ o /debug:full, no podrá
depurar el archivo de resultados del programa.
Si utiliza /debug:full, sea consciente de que se producirá algún impacto en la velocidad y el tamaño del código optimizado JIT
y un pequeño impacto en la calidad del código con /debug:full. Recomendamos /debug:pdbonly o ningún PDB para
generar el código de la versión de lanzamiento.
Nota
Una diferencia entre /debug:pdbonly y /debug:full es que con /debug:full el compilador emite DebuggableAttribute, que
se utiliza para indicar al compilador JIT que la información de depuración está disponible. Por consiguiente, aparecerá un err
or si el código contiene DebuggableAttribute establecido en false y ha utilizado /debug:full.
Para obtener información sobre cómo configurar el rendimiento de depuración de una aplicación, vea
Facilitar la depuración de una imagen.
Para cambiar la ubicación del archivo .pdb, vea
/pdb (Especificar archivo de símbolos de depuración) (Opciones del compilador de C#).
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener más información, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Haga clic en el botón Avanzadas.
4. Modifique la propiedad Información de depuración.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea DebugSymbols.
Ejemplo
Para incluir información de depuración en el archivo de resultados app.pdb, ejecute:
/define:name[;name2]
Argumentos
name, name2
Nombre de uno o varios símbolos que desea definir.
Comentarios
La opción /define produce el mismo efecto que una directiva de preprocesador #define en el archivo de código fuente. Un
símbolo permanece definido hasta que una directiva #undef del archivo de código fuente quita la definición o hasta que el
compilador llega al final del archivo.
Se pueden utilizar símbolos creados por esta opción con #if, #else, #elif y #endif para compilar archivos de código fuente de
forma condicional.
/d es la forma abreviada de /define.
Se pueden definir múltiples símbolos con /define utilizando punto y coma o coma para separar los nombres de símbolos. Por
ejemplo:
/define:DEBUG;TUESDAY
El propio compilador de C# no define ningún símbolo ni macro que se pueda utilizar en el código fuente; todas las definiciones
de símbolos deben estar definidas por el usuario.
Nota
La directiva #define de C# no permite que se le proporcione un valor a un símbolo, igual que sucede en otros lenguajes com
o C++. Por ejemplo, #define no se puede utilizar para crear una macro o definir una constante. Si tiene que definir una cons
tante, utilice una variable enum. Si desea crear una macro de estilo C++, considere alternativas como el uso de genéricos. Ya
que las macros son notoriamente propensas a errores, C# no permite su uso, pero proporciona alternativas más seguras.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener más información, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Modifique el valor de la propiedad Símbolos de compilación condicional.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea DefineConstants.
Ejemplo
// preprocessor_define.cs
// compile with: /define:xx
// or uncomment the next line
// #define xx
using System;
public class Test
{
public static void Main()
{
#if (xx)
Console.WriteLine("xx defined");
#else
Console.WriteLine("xx not defined");
#endif
}
}
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/delaysign[ + | - ]
Argumentos
+|-
Utilice /delaysign- para firmar completamente un ensamblado. Utilice /delaysign+ si desea incluir sólo la clave pública en
el ensamblado. El valor predeterminado es /delaysign-.
Comentarios
La opción /delaysign no produce ningún efecto a menos que se utilice con /keyfile o /keycontainer.
Cuando se solicita un ensamblado con firma completa, el compilador calcula el hash del archivo que contiene el manifiesto
(metadatos de ensamblado) y firma el hash con la clave privada. La firma digital resultante se almacena en el archivo que
contiene el manifiesto. Cuando se firma un ensamblado de forma retardada, el compilador no calcula ni almacena la firma,
pero reserva espacio en el archivo para poder agregar la firma más tarde.
Por ejemplo, si se utiliza /delaysign+, un comprobador podrá colocar el ensamblado en la caché global. Después de las
pruebas, se puede firmar totalmente el ensamblado colocando la clave privada en el mismo mediante la utilidad
Assembly Linker.
Para obtener más información, vea Crear y utilizar ensamblados con nombre seguro y Retrasar la firma de un ensamblado.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener más información, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Firma.
3. Modifique la propiedad Retrasar firma sólo.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea DelaySign.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/doc:file
Argumentos
file
Archivo de resultados para XML, que se llena con los comentarios de los archivos del código fuente de la compilación.
Comentarios
En los archivos de código fuente, pueden procesarse y agregarse al archivo XML los comentarios de documentación que
preceden a los citados a continuación:
Tipos definidos por el usuario como una clase, un delegado o una interfaz
Miembros como un campo, un evento, una propiedad o un método.
El código fuente que contiene Main es el primero que se extrae al archivo XML.
Para utilizar el archivo .xml generado junto con la función IntelliSense, dé el mismo nombre al archivo .xml que al ensamblado
que con el desee tener compatibilidad, y asegúrese de que ambos estén en el mismo directorio. Así, cuando se haga referencia
al ensamblado en el proyecto de Visual Studio, también se encontrará el archivo .xml. Vea Proporcionar comentarios al código
para obtener más información.
A no ser que compile con /target:module, file contendrá las etiquetas <assembly></assembly>, que especifican el nombre del
archivo que contiene el manifiesto del ensamblado del archivo de resultados de la compilación.
Nota
La opción /doc se aplica a todos los archivos de entrada; o bien, si se ha establecido en la configuración del proyecto, a todos
los archivos en el proyecto. Para deshabilitar las advertencias relacionadas con los comentarios de documentación de un arc
hivo o sección de código en particular, utilice #pragma warning.
Vea Etiquetas recomendadas para comentarios de documentación para conocer los modos de generar documentación a partir
de los comentarios del código.
Vea Ejemplo XML Documentation para obtener un ejemplo.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Modifique la propiedad Archivo de documentación XML.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea DocumentationFile.
Vea también
Tareas
Ejemplo XML Documentation
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
Argumentos
none
Los informes sobre los errores internos del compilador no se recogerán ni se enviarán a Microsoft.
prompt
Le pide que envíe un informe cuando reciba un error interno del compilador. prompt es la opción predeterminada cuando
se compila una aplicación en el entorno de desarrollo.
queue
Pone en la cola el informe de errores. Cuando inicia una sesión con privilegios de administrador, aparece una ventana
emergente donde puede informar de todos los errores desde la última vez que inició una sesión. No se le pedirá que envíe
informes de errores más de una vez cada tres días. queue es la opción predeterminada cuando se compila una aplicación en
la línea de comandos.
send
Envía automáticamente informes de errores internos del compilador a Microsoft. Para habilitar esta opción, primero debe
aceptar la directiva de recogida de datos de Microsoft. La primera vez que especifique /errorreport:send en un equipo, un
mensaje del compilador le remitirá a un sitio Web que contiene la directiva de recogida de datos de Microsoft.
Comentarios
Un error interno del compilador (ICE) se produce cuando el compilador no puede procesar un archivo de código fuente.
Cuando aparece un ICE, el compilador no genera un archivo de resultados ni otro tipo de diagnóstico útil que pueda utilizar
para corregir el código.
En versiones anteriores, cuando se obtenía un ICE, se le animaba a que llamara al servicio de soporte técnico de Microsoft para
informar del problema. Con /errorreport, puede proporcionar directamente la información de los ICE al equipo de Visual C#.
Sus informes de errores pueden ayudar a mejorar las futuras versiones del compilador.
La capacidad de un usuario para enviar informes depende del equipo y de los permisos de la directiva del usuario.
Para obtener más información sobre depurador de errores, vea
Descripción de la herramienta Dr. Watson para Windows (Drwtsn32.exe) Descripción de la herramienta Dr. Watson para
Windows (Drwtsn32.exe).
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener más información, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Haga clic en el botón Avanzadas.
4. Modifique la propiedad Informe de errores internos del compilador.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea ErrorReport.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/filealign:number
Argumentos
number
Valor que especifica el tamaño de las secciones del archivo de resultados. Los valores válidos son 512, 1024, 2048, 4096 y
8192. Estos valores se expresan en bytes.
Comentarios
Cada sección se alineará con un límite que es múltiplo del valor /filealign. No hay un valor predeterminado fijo. Si no se
especifica /filealign, Common Language Runtime elige un valor predeterminado en tiempo de compilación.
Especificar el tamaño de la sección afecta al tamaño del archivo de resultados. Puede ser útil modificar el tamaño de sección
para programas que se ejecuten en dispositivos más pequeños.
Utilice DUMPBIN para ver información acerca de las secciones del archivo de resultados.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Haga clic en el botón Avanzadas.
4. Modifique la propiedad Alineación de archivo.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea FileAlignment.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/fullpaths
Comentarios
Los errores y advertencias que resultan de la compilación especifican, de forma predeterminada, el nombre del archivo en el
que se encontró el error. La opción /fullpaths hace que el compilador especifique la ruta completa al archivo.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/help
/?
Comentarios
Si se incluye esta opción en una compilación, no se creará ningún archivo de resultados y no se llevará a cabo la compilación.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/keycontainer:string
Argumentos
Término Definición
string Nombre del contenedor de clave de nombre seguro.
Comentarios
Cuando se utiliza la opción /keycontainer, el compilador crea un componente compartible insertando en el manifiesto del
ensamblado una clave pública incluida en el contenedor especificado y firmando el ensamblado final con la clave privada. Para
generar un archivo de claves, escriba sn -k file en la línea de comandos. sn -i instala el par de claves en un contenedor.
Si se compila con la opción /target:module, el nombre del archivo de clave queda almacenado en el módulo y se incorpora al
ensamblado al compilar este módulo como un ensamblado mediante /addmodule.
También se puede especificar esta opción como un atributo personalizado (System.Reflection.AssemblyKeyNameAttribute) en
el código fuente de cualquier módulo de lenguaje intermedio de Microsoft (MSIL).
También puede pasar la información de cifrado al compilador mediante /keyfile. Utilice /delaysign si desea agregar la clave
pública al manifiesto del ensamblado pero prefiere retardar la firma del ensamblado hasta haberlo probado.
Para obtener más información, vea Crear y utilizar ensamblados con nombre seguro y Retrasar la firma de un ensamblado.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
Esta opción del compilador no está disponible en el entorno de desarrollo de Visual Studio.
Puede tener acceso mediante programación a esta opción del compilador con AssemblyKeyContainerName.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/keyfile:file
Argumentos
Término Definición
file Nombre del archivo que contiene la clave de nombre seguro.
Comentarios
Cuando se utiliza esta opción, el compilador inserta la clave pública del archivo especificado en el manifiesto del ensamblado y,
a continuación, firma el último ensamblado con la clave privada. Para generar un archivo de clave, escriba sn -k file en la línea
de comandos.
Si se compila con la opción /target:module, el nombre del archivo de claves se mantiene en el módulo y se incorpora en el
ensamblado que se crea al compilar un ensamblado con la opción /addmodule.
También puede pasar la información de cifrado al compilador mediante /keycontainer. Utilice /delaysign para firmar el
ensamblado de forma parcial.
Si se especifica tanto /keyfile como /keycontainer (ya sea mediante una opción de línea de comandos o mediante un atributo
personalizado) en la misma compilación, el compilador probará primero el contenedor de clave. Si lo consigue, el ensamblado
se firma con la información del contenedor de claves. Si el compilador no encuentra el contenedor de clave, probará el archivo
especificado con /keyfile. Si lo consigue, el ensamblado se firma con la información del archivo de clave y la información de la
clave se instalará en el contenedor de clave (similar a sn -i) de modo que, en la próxima compilación, el contenedor de claves
será válido.
Tenga en cuenta que un archivo de clave puede contener sólo la clave pública.
Para obtener más información, vea Crear y utilizar ensamblados con nombre seguro y Retrasar la firma de un ensamblado.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Firma.
3. Modifique la propiedad Seleccione un archivo de clave de nombre seguro.
Puede tener acceso mediante programación a esta opción del compilador con AssemblyOriginatorKeyFile.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/langversion:option
Argumentos
option
Si option es ISO-1, el compilador producirá un error para cualquier sintaxis que no esté en la especificación del lenguaje C#
ISO/IEC 23270:2003. Si option es default, el compilador aceptará toda sintaxis del lenguaje que sea válida.
/langversion:default es el valor predeterminado.
Comentarios
La versión 1.0 de la especificación de C# representa la funcionalidad disponible con /langversion:ISO-1.
http://msdn.microsoft.com/vcsharp/programming/language/default.aspx contiene todas las especificaciones en archivos de
Microsoft Word.
Los metadatos a los que hace referencia una aplicación de C# no están sujetos a la opción del compilador /langversion.
Todas las versiones del compilador de C# contienen extensiones que corresponden a la especificación del lenguaje, de modo
que /langversion no proporciona la funcionalidad equivalente de una versión anterior del compilador.
Sin tener en cuenta la configuración de /langversion que utilice, debe emplear la versión actual de Common Language
Runtime para crear archivos .exe o .dll.
Una excepción son los ensamblados de confianza y
/moduleassemblyname (Especificar un ensamblado de confianza para el módulo) (Opción del compilador de C# ), que
funcionan bajo /langversion:ISO-1.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Haga clic en el botón Avanzadas.
4. Modifique la propiedad Versión del lenguaje.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea LanguageVersion.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/lib:dir1[,dir2]
Argumentos
dir1
Directorio utilizado por el compilador para buscar un ensamblado al que se hace referencia si no lo encuentra en el
directorio de trabajo actual (el directorio desde el que se invoca al compilador) o en el directorio del sistema de Common
Language Runtime.
dir2
Uno o varios directorios adicionales para buscar las referencias a ensamblados. Separe los nombres de directorio adicionales
con una coma y sin espacio en blanco entre ellos.
Comentarios
El compilador busca referencias a ensamblados que no presentan la ruta completa en el siguiente orden:
1. Directorio actual de trabajo. Es el directorio desde donde se invoca al compilador.
2. Directorio del sistema de Common Language Runtime.
3. Directorios especificados por /lib.
4. Directorios especificados por la variable de entorno LIB.
Hay que utilizar /reference para especificar una referencia a un ensamblado.
La opción /lib es sumatoria; si se especifica más de una vez, anexa nuevos valores a los ya existentes.
Una alternativa al uso de /lib consiste en copiar en el directorio de trabajo los ensamblados requeridos; esto permitirá pasar el
nombre del ensamblado a /reference. A continuación, se pueden eliminar los ensamblados del directorio de trabajo. Dado
que en el manifiesto del ensamblado no se especifica la ruta al ensamblado dependiente, la aplicación puede iniciarse en el
equipo de destino y desde allí buscará y utilizará el ensamblado en la caché de ensamblados global.
El hecho de que el compilador puede hacer referencia al ensamblado, no implica que Common Language Runtime pueda
buscar y cargar el ensamblado en tiempo de ejecución. Vea Cómo el motor en tiempo de ejecución ubica ensamblados para
obtener los detalles sobre cómo busca el motor en tiempo de ejecución los ensamblados a los que se hace referencia.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra el cuadro de diálogo Páginas de propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Ruta de acceso de referencias.
3. Modifique el contenido del cuadro de lista.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea ReferencePath.
Ejemplo
Para compilar t2.cs con el fin de crear un archivo .exe. El compilador busca referencias a ensamblados en el directorio de
trabajo y en el directorio raíz de la unidad C.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/linkresource:filename[,identifier[,accessibility-modifier]]
Argumentos
filename
Archivo de recursos de .NET Framework con el que desea crear un vínculo desde el ensamblado.
identifier (opcional)
Nombre lógico del recurso; nombre usado para cargar el recurso. El valor predeterminado es el nombre del archivo.
accessibility-modifier (opcional)
Accesibilidad del recurso: pública o privada. El valor predeterminado es que sea pública.
Comentarios
Los recursos vinculados son públicos en el ensamblado cuando se crean con el compilador de C#. Para que sean privados,
especifique el modificador de accesibilidad private. No se permite ningún otro modificador distinto de public o private.
/linkresource requiere una de las opciones de /target distinta de /target:module.
Si filename es un archivo de recursos de .NET Framework creado, por ejemplo, con Resgen.exe o en el entorno de desarrollo,
se puede obtener acceso a él con miembros del espacio de nombres System.Resources. Para obtener más información, vea
System.Resources.ResourceManager. En todos los demás recursos, hay que utilizar los métodos GetManifestResource* en la
clase Assembly para tener acceso al recurso en tiempo de ejecución.
El archivo especificado en filename puede tener cualquier formato. Por ejemplo, se puede hacer que un archivo DLL nativo
forme parte de un ensamblado para que se pueda instalar en la caché de ensamblados global y sea accesible desde código
administrado del ensamblado. El segundo de los siguientes ejemplos muestra cómo hacerlo. También es posible llevarlo a
cabo en Assembly Linker. El tercer ejemplo indica cómo. Para obtener más información, vea
Herramienta Assembly Linker (Al.exe) y Trabajar con ensamblados y la Caché de ensamblados global.
La opción /linkres es la forma breve de /linkresource.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Ejemplo
Para compilar in.cs y vincularlo al archivo de recursos rf.resource, ejecute:
Para compilar A.cs en un archivo DLL, vincularlo a un archivo DLL nativo N.dll y colocar el resultado en la Caché de
ensamblados global (GAC), ejecute lo siguiente. En este ejemplo, A.dll y N.dll residen en la GAC.
Este ejemplo hace lo mismo que el anterior, pero utiliza las opciones de Assembly Linker.
Vea también
Referencia
Herramienta Assembly Linker (Al.exe)
Otros recursos
Opciones del compilador de C#
Trabajar con ensamblados y la Caché de ensamblados global
Referencia del lenguaje C#
/main:class
Argumentos
class
Tipo que contiene el método Main.
Comentarios
Si la compilación incluye más de un tipo con un método Main, se puede especificar el tipo que contiene el método Main que
se desea utilizar como punto de entrada en el programa.
Esta opción sólo se puede usar al compilar archivos .exe.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Aplicación.
3. Modifique el valor de la propiedad Objeto inicial.
Para establecer esta opción del compilador mediante programación, vea StartupObject.
Ejemplo
Para compilar t2.cs y t3.cs, y especificar que el método Main está en Test2, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/moduleassemblyname:assembly_name
Argumentos
assembly_name
El nombre del ensamblado a cuyos tipos no públicos puede tener acceso .netmodule.
Comentarios
Se debe utilizar /moduleassemblyname al generar .netmodule cuando se den las condiciones siguientes:
.netmodule necesita tener acceso a los tipos no públicos de un ensamblado existente.
Se conoce el nombre del ensamblado en el que se generará .netmodule.
El ensamblado existente ha concedido acceso de ensamblado de confianza al ensamblado en el que se generará
.netmodule.
Para obtener más información sobre cómo generar .netmodule, vea
/target:module (Crear un módulo para agregarlo a un ensamblado) (Opciones del compilador de C#).
Para obtener más información sobre los ensamblados de confianza, vea
Ensamblados de confianza (Guía de programación de C#).
Esta opción no está disponible en el entorno de desarrollo; sólo está disponible al compilar desde la línea de comandos.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Ejemplo
Este ejemplo genera un ensamblado con un tipo privado que concede acceso de ensamblado de confianza a un ensamblado
llamado csman_an_assembly.
// moduleassemblyname_1.cs
// compile with: /target:library
using System;
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo ("csman_an_assembly")]
class An_Internal_Class
{
public void Test()
{
Console.WriteLine("An_Internal_Class.Test called");
}
}
Este ejemplo genera un módulo .netmodule que tiene acceso a un tipo no público del ensamblado moduleassemblyname_1.dll.
Al saber que dicho .netmodule se generará en un ensamblado llamado csman_an_assembly, se puede especificar
/moduleassemblyname, lo que permite que el módulo .netmodule tenga acceso a los tipos no públicos de un ensamblado
que ha concedido acceso de ensamblado de confianza a csman_an_assembly.
// moduleassemblyname_2.cs
// compile with: /moduleassemblyname:csman_an_assembly /target:module /reference:moduleasse
mblyname_1.dll
class B {
public void Test() {
An_Internal_Class x = new An_Internal_Class();
x.Test();
}
}
Este ejemplo de código genera el ensamblado csman_an_assembly, haciendo referencia al ensamblado y .netmodule
generados previamente.
// csman_an_assembly.cs
// compile with: /addmodule:moduleassemblyname_2.netmodule /reference:moduleassemblyname_1.
dll
class A {
public static void Main() {
B bb = new B();
bb.Test();
}
}
Resultados
An_Internal_Class.Test called
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/noconfig
Comentarios
El archivo csc.rsp hace referencia a todos los ensamblados incluidos en .NET Framework. Las referencias reales que incluye el
entorno de desarrollo Visual Studio .NET dependen del tipo de proyecto.
Es posible modificar el archivo csc.rsp y especificar opciones de compiladores adicionales que puedan incluirse en cada
compilación desde la línea de comandos con csc.exe (excepto la opción /noconfig).
El compilador procesa en último lugar las opciones que se pasan al comando csc. Por lo tanto, cualquier opción de la línea de
comandos reemplaza la configuración de la misma opción en el archivo csc.rsp.
Si no desea que el compilador busque y utilice la configuración del archivo csc.rsp, especifique /noconfig.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/nologo
Comentarios
Esta opción no está disponible en el entorno de desarrollo; sólo está disponible al compilar desde la línea de comandos.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/nostdlib[<U>+</U> | -]
Comentarios
Use esta opción si desea definir o crear sus propios objetos y espacio de nombres System.
Si no especifica /nostdlib, se importará mscorlib.dll al programa (equivale a especificar /nostdlib-). Especificar sólo /nostdlib
equivale a especificar /nostdlib+.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Haga clic en el botón Avanzadas.
4. Modifique la propiedad No hacer referencia al archivo mscorlib.dll.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea NoStdLib.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/nowarn:number1[,number2,...]
Argumentos
number1, number2
Número o números de advertencia que el compilador debe suprimir.
Comentarios
Sólo se debe especificar la parte numérica del identificador de advertencia. Por ejemplo, si se desea suprimir CS0028, hay que
especificar /nowarn:28.
El compilador omitirá silenciosamente los números de advertencias que se han pasado a /nowarn, que eran válidas en
versiones anteriores, pero que se han eliminado del compilador. Por ejemplo, CS0679 era válida para el compilador en Visual
Studio .NET 2002, pero posteriormente se ha eliminado.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Modifique el valor de la propiedad Suprimir advertencias.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea DelaySign.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/optimize[+ | <U>-</U>]
Comentarios
También indica a Common Language Runtime que optimice el código en tiempo de ejecución.
De forma predeterminada, las optimizaciones están deshabilitadas. Especifique /optimize+ para habilitar las optimizaciones.
Cuando genere un módulo para que lo utilice un ensamblado, utilice la misma configuración /optimize que para el propio
ensamblado.
/o es la forma abreviada de /optimize.
Se pueden combinar las opciones /optimize y /debug.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Modifique la propiedad Optimizar código.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea Optimize.
Ejemplo
Para compilar t2.cs y habilitar las optimizaciones del compilador, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/out:filename
Argumentos
filename
Nombre del archivo de resultados creado por el compilador.
Comentarios
En la línea de comandos, es posible especificar varios archivos de resultados de una compilación. El compilador espera
encontrar al menos un archivo de código fuente después de la opción /out. Posteriormente, todos los archivos de código
fuente se compilarán en el archivo de resultados especificado por la opción /out.
Hay que especificar el nombre completo y la extensión del archivo que se desea crear.
Si no se especifica el nombre del archivo de resultados:
Un archivo .exe toma el nombre del archivo de código fuente que contiene el método Main.
Un archivo .dll o .netmodule toma el nombre del primer archivo de código fuente.
Un archivo de código fuente utilizado para compilar un archivo de resultados no puede utilizarse para compilar otro archivo de
este tipo en la misma compilación.
Cuando se producen varios archivos de resultados en una compilación de línea de comandos, recuerde que sólo uno de los
archivos de resultados puede ser un ensamblado y que sólo el primero que haya especificado (ya sea implícita o
explícitamente con /out) puede ser el ensamblado.
Todos los módulos que se produzcan como parte de una compilación se convierten en archivos asociados a cualquier
ensamblado que también se haya producido en la compilación. Utilice ildasm.exe para ver el manifiesto del ensamblado y los
archivos asociados.
Es obligatorio utilizar la opción /out del compilador que un archivo exe sea el destino de un ensamblado de confianza. Para
obtener más información, vea Ensamblados de confianza (Guía de programación de C#).
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Aplicación.
3. Modifique la propiedad Nombre del ensamblado.
Para establecer esta opción del compilador mediante programación: OutputFileName es una propiedad de sólo lectura
que se determina a partir de una combinación del tipo de proyecto (ejecutable, biblioteca, etc.) y el nombre del
ensamblado. Es necesario modificar una de estas propiedades o ambas para establecer el nombre del archivo de
resultados.
Ejemplo
Para compilar t.cs y crear el archivo de resultados t.exe, y para generar t2.cs y crear el archivo de resultados del módulo
mymodule.netmodule, ejecute:
Vea también
Referencia
Ensamblados de confianza (Guía de programación de C#)
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/pdb:filename
Argumentos
filename
Nombre y ubicación del archivo de símbolos de depuración.
Comentarios
Cuando especifica /debug (Emitir información de depuración) (Opciones del compilador de C#), el compilador crea un archivo
.pdb en el mismo directorio en el que creará el archivo de resultados (.exe o .dll) con un nombre de archivo que es igual que el
del archivo de resultados.
/pdb le permite especificar un nombre de archivo y ubicación no predeterminados para el archivo .pdb.
Esta opción del compilador no se puede establecer en el entorno de desarrollo de Visual Studio, ni se puede cambiar mediante
programación.
Ejemplo
Compile t.cs y cree un archivo .pdb denominado tt.pdb:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/platform:string
Parámetros
string
x86, Itanium, x64 o anycpu (valor predeterminado).
Comentarios
x86 compila el ensamblado para ejecutarlo en Common Language Runtime de 32 bits, compatible con x86.
Itanium compila el ensamblado para ejecutarlo en Common Language Runtime de 64 bits en un equipo con un
procesador Itanium.
x64 compila el ensamblado para ejecutarlo en Common Language Runtime de 64 bits en un equipo que admite el
conjunto de instrucciones de AMD64 o EM64T.
anycpu (valor predeterminado) compila el ensamblado para ejecutarlo en cualquier plataforma.
En un sistema operativo Windows de 64 bits:
Los ensamblados compilados con /platform:x86 se ejecutarán en el CLR de 32 bits que se ejecuta bajo WOW64.
Los ejecutables compilados con el modificador /platform:anycpu se ejecutarán en el CLR de 64 bits.
Un archivo DLL compilado con el modificador /platform:anycpu se ejecutará en el mismo CLR que el proceso en el que
se cargó.
Para obtener más información sobre cómo desarrollar una aplicación que se ejecute en un sistema operativo Windows de 64
bits, vea Aplicaciones de 64 bits.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Modifique la propiedad Destino de la plataforma.
Nota /platform no está disponible en el entorno de desarrollo en Visual C# Express.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea PlatformTarget.
Ejemplo
En el ejemplo siguiente se muestra cómo utilizar la opción /platform para especificar que la aplicación sólo se debe ejecutar
en el CLR de 64 bits, en un sistema operativo Windows de 64 bits para Itanium.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/recurse:[dir\]file
Argumentos
dir (opcional)
Directorio en el que se desea iniciar la búsqueda. Si no se especifica, la búsqueda empieza en el directorio del proyecto.
file
Los archivos que se van a buscar. Se permiten caracteres comodín.
Comentarios
La opción /recurse permite compilar archivos de código fuente de todos los directorios secundarios del directorio especificado
(dir) o del directorio del proyecto.
El nombre de archivo se puede especificar con caracteres comodín de modo que se compilen todos los archivos del directorio
del proyecto que cumplan la especificación sin tener que utilizar /recurse.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Ejemplo
Compila todos los archivos de C# del directorio actual:
csc *.cs
Compila todos los archivos de C# del directorio dir1\dir2 y todos sus subdirectorios, y genera dir2.dll:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/reference:[alias=]filename
/reference:filename
Argumentos
filename
Nombre de un archivo que contiene un manifiesto del ensamblado. Para importar más de un archivo, incluya una opción
/reference independiente para cada archivo.
alias
Un identificador de C# válido que representa al espacio de nombres raíz que contendrá todos los espacios de nombres del
ensamblado.
Comentarios
Para importar más de un archivo, incluya una opción /reference para cada archivo.
Los archivos que importe deben contener un manifiesto, y el archivo de resultados debe haberse compilado con una opción
/target (Especificar el formato del archivo de resultados) (Opciones del compilador de C#) que no sea
/target:module (Crear un módulo para agregarlo a un ensamblado) (Opciones del compilador de C#).
/r es la forma abreviada de /reference.
Utilice /addmodule (Importar metadatos) (Opciones del compilador de C#) para importar metadatos de un archivo de
resultados que no contenga un manifiesto de ensamblado.
Si hace referencia a un ensamblado (Ensamblado A) que, a su vez, hace referencia a otro ensamblado (Ensamblado B), también
deberá hacer referencia al ensamblado B si:
Un tipo utilizado en el Ensamblado A hereda de un tipo o implementa una interfaz del Ensamblado B.
Se invoca un campo, una propiedad, un evento o un método que devuelve un tipo o tiene un tipo de parámetro de
Ensamblado B.
Utilice /lib (Especificar ubicaciones de referencias de ensamblados) (Opciones del compilador de C#) para especificar el
directorio en el que se encuentran una o varias de las referencias de ensamblados. El tema /lib trata también sobre los
directorios donde el compilador busca ensamblados.
Para que el compilador reconozca un tipo en un ensamblado, y no en un módulo, debe obligársele a que resuelva el tipo, lo
que se puede conseguir definiendo una instancia del tipo. Existen otras formas de que el compilador resuelva nombres de
tipos en un ensamblado; por ejemplo, si hereda de un tipo de un ensamblado, el compilador reconocerá el nombre del tipo.
A veces, es necesario hacer referencia a dos versiones diferentes del mismo componente desde un solo ensamblado. Para ello,
utilice la subopción de alias en el modificador /reference para que cada archivo distinga entre los dos archivos. Dicho alias se
utilizará como calificador del nombre del componente y se resolverá como tal componente en uno de los archivos.
El archivo de respuesta csc.rsp, que hace referencia a los ensamblados utilizados comúnmente en .NET Framework, es el
predeterminado. Utilice /noconfig (Omitir csc.rsp) (Opciones del compilador de C#) si no desea que el compilador utilice
csc.rsp.
Para obtener más información, vea Agregar referencia (Cuadro de diálogo).
Ejemplo
En este ejemplo se muestra cómo utilizar la función alias externo (Referencia de C#).
Compile el archivo de código fuente e importe los metadatos de grid.dll y grid20.dll, que se compilaron anteriormente.
Los dos archivos DLL contienen versiones independientes del mismo componente y el usuario utiliza dos modificadores
/reference con opciones de alias para compilar el archivo de código fuente. Las opciones tienen la apariencia siguiente:
/reference:GridV1=grid.dll y /reference:GridV2=grid20.dll
Con ello se crean los alias externos "GridV1" y "GridV2" que podrá utilizar en su programa por medio de una instrucción
extern:
extern GridV1;
extern GridV2;
// Using statements go here.
Una vez hecho esto, puede hacer referencia al control de cuadrícula de grid.dll anteponiendo GridV1 al nombre de control, de
la siguiente forma:
GridV1::Grid
Además, puede hacer referencia al control de cuadrícula de grid20.dll anteponiendo GridV2 al nombre de control, de la
siguiente forma:
GridV2::Grid
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/resource:filename[,identifier[,accessibility-modifier]]
Argumentos
filename
Archivo de recursos de .NET Framework que se desea incrustar en el archivo de resultados de la compilación.
identifier (opcional)
Nombre lógico del recurso; nombre usado para cargar el recurso. El valor predeterminado es el nombre del archivo.
accessibility-modifier (opcional)
Accesibilidad del recurso: pública o privada. El valor predeterminado es que sea pública.
Comentarios
Se utiliza la opción /linkresource para vincular un recurso a un ensamblado y no incluir el archivo de recursos en el archivo de
resultados.
De forma predeterminada, los recursos son públicos en el ensamblado cuando se crean con el compilador de C#. Para que
sean privados, especifique el modificador de accesibilidad private. No se permite ninguna otra accesibilidad distinta de public
o private.
Si filename es un archivo de recursos de .NET Framework creado, por ejemplo, con Resgen.exe o en el entorno de desarrollo,
se puede tener acceso a él con miembros del espacio de nombres System.Resources (vea System.Resources.ResourceManager
para obtener más información). En todos los demás recursos, hay que utilizar los métodos GetManifestResource* en la clase
Assembly para tener acceso al recurso en tiempo de ejecución.
/res es la forma abreviada de /resource.
El orden de los recursos en el archivo de resultados se determina a partir del orden especificado en la línea de comandos.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Agregue un archivo de recursos al proyecto.
2. Seleccione el archivo que desea incrustar en el Explorador de soluciones.
3. Seleccione Acción de generación para ese archivo en la ventana Propiedades.
4. Establezca el valor de Acción de generación en Recurso incrustado.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea BuildAction.
Ejemplo
Para compilar in.cs y asociar el archivo de recursos rf.resource, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
El compilador sólo crea un manifiesto de ensamblado por compilación. En el manifiesto de ensamblado se incluye información
sobre todos los archivos que intervienen en una compilación. Todos los archivos resultantes, excepto los creados con
/target:module, pueden contener un manifiesto de ensamblado. Cuando se producen varios archivos de resultados en la
línea de comandos, sólo puede crearse un manifiesto de ensamblado y éste debe ir al primer archivo de resultados
especificado en la línea de comandos. Independientemente de cuál sea el primer archivo de resultados (/target:exe,
/target:winexe, /target:library o /target:module), cualquier otro archivo de resultados creado en la misma compilación
debe ser un módulo (/target:module).
Si crea un ensamblado, puede indicar que todo o parte del código sea compatible con CLS mediante el atributo CLSCompliant.
// target_clscompliant.cs
[assembly:System.CLSCompliant(true)] // specify assembly compliance
Para obtener más información sobre cómo establecer mediante programación esta opción del compilador, vea OutputType.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/target:exe
Comentarios
La opción /target:exeestá activada de manera predeterminada. El archivo ejecutable se creará con la extensión .exe.
Utilice /target:winexe para crear un programa ejecutable de Windows.
A menos que se especifique otra cosa con la opción /out, el archivo de resultados toma el nombre del archivo de entrada que
contiene el método Main.
Cuando se especifica en la línea de comandos, se utilizan todos los archivos hasta la siguiente opción /out o /target:module
para crear el archivo .exe.
Sólo se requiere un método Main en los archivos de código fuente que se compilan para producir un .exe. La opción /main del
compilador permite especificar la clase que contiene el método Main, en casos en los que el código tiene más de una clase con
un método Main.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Aplicación.
3. Modifique la propiedad Tipo de resultado.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea OutputType.
Ejemplo
Cada una de las siguientes líneas de comandos compilará in.cs y creará in.exe:
Vea también
Referencia
/target (Especificar el formato del archivo de resultados) (Opciones del compilador de C#)
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/target:library
Comentarios
Se creará el archivo DLL con la extensión .dll.
A menos que se especifique otra cosa con la opción /out, el archivo de resultados toma el nombre del primer archivo de
entrada.
Cuando se especifica en la línea de comandos, se utilizan todos los archivos hasta la siguiente opción /out o /target:module
para crear el archivo .dll.
Para generar un archivo .dll, no es necesario un método Main.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Aplicación.
3. Modifique la propiedad Tipo de resultado.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea OutputType.
Ejemplo
Compile in.cs, creando in.dll:
Vea también
Referencia
/target (Especificar el formato del archivo de resultados) (Opciones del compilador de C#)
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/target:module
Comentarios
De manera predeterminada, el archivo de resultados creado al compilar con esta opción tendrá la extensión .netmodule.
Common Language Runtime de .NET Framework no puede cargar un archivo sin manifiesto de ensamblado. No obstante,
puede incorporar ese archivo al manifiesto del ensamblado mediante /addmodule.
Si se crea más de un módulo en una sola compilación, los tipos internal de un módulo estarán disponibles para el resto de
módulos de la compilación. Cuando el código de un módulo hace referencia a los tipos internal de otro módulo, ambos
módulos deben incorporarse a un manifiesto de ensamblado mediante /addmodule.
El entorno de desarrollo de Visual Studio no permite la creación de módulos.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea OutputType.
Ejemplo
Compile in.cs, creando in.netmodule:
Vea también
Referencia
/target (Especificar el formato del archivo de resultados) (Opciones del compilador de C#)
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/target:winexe
Comentarios
El archivo ejecutable se creará con la extensión .exe. Los programas para Windows proporcionan una interfaz de usuario para
la biblioteca de .NET Framework o con las API Win32.
Utilice /target:exe para crear una aplicación de consola.
A menos que se especifique otra cosa con la opción /out, el archivo de resultados toma el nombre del archivo de entrada que
contiene el método Main.
Cuando se especifica en la línea de comandos, todos los archivos hasta la siguiente opción /out o /target se utilizan para crear
el programa de Windows.
Sólo se requiere un método Main en los archivos de código fuente que se compilan para producir un .exe. La opción /main
permite especificar la clase que contiene el método Main, en casos en los que el código tiene más de una clase con un método
Main.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Aplicación.
3. Modifique la propiedad Tipo de resultado.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea OutputType.
Ejemplo
Para compilar in.cs en un programa de Windows, ejecute:
Vea también
Referencia
/target (Especificar el formato del archivo de resultados) (Opciones del compilador de C#)
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/unsafe
Comentarios
Para obtener más información sobre el código no seguro, vea Código no seguro y punteros (Guía de programación de C#).
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Active la casilla de verificación Permitir código no seguro.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea AllowUnsafeBlocks.
Ejemplo
Para compilar in.cs en modo no seguro, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/utf8output
Comentarios
En algunas configuraciones internacionales, los resultados del compilador no se pueden mostrar correctamente en la consola.
En estas configuraciones, hay que utilizar /utf8output y redirigir los resultados del compilador a un archivo.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/warn:option
Argumentos
option
El nivel de advertencia que se desea mostrar para la compilación: los números más bajos muestran sólo las advertencias
muy graves; los números altos, más advertencias. Los valores válidos están comprendidos entre 0 y 4:
Nivel de advert Significado
encia
0 Desactiva la emisión de todos los mensajes de advertencia.
2 Muestra las advertencias de nivel 1 y también algunas otras menos graves, como las relativas a la ocultaci
ón de miembros de clase.
3 Muestra las advertencias de nivel 2 y también algunas otras menos graves, como las relativas a expresion
es que siempre se evalúan como true o false.
4 (valor predeter Muestra todas las advertencias de nivel 3 y también las informativas.
minado)
Comentarios
Para obtener información sobre un error o una advertencia, puede buscar su código en el índice de la Ayuda. Encontrará otras
formas de obtener información sobre errores o advertencias en Cómo: Buscar temas de Ayuda para los errores del compilador.
Si desea tratar todas las advertencias como errores, utilice /warnaserror. Utilice /nowarn para deshabilitar determinadas
advertencias.
/w es la forma abreviada de /warn.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Modifique la propiedad Nivel de advertencia.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea WarningLevel.
Ejemplo
Para compilar in.cs y hacer que el compilador sólo muestre las advertencias de nivel 1, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/warnaserror[<U>+</U> | -][:warning-list]
Comentarios
Los mensajes que, normalmente, se mostrarían como advertencias se muestran como errores y el proceso de generación se
detiene (no se generan archivos de resultados).
De manera predeterminada, está activada la opción /warnaserror-, que hace que las advertencias no impidan la generación de
un archivo de resultados. La opción /warnaserror, que equivale a /warnaserror+, hace que se traten las advertencias como
errores.
De manera optativa, si desea que sólo se traten como errores algunas advertencias concretas, puede especificar sus números
en una lista separada por comas.
Utilice /warn para especificar el nivel de advertencia que debe mostrar el compilador. Utilice /nowarn para deshabilitar
determinadas advertencias.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra la página Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Generar.
3. Modifique el valor de la propiedad Tratar advertencias como errores.
Para establecer esta opción del compilador mediante programación, vea TreatWarningsAsErrors.
Ejemplo
Para compilar in.cs y hacer que el compilador no muestre advertencias, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/win32icon:filename
Argumentos
filename
Archivo .ico que se desea agregar al archivo de resultados.
Comentarios
Los archivos .ico pueden crearse con el compilador de recursos. El compilador de recursos se invoca cuando se compila un
programa de Visual C++; se crea un archivo .ico a partir del archivo .rc.
Vea /linkresource (para hacer referencia a) o /resource (para asociar) un archivo de recursos de .NET Framework. Vea
/win32res para importar un archivo .res.
Para establecer esta opción del compilador en el entorno de desarrollo de Visual Studio
1. Abra las páginas Propiedades del proyecto. Para obtener información detallada, vea
Cómo: Especificar las propiedades del proyecto (C#, J#).
2. Haga clic en la página de propiedades Aplicación.
3. Modifique el valor de la propiedad Icono de aplicación.
Para obtener información sobre cómo establecer esta opción del compilador mediante programación, vea ApplicationIcon.
Ejemplo
Para compilar in.cs y asociar un archivo .ico rf.ico con el fin de generar in.exe, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
/win32res:filename
Argumentos
filename
Archivo de recursos que se desea agregar al archivo de resultados.
Comentarios
Los archivos de recursos Win32 se pueden crear con el compilador de recursos. El compilador de recursos se invoca cuando se
compila un programa de Visual C++; se crea un archivo .res a partir del archivo .rc.
Un recurso Win32 puede contener información de versión o un mapa de bits (icono) que ayudan a identificar la aplicación en
el Explorador de Windows. Si no se especifica la opción /win32res, el compilador generará información de versión basada en
la versión del ensamblado.
Vea /linkresource (para hacer referencia a) o /resource (para asociar) un archivo de recursos de .NET Framework.
Esta opción del compilador no está disponible en Visual Studio y no se puede cambiar mediante programación.
Ejemplo
Para compilar in.cs y asociar un archivo de recursos Win32 rf.res con el fin de generar in.exe, ejecute:
Vea también
Otros recursos
Opciones del compilador de C#
Referencia del lenguaje C#
Todos los errores del compilador de C# tienen temas correspondientes que explican por qué se genera un error, y en algunos
casos, cómo corregirlo. Para obtener ayuda sobre un mensaje de error concreto, pruebe una de las siguientes opciones:
Procedimiento
Para encontrar la ayuda de un error
Haga clic en el número de error en el Resultados (Ventana) y presione F1.
-O bien-
Escriba el número de error en el cuadro Buscar del Índice.
-O bien-
Escriba el número de error en la página Buscar.
Vea también
Otros recursos
Opciones del compilador de C#
Referencia de Visual C#: errores y advertencias
Vea también
Otros recursos
Opciones del compilador de C#
Referencia de Visual C#: errores y advertencias
El segundo crea un archivo DLL que define una clase C derivada de la clase B creada en el ejemplo anterior.
// CS0011_2.cs
// compile with: /target:library /reference:CS0011_1.dll
// post-build command: del /f CS0011_1.dll
public class C : Outer.B {}
El tercero reemplaza el archivo DLL creado por el primer paso y omite la definición de la clase interna B.
// CS0011_3.cs
// compile with: /target:library /out:cs0011_1.dll
public class Outer {}
Por último, el cuarto archivo hace referencia a la clase C definida en el segundo ejemplo, que se deriva de la clase B y que ya no
está.
El ejemplo siguiente genera el error CS0011.
// CS0011_4.cs
// compile with: /reference:CS0011_1.dll /reference:CS0011_2.dll
// CS0011 expected
class M
{
public static void Main()
{
C c = new C();
}
}
Vea también
Referencia
Agregar referencia (Cuadro de diálogo)
/reference (Importar metadatos) (Opciones del compilador de C#)
Referencia de Visual C#: errores y advertencias
// cs0012a.cs
// compile with: /target:library
public class A {}
A continuación:
// cs0012b.cs
// compile with: /target:library /reference:cs0012a.dll
public class B
{
public static A f()
{
return new A();
}
}
A continuación:
// cs0012c.cs
// compile with: /reference:cs0012b.dll
class C
{
public static void Main()
{
object o = B.f(); // CS0012
}
}
// CS0015.cs
namespace
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
{
namespace
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
{
namespace
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
{
public class
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC // CS0015
{
public static void Main()
{
}
}
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0017.cs
public class clx
{
static public void Main()
{
}
}
public class cly
{
public static void Main() // CS0017, delete one Main or use /main
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0019.cs
// compile with: /target:library
using System.Diagnostics;
public class MyClass
{
[ConditionalAttribute("DEBUG" || "TRACE")] // CS0019
public void TestMethod() {}
// OK
[ConditionalAttribute("DEBUG")]
public void TestMethod2() {}
}
Vea también
Referencia
Operadores (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0020.cs
namespace x
{
public class b
{
public static void Main()
{
1 / 0; // CS0020
}
}
}
Vea también
Referencia
Operadores (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CPP0021.cpp
// compile with: /clr /LD
using namespace System::Reflection;
// Uncomment the following line to resolve
//[DefaultMember("myItem")]
public ref class MyClassMC
{
public:
property int myItem[int]
{
int get(int i){ return 5; }
void set(int i, int value) {}
}
};
A continuación figura el archivo C# que llama al archivo .dll. Este archivo intenta tener acceso a la clase a través de un
indizador, pero se genera el error porque no se ha declarado ningún miembro como indizador predeterminado para su uso.
// CS0021.cs
// compile with: /reference:CPP0021.dll
public class MyClass
{
public static void Main()
{
MyClassMC myMC = new MyClassMC();
int j = myMC[1]; // CS0021
}
}
Referencia de Visual C#: errores y advertencias
// CS0022.cs
public class MyClass
{
public static void Main()
{
int[] a = new int[10];
a[0] = 0; // single-dimension array
a[0,1] = 9; // CS0022, the array does not have two dimensions
}
}
Referencia de Visual C#: errores y advertencias
// CS0023.cs
namespace x
{
public class a
{
public static void Main()
{
string s = "hello";
s = -s; // CS0023, minus operator not allowed on strings
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0026.cs
public class A
{
public static int i = 0;
public static void Main()
{
// CS0026
this.i = this.i + 1;
// Try the following line instead:
// i = i + 1;
}
}
Referencia de Visual C#: errores y advertencias
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication3
{
class MyClass
{
int i = 50;
long lng = 100;
i = lng;
i = lng; realiza una asignación, pero los tipos de datos de las variables a la izquierda y a la derecha del operador de
asignaciones no coinciden. Antes de realizar la asignación, el compilador convierte implícitamente la variable lng, que es de
tipo long, a int. Se realiza de forma implícita porque ningún código indicó explícitamente al compilador que realizara esta
conversión. El problema de este código es que se considera una conversión de restricción, y el compilador no permite
conversiones de restricción implícitas, porque podrían perderse datos.
Se produce una conversión de restricción cuando se realiza la conversión a un tipo de datos que ocupa menos espacio de
almacenamiento en la memoria que el tipo de datos desde el que se realiza la conversión. Por ejemplo, la conversión de long a
int sería considerada como una conversión de restricción. Un long ocupa 8 bytes de memoria, mientras que un int ocupa 4
bytes. Para ver cómo puede producirse una pérdida de datos, observe el siguiente ejemplo:
int i = 50;
long lng = 3147483647;
i = lng;
La variable lng contiene ahora un valor que no se puede almacenar en la variable i porque es demasiado grande. Si
tuviéramos que convertir este valor a un tipo int, perderíamos parte de los datos y el valor convertido no sería el mismo que el
valor antes de la conversión.
Una conversión de ampliación sería lo contrario que una conversión de restricción. En las conversiones de ampliación, se
realiza la conversión a un tipo de datos que ocupa más espacio en la memoria que el tipo de datos desde el que se realiza la
conversión. He aquí un ejemplo de una conversión de ampliación:
int i = 50;
long lng = 100;
lng = i;
Observe la diferencia que existe entre este ejemplo de código y el primero. En esta ocasión, la variable lng se encuentra a la
izquierda del operador de asignaciones, por lo que es el destino de la asignación. Antes de que pueda realizarse el trabajo, el
compilador debe convertir implícitamente la variable i, que es de tipo int, al tipo long. Se trata de una conversión de
ampliación, puesto que se convierte de un tipo que ocupa 4 bytes de memoria (int) a un tipo que ocupa 8 bytes de memoria
(long). Las conversiones de ampliación implícitas están permitidas porque no existe riesgo de pérdida de datos. Cualquier valor
que se pueda almacenar en un tipo int también se puede almacenar en un tipo long.
Sabemos que las conversiones de restricción implícitas no están permitidas, de modo que para compilar este código debemos
convertir de forma explícita el tipo de datos. Las conversiones explícitas se realizan mediante conversiones de tipo. En C# se
entiende por conversión la conversión de un tipo de datos a otro. Para obtener el código que se debe compilar debemos
utilizar la siguiente sintaxis:
int i = 50;
long lng = 100;
i = (int) lng; // cast to int
Con la tercera línea de código se le indica al compilador que, antes de que se realice la asignación, convierta explícitamente a
int la variable lng, que es de tipo long. No olvide que con una conversión de restricción se pueden perder datos. Las
conversiones de restricción deben utilizarse con precaución y, aunque se realizará la compilación del código, podrían
producirse resultados inesperados en tiempo de ejecución.
Esto sólo hace referencia a los tipos de valores. Cuando se trabaja con tipos de valores, se hace directamente con los datos
almacenados en la variable. Sin embargo, .NET Framework también tiene tipos de referencia. Cuando se trabaja con tipos de
referencia, se hace con una referencia a una variable, no con los datos reales. Son ejemplos de tipos de referencia las clases, las
interfaces y las matrices. No es posible convertir implícita o explícitamente un tipo de referencia en otro, a no ser que el
compilador permita la conversión específica o bien que los operadores de conversión necesarios estén implementados.
El código siguiente genera el error CS0029:
// CS0029.cs
public class MyInt
{
private int x = 0;
Vea también
Conceptos
Operadores de conversión (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0030.cs
namespace x
{
public class iii
{
/*
public static implicit operator iii(int aa)
{
return null;
}
// CS0031.cs
namespace x
{
public class a
{
public static void Main()
{
byte i = 512; // CS0031, 512 cannot fit in byte
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0034.cs
public class A
{
// allows for the conversion of A object to int
public static implicit operator int (A s)
{
return 0;
}
public class B
{
public static implicit operator int (B s)
// one way to resolve this CS0034 is to make one conversion explicit
// public static explicit operator int (B s)
{
return 0;
}
public class C
{
public static void Main ()
{
A a = new A();
B b = new B();
b = b + a; // CS0034
// another way to resolve this CS0034 is to make a cast
// b = b + (int)a;
}
}
Referencia de Visual C#: errores y advertencias
// CS0035.cs
class MyClass
{
private int i;
public MyClass(int i)
{
this.i = i;
}
class MyClass2
{
static void Main()
{
MyClass x = new MyClass(7);
object o = - x; // CS0035
// try a cast:
// object o = - (double)x;
}
}
Referencia de Visual C#: errores y advertencias
// CS0036.cs
using System;
using System.Runtime.InteropServices;
// CS0037.cs
public struct s
{
}
class a
{
public static void Main()
{
int i = null; // CS0037
s ss = null; // CS0037
}
}
Referencia de Visual C#: errores y advertencias
// CS0038.cs
class OuterClass
{
public int count;
// try the following line instead
// public static int count;
class InnerClass
{
void func()
{
// or, create an instance
// OuterClass class_inst = new OuterClass();
// int count2 = class_inst.count;
int count2 = count; // CS0038
}
}
// CS0039.cs
using System;
class A
{
}
class B: A
{
}
class C: A
{
}
class M
{
static void Main()
{
A a = new C();
B b = new B();
C c;
// CS0050.cs
class MyClass //accessibility defaults to private
// try the following line instead
// public class MyClass
{
}
// CS0051.cs
public class A
{
// Try making B public since F is public
// B is implicitly private here
class B
{
}
// CS0052.cs
class MyClass
// try the following line instead
// public class MyClass
{
}
Vea también
Referencia
Palabras clave de C#
Modificadores de acceso (Referencia de C#)
Niveles de accesibilidad (Referencia de C#)
Modificadores (Referencia de C#)
Referencia de Visual C#: errores y advertencias
// CS0053.cs
class MyClass //defaults to private accessibility
// try the following line instead
// public class MyClass
{
}
public class MyClass2
{
public MyClass myProperty // CS0053
{
get
{
return new MyClass();
}
set
{
}
}
}
// CS0054.cs
class MyClass
// try the following line instead
// public class MyClass
{
}
public class MyClass3
{
public MyClass this[int i] // CS0054
{
get
{
return new MyClass();
}
}
}
// CS0055.cs
class MyClass //defaults to private accessibility
// try the following line instead
// public class MyClass
{
}
public class MyClass2
{
public int this[MyClass myClass] // CS0055
{
get
{
return 0;
}
}
}
// CS0056.cs
class MyClass
// try the following line instead
// public class MyClass
{
}
public class A
{
public static implicit operator MyClass(A a) // CS0056
{
return new MyClass();
}
// CS0057.cs
class MyClass //defaults to private accessibility
// try the following line instead
// public class MyClass
{
}
public class MyClass2
{
public static implicit operator MyClass2(MyClass iii) // CS0057
{
return new MyClass2();
}
// CS0058.cs
class MyClass
// try the following line instead
// public class MyClass
{
}
public class A
{
public static void Main()
{
}
}
Vea también
Referencia
private (Referencia de C#)
Referencia de Visual C#: errores y advertencias
// CS0059.cs
class MyClass //defaults to private accessibility
// try the following line instead
// public class MyClass
{
}
public delegate void MyClassDel( MyClass myClass); // CS0059
// CS0060.cs
class MyClass
// try the following line instead
// public class MyClass
{
}
Vea también
Referencia
Modificadores de acceso (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0061.cs
// compile with: /target:library
internal interface A {}
public interface AA : A {} // CS0061
// OK
public interface B {}
internal interface BB : B {}
internal interface C {}
internal interface CC : C {}
Referencia de Visual C#: errores y advertencias
// CS0065.cs
using System;
public delegate void Eventhandler(object sender, int e);
public class MyClass
{
public event EventHandler Click // CS0065,
{
// to fix, uncomment the add and remove definitions
/*
add
{
Click += value;
}
remove
{
Click -= value;
}
*/
}
Vea también
Conceptos
Eventos (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0066.cs
using System;
public class a
{
public event EventHandler Click; // CS0066
// CS0068.cs
interface I
{
event MyDelegate d = new MyDelegate(M.f); // CS0068
// try the following line instead
// event MyDelegate d2;
}
class M
{
event MyDelegate d = new MyDelegate(M.f);
// CS0069.cs
// compile with: /target:library
public interface a
{
event EventHandler Click { remove {} } // CS0069
event EventHandler Click2; // OK
}
Referencia de Visual C#: errores y advertencias
// CS0070.cs
using System;
public delegate void EventHandler();
public class A
{
public event EventHandler Click;
public class B
{
public int Foo ()
{
EventHandler eh = new EventHandler(A.OnClick);
A a = new A();
eh = a.Click; // CS0070
// try the following line instead
// a.Click += eh;
return 1;
}
}
Referencia de Visual C#: errores y advertencias
// CS0071.cs
public delegate void MyEvent(object sender);
interface ITest
{
event MyEvent Clicked;
}
// CS0072.cs
delegate void MyDelegate();
class Test1
{
public virtual event MyDelegate MyEvent;
public virtual void VMeth()
{
}
// CS0073.cs
delegate void del();
class Test
{
public event del MyEvent
{
add; // CS0073
// try the following lines instead
// add
// {
// MyEvent += value;
// }
remove
{
MyEvent -= value;
}
// CS0074.cs
delegate void D();
// CS0075
namespace MyNamespace
{
enum MyEnum { }
public class MyClass
{
public static void Main()
{
// To fix the error, place the negative
// values below in parentheses
int i = (System.Int32) - 4; //CS0075
MyEnum e = (MyEnum) - 1; //CS0075
System.Console.WriteLine(i); //to avoid warning
System.Console.WriteLine(e); //to avoid warning
}
}
}
Vea también
Referencia
Conversión (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0077.cs
using System;
class C
{
}
struct S
{
}
class M
{
public static void Main()
{
object o1, o2;
C c;
S s;
o1 = new C();
o2 = new S();
// CS0079.cs
using System;
namespace MyNamespace
{
public class MyClass where MyClass : System.IDisposable // CS0080 //the following li
ne shows an example of correct syntax
//public class MyClass<T> where T : System.IDisposable
{
public void Foo() where Foo : new() // CS0080
//the following line shows an example of correct syntax
//public void Foo<U>() where U : struct
{
}
}
// CS0081.cs
class MyClass
{
public void F<int>() {} // CS0081
public void F<T>(T input) {} // OK
Vea también
Conceptos
Genéricos (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0100.cs
namespace x
{
public class a
{
public static void f(int i, char i) // CS0100
// try the following line instead
// public static void f(int i, char j)
{
}
// CS0101.cs
namespace MyNamespace
{
public class MyClass
{
static public void Main()
{
}
}
// CS0102.cs
// compile with: /target:library
namespace MyApp
{
public class MyClass
{
string s = "Hello";
string s = "Goodbye"; // CS0102
// CS0103.cs
using System;
class MyClass
{
public static void Main()
{
// MyClass conn = null;
try
{
MyClass conn = new MyClass(); // delete this line
// and uncomment the following line and the line above the try
// conn = new MyClass();
}
catch(Exception e)
{
if (conn != null) // CS0103
Console.WriteLine("{0}", e);
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0104.cs
using x;
using y;
namespace x
{
public class Test
{
}
}
namespace y
{
public class Test
{
}
}
public class a
{
public static void Main()
{
Test test = new Test(); // CS0104, is Test in x or y namespace?
// try the following line instead
// y.Test test = new y.Test();
}
}
Referencia de Visual C#: errores y advertencias
// CS0106.cs
namespace MyNamespace
{
interface I
{
void m();
static public void f(); // CS0106
}
// CS0107.cs
public class C
{
private internal void f() // CS0107, delete private or internal
{
}
public static int Main()
{
return 1;
}
}
Referencia de Visual C#: errores y advertencias
// CS0110.cs
namespace MyNamespace
{
public class A
{
public static void Main()
{
}
}
public class B : A
{
public const int i = c + 1; // CS0110, c already references i
public const int c = i + 1;
// the following line would be OK
// public const int c = 10;
}
}
Vea también
Referencia
Constantes (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0111.cs
class A
{
void Test() { }
public static void Test(){} // CS0111
// CS0112.cs
namespace MyNamespace
{
abstract public class MyClass
{
public abstract void Foo();
}
public class MyClass2 : MyClass
{
override public static void Foo() // CS0112, remove static keyword
{
}
public static int Main()
{
return 0;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0113.cs
namespace MyNamespace
{
abstract public class MyClass
{
public abstract void Foo();
}
// CS0115.cs
namespace MyNamespace
{
abstract public class MyClass1
{
public abstract int f();
}
// CS0116.cs
namespace x
{
using System;
// method must be in class/struct
void Method(string str) // CS0116
{
Console.WriteLine(str);
}
}
Referencia de Visual C#: errores y advertencias
// CS0117_1.cs
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
int i;
i = i.get(); // CS0117
}
}
}
Ejemplo
En este ejemplo, se utiliza la propiedad Item con un indizador. En C#, se puede utilizar una propiedad o un indizador para
tener acceso a un miembro, pero no ambos. El código siguiente genera el error CS0117.
// CS0117_2.cs
using System;
using System.Collections;
class Test
{
public static void Main()
{
ArrayList al = new ArrayList();
al.Add( new Test() );
Console.WriteLine("{0}", al.Item[0]); // CS0117
Console.WriteLine("{0}", al[0]); // OK
}
}
El error CS0017 también se produce cuando se utiliza una biblioteca escrita un lenguaje que admite miembros estáticos en las
interfaces y se intenta tener acceso al miembro estático desde C#.
// CS0117_3.jsl
// compile with: /target:library
public interface IMyJSharpInterface
{
static int MyStaticMember = 0;
void NonStaticMember();
}
El código siguiente genera el error CS0117.
// CS0117_4.cs
// compile with: /reference:CS0117_3.dll
class MyCSharpClass : IMyJSharpInterface
{
public void NonStaticMember() {}
public static void Main()
{
IMyJSharpInterface myObj = new MyCSharpClass();
myObj.NonStaticMember();
int i = myObj.MyStaticMember; // CS0117
}
}
Referencia de Visual C#: errores y advertencias
// CS0118.cs
// compile with: /target:library
namespace MyNamespace
{
class MyClass
{
// MyNamespace not a class
MyNamespace ix = new MyNamespace (); // CS0118
}
}
Referencia de Visual C#: errores y advertencias
// CS0119.cs
using System;
public class MyClass
{
public static void Test() {}
// CS0120_1.cs
public class MyClass
{
// Non-static field
public int i;
// Non-static method
public void f(){}
// Non-static property
int Prop
{
get
{
return 1;
}
}
También se generará el error CS0120 si hay una llamada a un método no estático desde un método estático de la siguiente
manera:
// CS0120_2.cs
// CS0120 expected
using System;
// CS0120_3.cs
using System;
// CS0121.cs
public class C
{
void f(int i, double d)
{
}
// CS0122.cs
public class MyClass
{
// Make public to resolve CS0122
void Foo()
{
}
}
// CS0123.cs
delegate void D();
delegate void D2(int i);
public class C
{
public static void f(int i) {}
// CS0126.cs
public class a
{
public int i
{
set
{
}
get
{
return; // CS0126, specify a value to return
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0127.cs
namespace MyNamespace
{
public class MyClass
{
public int hiddenMember2
{
get
{
return 0;
}
set // CS0127, set has an implicit void return type
{
return 0; // remove return statement to resolve this CS0127
}
}
// CS0128.cs
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
char i;
int i; // CS0128
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0131.cs
public class MyClass
{
public int i = 0;
public void MyMethod()
{
i++ = 1; // CS0131
// try the following line instead
// i = 1;
}
public static void Main() { }
}
Este error también se puede producir al intentar realizar operaciones aritméticas en la parte izquierda de un operador de
asignación, como en el siguiente ejemplo.
// CS0131b.cs
public class C
{
public static int Main()
{
int a = 1, b = 2, c = 3;
if (a + b = c) // CS0131
// try this instead
// if (a + b == c)
return 0;
return 1;
}
}
Referencia de Visual C#: errores y advertencias
// CS0132.cs
namespace MyNamespace
{
public class MyClass
{
public MyClass(int i)
{
}
}
// CS0133.cs
public class MyClass
{
public const int i = c; // CS0133, c is not constant
public static int c = i;
// try the following line instead
// public const int i = 6;
// CS0134.cs
// compile with: /target:library
class MyTest {}
class MyClass
{
const MyTest test = new MyTest(); // CS0134
//OK
const MyTest test2 = null;
const System.String test3 = "test";
}
Referencia de Visual C#: errores y advertencias
// CS0135.cs
public class MyClass2
{
public static int i = 0;
// CS0136.cs
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
int i = 0;
{
char i = 'a'; // CS0136, hides int i
}
i++;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0138.cs
using System.Object; // CS0138
Referencia de Visual C#: errores y advertencias
// CS0139.cs
namespace x
{
public class a
{
public static void Main()
{
continue; // CS0139
break; // CS0139
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0140.cs
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
label1: int i = 0;
label1: int j = 0; // CS0140, comment this line to resolve
goto label1;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0143.cs
class MyClass
{
static public void Main ()
{
double d = new double(4.5); // CS0143
}
}
Referencia de Visual C#: errores y advertencias
// CS0144.cs
interface MyInterface
{
}
public class MyClass
{
public static void Main()
{
MyInterface myInterface = new MyInterface (); // CS0144
}
}
Referencia de Visual C#: errores y advertencias
// CS0145.cs
class MyClass
{
const int i; // CS0145
// try the following line instead
// const int i = 0;
// CS0146.cs
namespace MyNamespace
{
public interface InterfaceA
{
}
public class MyClass : InterfaceA, MyClass2
{
public void Main()
{
}
}
// CS0149.cs
using System;
class MyClass
{
// class member-field of the declared delegate type
static MyDelegate dt;
// CS0150.cs
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
int i = 0;
int j = 0;
switch(i)
{
case j: // CS0150, j is a variable int, not a constant int
// try the following line instead
// case 1:
}
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0151.cs
public class MyClass
{
public static implicit operator int (MyClass aa)
{
return 0;
}
// CS0152.cs
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
int i = 0;
switch (i)
{
case 1:
i++;
return;
// CS0153.cs
public class a
{
public static void Main()
{
goto case 5; // CS0153
}
}
Referencia de Visual C#: errores y advertencias
// CS0154.cs
public class MyClass2
{
public int i
{
set
{
}
// uncomment the get method to resolve this error
/*
get
{
return 0;
}
*/
}
}
// CS0155.cs
using System;
namespace MyNamespace
{
public class MyClass2
// try the following line instead
// public class MyClass2 : Exception
{
}
public class MyClass
{
public static void Main()
{
try
{
}
catch (MyClass2) // CS0155, resolves if you derive MyClass2 from Exception
{
}
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0156.cs
using System;
namespace MyNamespace
{
public class MyClass2 : Exception
{
}
catch(MyClass2)
{
throw; // this throw is valid
}
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0157.cs
using System;
namespace MyNamespace
{
public class MyClass2 : Exception
{
}
finally
{
return; // CS0157, cannot leave finally clause
}
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0158.cs
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
goto lab1;
lab1:
{
lab1:
goto lab1; // CS0158
}
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0159.cs
public class Class1
{
public static void Main()
{
int i = 0;
switch (i)
{
case 1:
goto case 3; // CS0159, case 3 label does not exist
case 2:
break;
}
goto NOWHERE; // CS0159, NOWHERE label does not exist
}
}
Referencia de Visual C#: errores y advertencias
// CS0160.cs
public class MyClass2 : System.Exception {}
public class MyClass
{
public static void Main()
{
try {}
// CS0161.cs
public class Test
{
public static int Main() // CS0161
{
int i = 10;
if (i < 10)
{
return i;
}
else
{
// uncomment the following line to resolve
// return 1;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0163.cs
public class MyClass
{
public static void Main()
{
int i = 0;
case 2:
i++;
return;
case 3:
i = 0;
return;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0165.cs
using System;
class MyClass
{
public int i;
}
class MyClass2
{
public static void Main(string [] args)
{
int i, j;
if (args[0] == "test")
{
i = 0;
}
/*
// to resolve, either initialize the variables when declared
// or provide for logic to initialize them, as follows:
else
{
i = 1;
}
*/
j = i; // CS0165, i might be uninitialized
MyClass myClass;
myClass.i = 0; // CS0165
// use new as follows
// MyClass myClass = new MyClass();
// myClass.i = 0;
}
}
Referencia de Visual C#: errores y advertencias
// CS0170.cs
public struct error
{
public int i;
}
// CS0171.cs
struct MyStruct
{
MyStruct(int initField) // CS0171
{
// i = initField; // uncomment this line to resolve this error
}
public int i;
}
class MyClass
{
public static void Main()
{
MyStruct aStruct = new MyStruct();
}
}
Referencia de Visual C#: errores y advertencias
// CS0172.cs
public class Square
{
public class Circle
{
public static implicit operator Circle(Square aa)
{
return null;
}
// CS0173.cs
public class C {}
public class A {}
public class MyClass
{
public static void F(bool b)
{
A a = new A();
C c = new C();
object o = b ? a : c; // CS0173
}
// CS0175.cs
using System;
class BaseClass
{
public int TestInt = 0;
}
class MyClass : BaseClass
{
public static void Main()
{
MyClass aClass = new MyClass();
aClass.BaseTest();
}
// CS0176.cs
public class MyClass2
{
public static int ii;
}
public class a
{
public static void Main()
{
MyClass2 myClass2 = new MyClass2 ();
int i = myClass2.ii; // CS0176
// try the following line instead
// int i = MyClass2.ii;
}
}
Referencia de Visual C#: errores y advertencias
// CS0177.cs
public class MyClass
{
public static void Foo(out int i) // CS0177
{
// uncomment the following line to resolve this error
// i = 0;
}
// CS0178.cs
class MyClass
{
public static void Main()
{
int a = new int[5][,][][5; // CS0178
int[,] b = new int[3,2]; // OK
// CS0179.cs
public class MyClass
{
public extern int ExternMethod(int aa) // CS0179
{
return 0;
}
// try the following line instead
// public extern int ExternMethod(int aa);
// CS0180.cs
namespace MyNamespace
{
public class MyClass
{
public extern abstract int Foo(int a); // CS0180
// CS0182.cs
public class MyClass
{
static string s = "Test";
[System.Diagnostics.ConditionalAttribute(s)] // CS0182
// try the following line instead
// [System.Diagnostics.ConditionalAttribute("Test")]
void NonConstantArgumentToConditional()
{
}
// CS0185.cs
public class MainClass
{
public static void Main ()
{
lock (1) // CS0185
// try the following lines instead
// MainClass x = new MainClass();
// lock(x)
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0186.cs
using System;
using System.Collections;
class MyClass
{
static void Main()
{
// Each of the following lines generates CS0186:
foreach (int i in null) {} // CS0186
foreach (int i in (IEnumerable) null) { }; // CS0186
}
}
Referencia de Visual C#: errores y advertencias
// CS0188.cs
// compile with: /t:library
namespace MyNamespace
{
class MyClass
{
struct S
{
public int a;
void Foo()
{
}
S(int i)
{
// a = i;
Foo(); // CS0188
}
}
public static void Main()
{ }
}
}
Referencia de Visual C#: errores y advertencias
// CS0191.cs
class MyClass
{
public readonly int TestInt = 6; // OK to assign to readonly field in declaration
MyClass()
{
TestInt = 11; // OK to assign to readonly field in constructor
}
// CS0192.cs
class MyClass
{
public readonly int TestInt = 6;
static void TestMethod(ref int testInt)
{
testInt = 0;
}
MyClass()
{
TestMethod(ref TestInt); // OK
}
// CS0193.cs
using System;
// CS0196.cs
public class MyClass
{
public static void Main ()
{
int *i = null;
int j = 0;
j = i[1,2]; // CS0196
// try the following line instead
// j = i[1];
}
}
Referencia de Visual C#: errores y advertencias
// CS0197.cs
// compile with: /W:1
class X : System.MarshalByRefObject
{
public int i;
}
class M
{
public int i;
static void AddSeventeen(ref int i)
{
i += 17;
}
// OK
M m = new M();
m.i = 12;
AddSeventeen(ref m.i);
}
}
Referencia de Visual C#: errores y advertencias
// CS0198.cs
class MyClass
{
public static readonly int TestInt = 6;
MyClass()
{
TestInt = 11; // CS0198, constructor is not static and readonly field is
}
// CS0199.cs
class MyClass
{
public static readonly int TestInt = 6;
static void TestMethod(ref int testInt)
{
testInt = 0;
}
MyClass()
{
TestMethod(ref TestInt); // CS0199, TestInt is static
}
// CS0200.cs
public class MainClass
{
// private int _mi;
int I
{
get
{
return 1;
}
// CS0201.cs
public class MainClass
{
public static void Main()
{
2 * 3; // CS0201
}
}
// CS0201_b.cs
// compile with: /target:library
public class MyList<T>
{
public void Add(T x)
{
int i = 0;
if ( (object)x == null)
{
checked(i++); // CS0201
// OK
checked {
i++;
}
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0202.cs
public class C1
{
public int Current
{
get
{
return 0;
}
}
public class C2
{
public int Current
{
get
{
return 0;
}
}
public bool MoveNext ()
{
return false;
}
public C1[] GetEnumerator ()
// try the following line instead
// public C1 GetEnumerator ()
{
return null;
}
}
public class MainClass
{
public static void Main ()
{
C2 c2 = new C2();
// CS0205.cs
abstract public class MyClass
{
abstract public void mf();
}
// CS0206.cs
public class MyClass
{
public static int P
{
get
{
return 0;
}
set
{
}
}
// CS0208.cs
// compile with: /unsafe
class S
{
public int a = 98;
}
// CS0209.cs
// compile with: /unsafe
class Point
{
public int x, y;
}
// CS0210a.cs
// compile with: /unsafe
class Point
{
public int x, y;
}
El siguiente ejemplo también genera el error CS0210 porque la instrucción using no tiene inicializador.
// CS0210b.cs
using System.IO;
class Test
{
static void Main()
{
using (StreamWriter w) // CS0210
// Try this line instead:
// using (StreamWriter w = new StreamWriter("TestFile.txt"))
{
w.WriteLine("Hello there");
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0211.cs
// compile with: /unsafe
// CS0212a.cs
// compile with: /unsafe /target:library
public class A {
public int iField = 5;
// OK
unsafe public void mf2() {
A a = new A();
fixed (int* ptr = &a.iField) {}
}
}
El ejemplo siguiente también genera el error CS0212 y muestra una manera de resolverlo:
// CS0212b.cs
// compile with: /unsafe /target:library
using System;
// CS0213.cs
// compile with: /unsafe
public class MyClass
{
unsafe public static void Main()
{
int i = 45;
fixed (int *j = &i) { } // CS0213
// try the following line instead
// int* j = &i;
// CS0214.cs
// compile with: /target:library /unsafe
public struct S
{
public int a;
}
public class MyClass
{
public static void Test()
{
S s = new S();
S * s2 = &s; // CS0214
s2->a = 3; // CS0214
s.a = 0;
}
// OK
unsafe public static void Test2()
{
S s = new S();
S * s2 = &s;
s2->a = 3;
s.a = 0;
}
}
Referencia de Visual C#: errores y advertencias
// CS0215.cs
class MyClass
{
public static int operator true (MyClass MyInt) // CS0215
// try the following line instead
// public static bool operator true (MyClass MyInt)
{
return true;
}
// CS0216.cs
class MyClass
{
public static bool operator true (MyClass MyInt) // CS0216
{
return true;
}
// CS0217.cs
using System;
public static int operator & (MyClass f1, MyClass f2) // CS0217
// try the following line instead
// public static MyClass operator & (MyClass f1, MyClass f2)
{
return new MyClass();
}
public static void Main()
{
MyClass f = new MyClass();
int i = f && f;
}
}
Vea también
Referencia
Operadores sobrecargables (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0218.cs
using System;
public class MyClass
{
// uncomment these operator declarations to resolve this CS0218
/*
public static bool operator true (MyClass f)
{
return false;
}
Vea también
Conceptos
Operadores de conversión (Guía de programación de C#)
Referencia de Visual C#: errores y advertencias
// CS0220.cs
using System;
class TestClass
{
const int x = 1000000;
const int y = 1000000;
// CS0221.cs
public class MyClass
{
public static void Main()
{
// unchecked
// {
int a = (int)0xFFFFFFFF; // CS0221
a++;
// }
}
}
Referencia de Visual C#: errores y advertencias
// CS0225.cs
public class MyClass
{
public static void TestParams(params int a) // CS0225
// try the following line instead
// public static void TestParams(params int[] a)
{
}
// CS0227.cs
public class MyClass
{
unsafe public static void Main() // CS0227
{
}
}
Referencia de Visual C#: errores y advertencias
Ejemplo
En el código siguiente se genera el error CS0229:
// CS0229.cs
interface IList
{
int Count
{
get;
set;
}
void Counter();
}
interface Icounter
{
double Count
{
get;
set;
}
}
// CS0230.cs
using System;
class MyClass
{
public static void Main()
{
int[] myarray = new int[3] {1,2,3};
// CS0231.cs
class Test
{
public void TestMethod(params int[] p, int i) {} // CS0231
// To resolve the error, use the following line instead:
// public void TestMethod(int i, params int[] p) {}
static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0233.cs
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct S
{
public int a;
}
// CS0234.cs
public class C
{
public static void Main()
{
System.DateTime x = new System.DateTim(); // CS0234
// try the following line instead
// System.DateTime x = new System.DateTime();
}
}
Referencia de Visual C#: errores y advertencias
// CS0236.cs
public class MyClass
{
public int i = 5;
public int j = i; // CS0236
public int k; // initialize in constructor
MyClass()
{
k = i;
}
// CS0238.cs
abstract class MyClass
{
public abstract void f();
}
// CS0239.cs
abstract class MyClass
{
public abstract void f();
}
// CS0241.cs
public class A
{
public void Test(int i = 9) {} // CS0241
}
public class B
{
public void Test() { Test(9); }
public void Test(int i) {}
}
public class C
{
public static void Main()
{
B x = new B();
x.Test();
}
}
Referencia de Visual C#: errores y advertencias
// CS0242.cs
// compile with: /unsafe
class TestClass
{
public unsafe void Test()
{
void * p = null;
p++; // CS0242, incrementing a void pointer not allowed
}
// CS0243.cs
// compile with: /target:library
public class MyClass
{
public virtual void M() {}
}
// CS0244.cs
// compile with: /unsafe
class UnsafeTest
{
unsafe static void SquarePtrParam (int* p)
{
bool b = p is object; // CS0244 p is pointer
}
// CS0245.cs
using System;
using System.Collections;
void m()
{
this.Finalize(); // CS0245
// this.Dispose();
}
// CS0246.cs
// using System.Diagnostics;
A continuación se muestra un ejemplo en que se ha utilizado un objeto de tipo Type en un punto donde se esperaba un tipo
real (caso 4 anterior):
// CS0246b.cs
using System;
class C
{
public bool supports(object o, Type t)
{
if (o is t) // CS0246 – t is not a type
{
return true;
}
return false;
}
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0247.cs
// compile with: /unsafe
public class MyClass
{
unsafe public static void Main()
{
int *p = stackalloc int [-30]; // CS0247
}
}
Referencia de Visual C#: errores y advertencias
// CS0248.cs
class MyClass
{
public static void Main()
{
int[] myArray = new int[-3] {1,2,3}; // CS0248, pass a nonnegative number
}
}
Referencia de Visual C#: errores y advertencias
// CS0249.cs
class MyClass
{
protected override void Finalize() // CS0249
// try the following line instead
// ~MyClass()
{
}
// CS0250.cs
class B
{
}
class C : B
{
~C()
{
base.Finalize(); // CS0250
}
// CS0254.cs
// compile with: /unsafe
class Point
{
public uint x, y;
}
class FixedTest
{
unsafe static void SquarePtrParam (int* p)
{
*p *= *p;
}
// CS0255.cs
// compile with: /unsafe
using System;
try
{
// Conversion is not valid; o contains a string not an int
i = (int) o;
}
finally
{
Console.Write("i = {0}", i);
int* fib = stackalloc int[100]; // CS0255
}
}
// CS0260.cs
class C // CS0260
{
}
partial class C
{
}
Referencia de Visual C#: errores y advertencias
// CS0261.cs
partial class A // CS0261 – A declared as a class here, but as a struct below
{
}
partial struct A
{
}
Referencia de Visual C#: errores y advertencias
// CS0262.cs
class A
{
public partial class C // CS0262
{
}
private partial class C
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0263.cs
// compile with: /target:library
class B1
{
}
class B2
{
}
partial class C : B1 // CS0263 – is the base class B1 or B2?
{
}
partial class C : B2
{
}
Referencia de Visual C#: errores y advertencias
// CS0264.cs
// CS0265.cs
public class GenericsErrors
{
interface IFace1 { }
interface IFace2 { }
partial class PartialBadBounds<T> where T : IFace1 { } // CS0265
partial class PartialBadBounds<T> where T : IFace2 { }
}
Referencia de Visual C#: errores y advertencias
// CS0266.cs
class MyClass
{
public static void Main()
{
object obj = "MyString";
// Cannot implicitly convert 'object' to 'MyClass'
MyClass myClass = obj; // CS0266
// Try this line instead
// MyClass c = ( MyClass )obj;
}
}
Referencia de Visual C#: errores y advertencias
// CS0267.cs
public partial class MyClass
{
public MyClass()
{
}
}
// CS0269.cs
class C
{
public static void F(out int i)
// Try this instead:
// public static void F(ref int i)
{
int k = i; // CS0269
i = 1;
}
También se puede producir si la inicialización de una variable tiene lugar en un bloque try y el compilador no puede
comprobar si éste se ejecutará de forma correcta:
// CS0269b.cs
class C
{
public static void F(out int i)
{
try
{
// Assignment occurs, but compiler can't verify it
i = 1;
}
catch
{
}
int k = i; // CS0269
i = 1;
}
// CS0270.cs
// compile with: /t:module
// CS0271.cs
public class MyClass
{
public int Property
{
private get { return 0; }
set { }
}
// CS0272.cs
public class MyClass
{
public int Property
{
get { return 0; }
private set { }
}
}
// CS0273.cs
// compile with: /target:library
public class MyClass
{
internal int Property
{
get { return 0; }
internal set {} // CS0273
// try the following line instead
// private set {}
}
}
Referencia de Visual C#: errores y advertencias
// CS0274.cs
public class MyClass
{
public int Property // CS0274
{
public get { return 0; }
protected set { }
}
}
Referencia de Visual C#: errores y advertencias
// CS0275.cs
public interface MyInterface
{
int Property
{
get;
internal set; // CS0275
}
}
Referencia de Visual C#: errores y advertencias
// CS0276.cs
public class MyClass
{
public int Property
{
protected set { } // CS0276
}
public int Property2
{
internal get { } // CS0276
}
}
Referencia de Visual C#: errores y advertencias
// CS0277.cs
public interface MyInterface
{
int Property
{
get;
set;
}
}
// CS0281.cs
// compile with: /target:library /keyfile:CS0281.snk
public class A {}
// CS0281_b.cs
// compile with: /target:library /keyfile:CS0281.snk /reference:CS0281.dll
[assembly:System.Runtime.CompilerServices.InternalsVisibleTo("CS0281 , PublicKey=0024000004
8000009400000006020000002400005253413100040000010001004b2d4d56af7c50be2fcbbf97cb880b9e73ad8
4467a587191fef63aadc118a96cecf9d508cd679c907b6e20f71684300bdc2c0a851019af0c96b29bf8f1339753
276041aefd67db46139e6348b3a12f29537b4dc6c2c19829df2c9ed6803f3c63c3b84cfa2728849386aea575c54
3a5f70fa85793d2946f15f7fe1ccb0c5e8fe0")]
class B : A {}
// CS0281_c.cs
// compile with: /target:library /out:CS0281.dll /keyfile:CS0281.snk /reference:CS0281_b.dl
l
// CS0281 expected
[assembly:System.Reflection.AssemblyVersion("3")]
[assembly:System.Reflection.AssemblyCulture("en-us")]
class C : B {}
public class A {}
Referencia de Visual C#: errores y advertencias
// CS0283.cs
struct MyTest
{
}
class MyClass
{
// To resolve the error but retain the "const-ness",
// change const to readonly.
const MyTest test = new MyTest(); // CS0283
// CS0304.cs
// compile with: /target:library
class C<T>
{
T t = new T(); // CS0304
}
// CS0304_2.cs
// compile with: /target:library
class C<T>
{
public void f()
{
T t = new T(); // CS0304
}
}
Referencia de Visual C#: errores y advertencias
// CS0305.cs
public class MyList<T> {}
public class MyClass<T> {}
class MyClass
{
public static void Main()
{
MyList<MyClass, MyClass> list1 = new MyList<MyClass>(); // CS0305
MyList<MyClass> list2 = new MyList<MyClass>(); // OK
}
}
Referencia de Visual C#: errores y advertencias
// CS0306.cs
class C<T>
{
}
class M
{
// CS0306 – int* not allowed as a type parameter
C<int*> f;
}
Referencia de Visual C#: errores y advertencias
// CS0307.cs
class C
{
public int P { get { return 1; } }
public static void Main()
{
C c = new C();
int p = c.P<int>(); // CS0307 – C.P is a property
// Try this instead
// int p = c.P;
}
}
Referencia de Visual C#: errores y advertencias
// CS0308a.cs
class MyClass
{
public void F() {}
public static void Main()
{
F<int>(); // CS0308 – F is not generic.
// Try this instead:
// F();
}
}
El ejemplo siguiente también genera el error CS3008: Para resolver el error, utilice la directiva "using
System.Collections.Generic".
// CS0308b.cs
// compile with: /t:library
using System.Collections;
// To resolve, uncomment the following line:
// using System.Collections.Generic;
public class MyStack<T>
{
// Store the elements of the stack:
private T[] items = new T[100];
private int stack_counter = 0;
// CS0309.cs
using System;
interface I
{
}
class B
{
}
class CMain
{
public static void Main()
{
Console.WriteLine(new C<B>()); // CS0309
}
}
Referencia de Visual C#: errores y advertencias
// CS0310.cs
using System;
public G()
{
t = new T();
Console.WriteLine(t);
}
}
class B
{
private B() { }
// Try this instead:
// public B() { }
}
class CMain
{
public static void Main()
{
G<B> g = new G<B>(); // CS0310
Console.WriteLine(g.ToString());
}
}
Referencia de Visual C#: errores y advertencias
// CS0400.cs
class C
{
public static void Main()
{
// CS0400 - D could not be found
// in the global namespace.
global::D d = new global::D();
}
}
Referencia de Visual C#: errores y advertencias
// CS0401.cs
// compile with: /target:library
using System;
class C<T> where T : new(), IDisposable {} // CS0401
// CS0403.cs
// compile with: /target:library
class C<T>
{
public void f()
{
T t = null; // CS0403
T t2 = default(T); // OK
}
}
// CS0404.cs
[MyAttrib<int>] // CS0404
class C
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0405.cs
interface I
{
}
// CS0406.cs
// compile with: /target:library
interface I {}
class C {}
class D<T> where T : I, C {} // CS0406
class D2<T> where T : C, I {} // OK
Referencia de Visual C#: errores y advertencias
// CS0407.cs
public delegate int MyDelegate();
class C
{
MyDelegate d;
public C()
{
d = new MyDelegate(F); // OK: F returns int
d = new MyDelegate(G); // CS0407 – G doesn't return int
}
// CS0409.cs
interface I
{
}
// CS0410.cs
// compile with: /langversion:ISO-1
class Test
{
delegate void D(double d );
static void F(int i) { }
// CS0411.cs
class C
{
void G<T>()
{
}
Otros casos posibles en que puede producirse este error incluyen cuando el parámetro es null, puesto que no tiene ninguna
información de tipo:
// CS0411b.cs
class C
{
public void F<T>(T t) where T : C
{
}
Otro caso se produce cuando uno o varios parámetros requieren una conversión:
// CS0411c.cs
class C
{
void F<T>(T t1, T t2)
{
}
public static void Main()
{
C c = new C();
c.F(1, 2L); // CS0411 -- is T int or long?
}
}
Referencia de Visual C#: errores y advertencias
// CS0412.cs
using System;
class C
{
// Parameter name is the same as method type parameter name
public void G<T>(int T) // CS0412
{
}
public void F<T>()
{
// Method local variable name is the same as method type
// parameter name
double T = 0.0; // CS0412
Console.WriteLine(T);
}
// CS0413.cs
// compile with: /target:library
class A {}
class B : A {}
class CMain
{
A a = null;
public void G<T>()
{
a = new A();
System.Console.WriteLine (a as T); // CS0413
}
// OK
public void H<T>() where T : A
{
a = new A();
System.Console.WriteLine (a as T);
}
}
Referencia de Visual C#: errores y advertencias
// CS0415.cs
using System;
using System.Runtime.CompilerServices;
public interface IA
{
int this[int index]
{
get;
set;
}
}
public class A : IA
{
[IndexerName("Item")] // CS0415
int IA.this[int index]
// Try this line instead:
// public int this[int index]
{
get { return 0; }
set { }
}
// CS0416.cs
public class MyAttribute : System.Attribute
{
public MyAttribute(System.Type t)
{
}
}
class G<T>
{
[MyAttribute(typeof(G<T>))] // CS0416
public void F()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0417
class C<T> where T : new()
{
T type = new T(1); // CS0417
}
Referencia de Visual C#: errores y advertencias
// CS0418.cs
public abstract sealed class C // CS0418
{
}
// CS0423.cs
using System.Runtime.InteropServices;
[
ComImport,
Guid("7ab770c7-0e23-4d7a-8aa2-19bfad479829")
]
class ImageProperties
{
public static void Main() // CS0423
{
ImageProperties i = new ImageProperties();
}
}
Referencia de Visual C#: errores y advertencias
// CS0424.cs
// compile with: /target:library
using System.Runtime.InteropServices;
public class A {}
[ ComImport, Guid("7ab770c7-0e23-4d7a-8aa2-19bfad479829") ]
class B : A {} // CS0424 error
Referencia de Visual C#: errores y advertencias
Ejemplo
En el siguiente ejemplo se genera el error CS0425:
// CS0425.cs
class C1
{
}
class C2
{
}
interface IBase
{
void F<ItemType>(ItemType item) where ItemType : C1;
}
class CMain
{
public static void Main()
{
}
}
Las restricciones no tienen que ser una coincidencia literal, siempre que el conjunto de restricciones tenga el mismo
significado. Por ejemplo, lo siguiente es correcto:
// CS0425b.cs
interface J<Z>
{
}
interface I<S>
{
void F<T>(S s, T t) where T: J<S>, J<int>;
}
class C : I<int>
{
public void F<X>(int s, X x) where X : J<int>
{
}
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0426.cs
class C
{
}
class D
{
public static void Main()
{
C.A a; // CS0426
}
}
Referencia de Visual C#: errores y advertencias
// CS0428.cs
Al compilar con /reference:MyType=cs0430_a.dll para hacer referencia al archivo DLL creado en el ejemplo anterior se
resuelve este error. El código siguiente genera el error CS0430.
// CS0430_b.cs
extern alias MyType; // CS0430
public class Test
{
public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS0431.cs
using A = Outer;
// CS0432.cs
namespace A {
public class B {
public static void Meth() { }
}
}
public class Test
{
public static void Main()
{
A::B.Meth(); // CS0432
// To resolve, use the following line instead:
// A.B.Meth();
}
}
Referencia de Visual C#: errores y advertencias
// CS0433_1.cs
// compile with: /target:library
namespace TypeBindConflicts
{
public class AggPubImpAggPubImp {}
}
Este código crea el archivo DLL con la segunda copia del tipo ambiguo.
// CS0433_2.cs
// compile with: /target:library
namespace TypeBindConflicts
{
public class AggPubImpAggPubImp {}
}
// CS0433_3.cs
// compile with: /reference:cs0433_1.dll /reference:cs0433_2.dll
using TypeBindConflicts;
public class Test
{
public static void Main()
{
AggPubImpAggPubImp n6 = new AggPubImpAggPubImp(); // CS0433
}
}
En el siguiente ejemplo se muestra cómo utilizar la característica de alias de la opción de compilador /reference para resolver
este error CS0433.
// CS0433_4.cs
// compile with: /reference:cs0433_1.dll /reference:TypeBindConflicts=cs0433_2.dll
using TypeBindConflicts;
public class Test
{
public static void Main()
{
AggPubImpAggPubImp n6 = new AggPubImpAggPubImp();
}
}
Referencia de Visual C#: errores y advertencias
// CS0434_1.cs
// compile with: /t:library
namespace TypeBindConflicts
{
namespace NsImpAggPubImp
{
public class X { }
}
}
Este código crea la segunda copia del tipo con el nombre completo idéntico.
// CS0434_2.cs
// compile with: /t:library
namespace TypeBindConflicts {
// Conflicts with another import (import2.cs).
public class NsImpAggPubImp { }
// Try this instead:
// public class UniqueClassName { }
}
// CS0434.cs
// compile with: /r:cs0434_1.dll /r:cs0434_2.dll
using TypeBindConflicts;
public class Test
{
public TypeBindConflicts.NsImpAggPubImp.X n2 = null; // CS0434
}
Referencia de Visual C#: errores y advertencias
// CS0438_1.cs
// compile with: /target:module
public class Util
{
public class A { }
}
// CS0438_2.cs
// compile with: /target:module
namespace Util
{
public class A { }
}
// CS0438_3.cs
// compile with: /addmodule:CS0438_1.netmodule /addmodule:CS0438_2.netmodule
using System;
public class Test
{
public static void Main() {
Console.WriteLine(typeof(Util.A)); // CS0438
}
}
Referencia de Visual C#: errores y advertencias
// CS0439.cs
using System;
extern alias MyType; // CS0439
// To resolve the error, make the extern alias the first line in the file.
// CS0441.cs
sealed static class MyClass { } // CS0441
Referencia de Visual C#: errores y advertencias
// CS0442.cs
public abstract class MyClass
{
public abstract int AbstractProperty
{
get;
private set; // CS0442
// Try this instead:
// set;
}
}
Referencia de Visual C#: errores y advertencias
// CS0443.cs
using System;
class MyClass
{
public static void Main()
{
int[,] x = new int[1,5];
if (x[] == 5) {} // CS0443
// if (x[0, 0] == 5) {}
}
}
Referencia de Visual C#: errores y advertencias
// CS0445.CS
public struct Point
{
public int x;
public static void SetX(object obj, int x)
{
((Point)obj).x = x; // CS0445
}
}
class UnboxingTest{public static void Main(){}}
Referencia de Visual C#: errores y advertencias
// CS0446.cs
using System;
class Tester
{
static void Main()
{
int[] intArray = new int[5];
foreach (int i in M) { } // CS0446
}
static void M() { }
}
Referencia de Visual C#: errores y advertencias
En la siguiente línea de código se generará este error. Se supone que la clase C, definida en la línea anterior de código, tiene un
método estático denominado MyStaticMethod.
Ejemplo
En el siguiente código se genera el error CS0447.
// CS0447.cs
using System;
namespace Test41
{
public interface I<A>
{
void Meth<B>();
}
public class B : I<int>
{
void I<[Test] int>.Meth<X>() { } // CS0447
}
}
Referencia de Visual C#: errores y advertencias
// CS0448.cs
class C5
{
public static int operator ++(C5 c) { return null; } // CS0448
public static C5 operator --(C5 c) { return null; } // OK
public static void Main() {}
}
// CS0448_b.cs
public struct S
{
public static S? operator ++(S s) { return new S(); } // CS0448
public static S? operator --(S s) { return new S(); } // CS0448
}
public struct T
{
// OK
public static T operator --(T t) { return new T(); }
public static T operator ++(T t) { return new T(); }
// CS0449.cs
// compile with: /target:library
interface I {}
public class C4
{
public void F1<T>() where T : class, struct, I {} // CS0449
public void F2<T>() where T : I, struct {} // CS0449
public void F3<T>() where T : I, class {} // CS0449
// OK
public void F4<T>() where T : class {}
public void F5<T>() where T : struct {}
public void F6<T>() where T : I {}
}
Referencia de Visual C#: errores y advertencias
// CS0451.cs
using System;
public class C4
{
public void F4<T>() where T : struct, new() {} // CS0451
}
// OK
public class C5
{
public void F5<T>() where T : struct {}
}
public class C6
{
public void F6<T>() where T : new() {}
}
Referencia de Visual C#: errores y advertencias
// CS0452.cs
using System;
public class BaseClass<S> where S : class { }
public class Derived1 : BaseClass<int> { } // CS0452
public class Derived2<S> : BaseClass<S> where S : struct { } // CS0452
Referencia de Visual C#: errores y advertencias
// CS0453.cs
using System;
public class HV<S> where S : struct { }
public class H1 : HV<string> { } // CS0453
public class H2 : HV<H1> { } // CS0453
public class H3<S> : HV<S> where S : class { } // CS0453
public class H4 : HV<int?> { } // CS0453
public class H5 : HV<Nullable<Nullable<int>>> { } // CS0453
Referencia de Visual C#: errores y advertencias
// CS0554
using System;
public class GenericsErrors
{
public class G4<T> where T : T { } // CS0454
}
El ejemplo siguiente muestra una dependencia circular entre dos restricciones de tipo.
// CS0455.cs
using System;
// CS0456.cs
// compile with: /target:library
public class GenericsErrors
{
public class G5<T> where T : struct
{
public class N<U> where U : T {} // CS0456
public class N2<U> where U : struct {} // OK
}
}
Referencia de Visual C#: errores y advertencias
// CS0457.cs
using System;
public class A { }
public class G0 { }
public class G1<R> : G0 { }
public class H0 {
public static implicit operator G0(H0 h) {
return new G0();
}
}
public class H1<R> : H0 {
public static implicit operator G1<R>(H1<R> h) {
return new G1<R>();
}
}
public class Test
{
public static void F0(G0 g) { }
public static void Main()
{
H1<A> h1a = new H1<A>();
F0(h1a); // CS0457
}
}
Referencia de Visual C#: errores y advertencias
// CS0459.cs
// compile with: /unsafe
class A
{
public unsafe void M1()
{
int[] ints = new int[] { 1, 2, 3 };
foreach (int i in ints)
{
int *j = &i; // CS0459
}
private int _i = 0;
}
Referencia de Visual C#: errores y advertencias
// CS0460.cs
// compile with: /target:library
class BaseClass
{
BaseClass() { }
}
interface I
{
void F1<T>() where T : BaseClass;
void F2<T>() where T : struct;
void F3<T>() where T : BaseClass;
}
class ExpImpl : I
{
void I.F1<T>() where T : BaseClass {} // CS0460
void I.F2<T>() where T : class {} // CS0460
}
Referencia de Visual C#: errores y advertencias
// CS0462.cs
// compile with: /target:library
class C<T>
{
public virtual void F(T t) {}
public virtual void F(int t) {}
}
class D : C<int>
{
public override void F(int t) {} // CS0462
}
Referencia de Visual C#: errores y advertencias
// CS0463.cs
using System;
class MyClass
{
public static void Main()
{
const decimal myDec = 79000000000000000000000000000.0m + 79000000000000000000000000
000.0m; // CS0463
Console.WriteLine(myDec.ToString());
}
}
Referencia de Visual C#: errores y advertencias
// CS0466.cs
interface I
{
void F1(params int[] a);
void F2(int[] a);
}
class C : I
{
void I.F1(params int[] a) {}
void I.F2(params int[] a) {} // CS0466
void I.F2(int[] a) {} // OK
// CS0470.cs
// compile with: /target:library
interface I
{
int P { get; }
}
class MyClass : I
{
public int get_P() { return 0; } // CS0470
public int P2 { get { return 0;} } // OK
}
Referencia de Visual C#: errores y advertencias
// CS0471.cs
// compile with: /t:library
class Test
{
public void F(bool x, bool y) {}
public void F1()
{
int a = 1, b = 2, c = 3;
F(a<b, c>(3)); // CS0471
// To resolve, try the following instead:
// F((a<b), c>(3));
}
}
Referencia de Visual C#: errores y advertencias
// CS0500.cs
namespace x
{
abstract public class clx
{
abstract public void f(){} // CS0500
// try the following line instead
// abstract public void f();
}
// CS0501.cs
// compile with: /target:library
public class clx
{
public void f(); // CS0501 declared not defined
public void g() {} // OK
}
Referencia de Visual C#: errores y advertencias
// CS0502.cs
public class B
{
abstract public void F();
}
public class C : B
{
abstract sealed override public void F() // CS0502
{
}
}
// CS0503.cs
namespace x
{
abstract public class clx
{
abstract virtual public void f(); // CS0503
}
}
Referencia de Visual C#: errores y advertencias
// CS0504.cs
namespace x
{
abstract public class clx
{
static const int i = 0; // CS0504, cannot be both static and const
abstract public void f();
}
}
Referencia de Visual C#: errores y advertencias
// CS0505.cs
// compile with: /target:library
public class clx
{
public int i;
}
// CS0506.cs
namespace MyNameSpace
{
abstract public class ClassX
{
public int i = 0;
public int f()
{
return 0;
}
// Try the following definition for f() instead:
// abstract public int f();
}
// CS0507.cs
abstract public class clx
{
virtual protected void f() {}
}
El error CS0507 también puede aparecer si una clase intenta reemplazar un método marcado como protected internal
definido en metadatos a los que se hace referencia. En esta situación, el método que reemplaza se debería marcar como
protected.
// CS0507_b.cs
// compile with: /target:library
abstract public class clx
{
virtual protected internal void f() {}
}
// CS0507_c.cs
// compile with: /reference:cs0507_b.dll
public class cly : clx
{
protected internal override void f() {} // CS0507
// try the following line instead
// protected override void f() {} // OK
// CS0508.cs
// compile with: /target:library
abstract public class Clx
{
public int i = 0;
// Return type is int.
abstract public int F();
}
// CS0509.cs
// compile with: /target:library
sealed public class clx {}
public class cly : clx {} // CS0509
Referencia de Visual C#: errores y advertencias
// CS0513.cs
namespace x
{
public class clx
{
abstract public void f(); // CS0513, abstract member of nonabstract class
}
}
Referencia de Visual C#: errores y advertencias
// CS0514.cs
class A
{
static A() : base(0) // CS0514
{
}
public A(object o)
{
}
}
class B
{
static B() : this(null) // CS0514
{
}
public B(object o)
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0515.cs
public class Clx
{
public static void Main()
{
}
}
// CS0516.cs
namespace x
{
public class clx
{
public clx() : this() // CS0516, delete "this()"
{
}
// CS0522.cs
public class clx
{
public clx(int i)
{
}
// CS0523.cs
// compile with: /target:library
struct RecursiveLayoutStruct1
{
public RecursiveLayoutStruct2 field;
}
struct RecursiveLayoutStruct2
{
public RecursiveLayoutStruct1 field; // CS0523
}
Referencia de Visual C#: errores y advertencias
// CS0524.cs
public interface Clx
{
public class Cly // CS0524, delete user-defined type
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0525.cs
namespace x
{
public interface clx
{
public int i; // CS0525
}
}
Referencia de Visual C#: errores y advertencias
// CS0526.cs
namespace x
{
public interface clx
{
public clx() // CS0526
{
}
}
// CS0527.cs
// compile with: /target:library
public struct clx : int {} // CS0527 int not an interface
Referencia de Visual C#: errores y advertencias
// CS0528.cs
namespace x
{
public interface a
{
}
// CS0529.cs
namespace x
{
public interface a
{
}
public interface b : a, c
{
}
// CS0531.cs
namespace x
{
public interface clx
{
int xclx() // CS0531, cannot define xclx
// Try the following declaration instead:
// int xclx();
{
return 0;
}
}
// CS0533.cs
namespace x
{
abstract public class a
{
abstract public void f();
}
// CS0534.cs
namespace x
{
abstract public class clx
{
public abstract void f();
}
// CS0535.cs
public interface A
{
void F();
}
// OK
public class C : A {
public void F() {}
public static void Main() {}
}
// CS0535_b.cs
using System;
class C : IDisposable {} // CS0535
// OK
class D : IDisposable {
void IDisposable.Dispose() {}
public void Dispose() {}
static void Main() {
using (D d = new D()) {}
}
}
Referencia de Visual C#: errores y advertencias
// CS0536.cs
public interface a
{
void f();
}
public class b : a
{
public static int f() // CS0536
// try the following line instead
// public void f()
{
}
// CS0538.cs
interface MyIFace
{
void F();
}
class C: MyIFace
{
void MyIFace.F()
{
}
// CS0539.cs
namespace x
{
interface I
{
void m();
}
// CS0540.cs
interface I
{
void m();
}
// OK
public class Cly : I
{
void I.m() {}
public static void Main() {}
}
// CS0540_b.cs
using System;
class C {
void IDisposable.Dispose() {} // CS0540
}
class D : IDisposable {
void IDisposable.Dispose() {}
public void Dispose() {}
static void Main() {
using (D d = new D()) {}
}
}
Referencia de Visual C#: errores y advertencias
// CS0541.cs
namespace x
{
interface IFace
{
void F();
}
// CS0542.cs
class F
{
// Remove void from F() to resolve the problem.
void F() // CS0542, same name as the class
{
}
}
class MyClass
{
public static void Main()
{
}
}
Si la clase se denomina 'Item' y tiene un indizador declarado como this, puede producirse este error, ya que se dará el nombre
'Item' a un indizador predeterminado en el código emitido, lo que provoca el conflicto.
// CS0542b.cs
class Item
{
public int this[int i] // CS0542
{
get
{
return 0;
}
}
}
class CMain
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0543.cs
namespace x
{
enum I : byte
{a = 255, b, c} // CS0543
public class clx
{
public static int Main()
{
return 0;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0544.cs
// compile with: /target:library
public class a
{
public int i;
}
public class b : a
{
public override int i { // CS0544
// try the following line instead
// public new int i {
get
{
return 0;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0545.cs
// compile with: /target:library
// CS0545
public class a
{
public virtual int i
{
set {}
public class b : a
{
public override int i
{
get { return 0; }
set {} // OK
}
}
Referencia de Visual C#: errores y advertencias
// CS0546.cs
// compile with: /target:library
public class a
{
public virtual int i
{
get
{
return 0;
}
}
set {}
}
}
public class b : a
{
public override int i
{
set {} // CS0546 error no set
}
public override int i2
{
set {} // OK
}
}
Referencia de Visual C#: errores y advertencias
// CS0547.cs
public class a
{
public void i // CS0547
// Try the following declaration instead:
// public int i
{
get
{
return 0;
}
}
}
public class b : a
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0548.cs
// compile with: /target:library
public class b
{
public int MyProp {} // CS0548
// CS0549.cs
// compile with: /target:library
sealed public class MyClass
{
virtual public void TestMethod() {} // CS0549
public void TestMethod2() {} // OK
}
Referencia de Visual C#: errores y advertencias
// CS0550.cs
namespace x
{
interface ii
{
int i
{
get;
// add the following accessor to resolve this CS0550
// set;
}
}
public class a : ii
{
int ii.i
{
get
{
return 0;
}
set {} // CS0550 no set in interface
}
// CS0551.cs
// compile with: /target:library
interface ii
{
int i
{
get;
set;
}
}
public class a : ii
{
int ii.i { set {} } // CS0551
// OK
int ii.i
{
set {}
get { return 0; }
}
}
Referencia de Visual C#: errores y advertencias
// CS0552.cs
public interface ii
{
}
public class a
{
// delete the routine to resolve CS0552
public static implicit operator ii(a aa) // CS0552
{
return new ii();
}
// CS0553.cs
namespace x
{
public class ii
{
}
public class a : ii
{
// delete the conversion routine to resolve CS0553
public static implicit operator ii(a aa) // CS0553
{
return new ii();
}
// CS0554.cs
namespace x
{
public class ii
{
// delete the conversion routine to resolve CS0554
public static implicit operator ii(a aa) // CS0554
{
return new ii();
}
}
public class a : ii
{
public static void Main()
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0555.cs
public class MyClass
{
// delete the following operator to resolve this CS0555
public static implicit operator MyClass(MyClass aa) // CS0555
{
return new MyClass();
}
// CS0556.cs
namespace x
{
public class ii
{
public class iii
{
public static implicit operator int(byte aa) // CS0556
// try the following line instead
// public static implicit operator int(iii aa)
{
return 0;
}
}
// CS0557.cs
namespace x
{
public class ii
{
public class iii
{
public static implicit operator int(iii aa)
{
return 0;
}
// CS0558.cs
namespace x
{
public class ii
{
public class iii
{
static implicit operator int(iii aa) // CS0558, add public
{
return 0;
}
}
// CS0559.cs
// compile with: /target:library
public class iii
{
public static implicit operator int(iii x)
{
return 0;
}
// CS0559_b.cs
// compile with: /target:library
public struct S
{
public static S operator ++(S? s) { return new S(); } // CS0559
public static S operator --(S? s) { return new S(); } // CS0559
}
public struct T
{
// OK
public static T operator --(T t) { return new T(); }
public static T operator ++(T t) { return new T(); }
public static T? operator --(T? t) { return new T(); }
public static T? operator ++(T? t) { return new T(); }
}
Referencia de Visual C#: errores y advertencias
// CS0562.cs
public class iii
{
public static implicit operator int(iii x)
{
return 0;
}
// CS0563.cs
public class iii
{
public static implicit operator int(iii x)
{
return 0;
}
public static implicit operator iii(int x)
{
return null;
}
public static int operator +(int aa, int bb) // CS0563
// Use the following line instead:
// public static int operator +(int aa, iii bb)
{
return 0;
}
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0564.cs
using System;
class C
{
public static int operator << (C c1, C c2) // CS0564
// To correct, change second operand to int, like so:
// public static int operator << (C c1, int c2)
{
return 0;
}
static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0567.cs
interface IA
{
int operator +(int aa, int bb); // CS0567
}
class Sample
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0568.cs
public struct ClassY
{
public int field1;
public ClassY(){} // CS0568, cannot have no param constructor
// Try following instead:
// public ClassY(int i)
// {
// field1 = i;
// }
}
// CPP0570.cpp
// compile with: /clr /LD
namespace CS0570_Server {
[RequiredAttributeAttribute(Int32::typeid)]
public ref struct Scenario1 {
int intVar;
};
// CS0570.cs
// compile with: /reference:CPP0570.dll
using System;
using CS0570_Server;
public class C {
public static int Main() {
CS0570Class r = new CS0570Class();
r.sc1_field = null; // CS0570
object o = r.sc1_prop; // CS0570
r.sc1_method(); // CS0570
}
}
Referencia de Visual C#: errores y advertencias
// CS0571.cs
public class MyClass
{
public static MyClass operator ++ (MyClass c)
{
return null;
}
set_prop(1); // CS0571
// try the following line instead
// prop = 1;
}
}
Referencia de Visual C#: errores y advertencias
// CS0572.cs
using System;
class C
{
public class Inner
{
public static int v = 9;
}
}
class D : C
{
public static void Main()
{
C cValue = new C();
Console.WriteLine(cValue.Inner.v); // CS0572
// try the following line instead
// Console.WriteLine(C.Inner.v);
}
}
Referencia de Visual C#: errores y advertencias
// CS0573.cs
namespace x
{
public class clx
{
public static void Main()
{
}
}
// CS0574.cs
namespace x
{
public class iii
{
~iiii() // CS0574
{
}
// CS0575.cs
namespace x
{
public struct iii
{
~iii() // CS0575
{
}
// CS0576.cs
using SysIO = System.IO;
public class SysIO
{
public void MyMethod() {}
}
// CS0577.cs
// compile with: /target:library
interface I
{
void m();
}
// CS0578.cs
// compile with: /target:library
public class MyClass
{
[System.Diagnostics.ConditionalAttribute("a")] // CS0578
public int TestMethod()
{
return 0;
}
}
Referencia de Visual C#: errores y advertencias
// CS0579.cs
using System;
public class MyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.All,AllowMultiple=true)]
public class MyAttribute2 : Attribute
{
}
public class z
{
[MyAttribute, MyAttribute] // CS0579
public void zz()
{
}
[MyAttribute2, MyAttribute2] // OK
public void zzz()
{
}
// CS0582.cs
// compile with: /target:library
using System.Diagnostics;
interface MyIFace
{
[ConditionalAttribute("DEBUG")] // CS0582
void zz();
}
Referencia de Visual C#: errores y advertencias
// CS0590.cs
namespace x
{
public class a
{
public static void operator+(a A1, a A2) // CS0590
{
}
// CS0591.cs
using System;
[AttributeUsage(0)] // CS0591
class I: Attribute
{
}
public class a
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0592.cs
using System;
[AttributeUsage(AttributeTargets.Interface)]
public class MyAttribute : Attribute
{
}
[MyAttribute]
public class A // CS0592, MyAttribute is not valid for a class
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0594.cs
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
float f = 6.77777777777E400; // CS0594, value too large
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0596.cs
using System.Runtime.InteropServices;
namespace x
{
[ComImport] // CS0596
// try the following line to resolve this CS0596
// [ComImport, Guid("00000000-0000-0000-0000-000000000001")]
public class a
{
}
public class b
{
public static void Main()
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0601.cs
using System.Runtime.InteropServices;
using System.Text;
public class C
{
[DllImport("KERNEL32.DLL")]
extern int GetCurDirectory(int bufSize, StringBuilder buf); // CS0601
// Try the following line instead:
// static extern int GetCurDirectory(int bufSize, StringBuilder buf);
}
// CS0609.cs
using System;
using System.Runtime.CompilerServices;
// CS0610.cs
public class MainClass
{
System.TypedReference i; // CS0610
public static void Main ()
{
}
// CS0611.cs
public class a
{
public static void Main()
{
System.TypedReference[] ao = new System.TypedReference [10]; // CS0611
// try the following line instead
// int[] ao = new int[10];
}
}
Referencia de Visual C#: errores y advertencias
// CS0616.cs
// compile with: /target:library
[CMyClass(i = 5)] // CS0616
public class CMyClass {}
// CreateAttrib.cs
// compile with: /target:library
using System;
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface)]
public class MyAttr : Attribute
{
public int Name = 0;
public int Count = 0;
[MyAttr(5, 50)]
class Class1 {}
[MyAttr(6, 60)]
interface Interface1 {}
Referencia de Visual C#: errores y advertencias
// CS0617.cs
using System;
[AttributeUsage(AttributeTargets.Struct |
AttributeTargets.Class |
AttributeTargets.Interface)]
public class MyClass : Attribute
{
public int Name;
// CS0619.cs
using System;
public class C
{
[Obsolete("Use newMethod instead", true)] // generates an error on use
public static void m()
{
}
class MyClass
{
public static void Main()
{
C.m(); // CS0619
}
}
Referencia de Visual C#: errores y advertencias
// CS0620.cs
class MyClass
{
public static void Main()
{
MyClass test = new MyClass();
System.Console.WriteLine(test[2]);
}
// CS0621.cs
abstract class MyClass
{
private virtual void DoNothing1() // CS0621
{
}
// CS0622.cs
using System;
// CS0625.cs
// compile with: /target:library
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct A
{
public int i; // CS0625 not static; an instance field
}
// OK
[StructLayout(LayoutKind.Explicit)]
struct B
{
[FieldOffset(5)]
public int i;
}
Referencia de Visual C#: errores y advertencias
// CS0629.cs
interface MyInterface
{
void MyMethod();
}
// CS0631.cs
public class MyClass
{
public int this[ref int i] // CS0631
// try the following line instead
// public int this[int i]
{
get
{
return 0;
}
}
}
// CS0633a.cs
#define DEBUG
using System.Diagnostics;
public class Test
{
[Conditional("DEB+UG")] // CS0633
// try the following line instead
// [Conditional("DEBUG")]
public static void Main() { }
}
// CS0633b.cs
// compile with: /target:module
#define DEBUG
using System.Runtime.CompilerServices;
public class Test
{
[IndexerName("Invalid+Identifier")] // CS0633
// try the following line instead
// [IndexerName("DEBUG")]
public int this[int i]
{
get { return i; }
}
}
Referencia de Visual C#: errores y advertencias
// CS0636.cs
using System;
using System.Runtime.InteropServices;
// CS0637.cs
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
public class MainClass
{
[FieldOffset(3)] // CS0637
public static int i;
public static void Main ()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0641.cs
using System;
[AttributeUsage(AttributeTargets.All)]
public class NonAttrClass // CS0641
// try the following line instead
// public class NonAttrClass : Attribute
{
}
class MyClass
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0643.cs
using System;
using System.Runtime.InteropServices;
[AttributeUsage(AttributeTargets.Class)]
public class MyAttribute : Attribute
{
public MyAttribute()
{
}
public int x;
}
// CS0644.cs
class MyClass : System.ValueType // CS0644
{
}
Referencia de Visual C#: errores y advertencias
// CS0646.cs
// compile with: /target:library
[System.Reflection.DefaultMemberAttribute("x")] // CS0646
class MyClass
{
public int this[int index] // an indexer
{
get
{
return 0;
}
}
public int x = 0;
}
// OK
[System.Reflection.DefaultMemberAttribute("x")]
class MyClass2
{
public int prop
{
get
{
return 0;
}
}
public int x = 0;
}
class MyClass3
{
public int this[int index] // an indexer
{
get
{
return 0;
}
}
public int x = 0;
}
Referencia de Visual C#: errores y advertencias
// CS0647.cs
using System.Runtime.InteropServices;
// CS0650.cs
public class MyClass
{
public static void Main()
{
int myarray[2]; // CS0650
// OK
int[] myarray2 = new int[2] {1,2};
myarray2[0] = 0;
}
}
Referencia de Visual C#: errores y advertencias
// CS0653.cs
using System;
[My] // CS0653
// try the following line instead
// [My2]
class MyClass
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0655.cs
using System;
// CS0657.cs
// compile with: /target:library
public class TestAttribute : System.Attribute {}
[return: Test] // CS0657 return not valid on a class
class Class1 {}
Referencia de Visual C#: errores y advertencias
// CS0662.cs
using System.Runtime.InteropServices;
interface I
{
void method([Out] ref int i); // CS0662
// try one of the following lines instead
// void method(ref int i);
// void method([Out, In]ref int i);
}
class test
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0663.cs
class TestClass
{
public static void Main()
{
}
// CS0664.cs
class M
{
static void Main()
{
decimal m = 1.0; // CS0664
// try the following line instead
// decimal m = 1.0M;
System.Console.WriteLine(m);
}
}
Referencia de Visual C#: errores y advertencias
// CS0666.cs
class M
{
static void Main()
{
}
}
struct S
{
protected int x; // CS0666
}
Referencia de Visual C#: errores y advertencias
// CS0668.cs
using System;
using System.Runtime.CompilerServices;
class IndexerClass
{
[IndexerName("IName1")]
public int this [int index] // indexer declaration
{
get
{
return index;
}
set
{
}
}
[IndexerName("IName2")]
public int this [string s] // CS0668, change IName2 to IName1
{
get
{
return int.Parse(s);
}
set
{
}
}
void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0669.cs
using System.Runtime.InteropServices;
[ComImport, Guid("00000000-0000-0000-0000-000000000001")]
class TestClass
{
TestClass() // CS0669, delete constructor to resolve
{
}
// CS0670.cs
class C
{
void f; // CS0670
// try the following line instead
// public int f;
// CS0673.cs
class MyClass
{
public static void Main()
{
System.Type t = typeof(System.Void); // CS0673
// try the following line instead
// System.Type t = typeof(void);
}
}
Referencia de Visual C#: errores y advertencias
// CS0674.cs
using System;
public class MyClass
{
// CS0677.cs
class TestClass
{
private volatile long i; // CS0677
// CS0678.cs
using System;
class TestClass
{
private readonly volatile int i; // CS0678
// try the following line instead
// private volatile int i;
// CS0681.cs
// compile with: /target:library
abstract class C
{
abstract int num; // CS0681
}
// CS0681b.cs
// compile with: /target:library
abstract class C
{
public abstract int num
{
get;
set;
}
}
Referencia de Visual C#: errores y advertencias
// CS0683.cs
interface IExample
{
int Test { get; }
}
// CS0685.cs
using System.Diagnostics;
class C
{
[Conditional("DEBUG")]
void trace(out int i) // CS0685
{
i = 1;
}
}
Referencia de Visual C#: errores y advertencias
Interface.get_property() { /* */ }
Interface.set_property() { /* */ }
Ejemplo
El código siguiente genera el error CS0686:
// CS0686.cs
interface I
{
int get_P();
}
class C : I
{
public int P
{
get { return 1; } // CS0686
}
}
// But the following is valid:
class D : I
{
int I.get_P() { return 1; }
public static void Main() {}
}
Este error también se puede producir al declarar los eventos. La construcción del evento genera automáticamente los métodos
add_event y remove_event, que pueden estar en conflicto con los métodos del mismo nombre de una interfaz, como en el
ejemplo siguiente:
// CS0686b.cs
using System;
interface I
{
void add_OnMyEvent(EventHandler e);
}
class C : I
{
public event EventHandler OnMyEvent
{
add { } // CS0686
remove { }
}
}
// Correct (using explicit interface implementation):
class D : I
{
void I.add_OnMyEvent(EventHandler e) {}
public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS0687.cs
using M = Test;
using System;
public class Test
{
public static int x = 77;
// CS0689.cs
class A<T> : T // CS0689
{
}
Referencia de Visual C#: errores y advertencias
// CS0692.cs
// compile with: /target:library
class C <T, A, T> // CS0692
{
}
// CS0694.cs
// compile with: /target:library
class C<C> {} // CS0694
Además del en caso anterior que se refiere a una clase genérica, este error se puede producir con un método:
// CS0694_2.cs
// compile with: /target:library
class A
{
public void F<F>(F arg); // CS0694
}
Referencia de Visual C#: errores y advertencias
// CS0695.cs
// compile with: /target:library
interface I<T>
{
}
// CS0698.cs
class C<T> : System.Attribute // CS0698
{
}
Referencia de Visual C#: errores y advertencias
// CS0699.cs
class C<T> where U : I // CS0699 – U is not a valid type parameter
{
}
Referencia de Visual C#: errores y advertencias
// CS0701.cs
// compile with: /target:library
class C<T> where T : System.String {} // CS0701
class D<T> where T : System.Attribute {} // OK
Referencia de Visual C#: errores y advertencias
Ejemplo
El código siguiente genera el error CS0702:
// CS0702.cs
class C<T> where T : System.Array // CS0702
{
}
Referencia de Visual C#: errores y advertencias
// CS0703.cs
internal interface I {}
public class C<T> where T : I // CS0703 – I is internal; C<T> is public
{
}
Referencia de Visual C#: errores y advertencias
// CS0704.cs
class B
{
public class I { }
}
class CMain
{
public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS0706.cs
// compile with: /target:library
class A {}
class C<T> where T : int[] {} // CS0706
class D<T> where T : A {} // OK
Referencia de Visual C#: errores y advertencias
// CS0708.cs
// compile with: /target:library
public static class C
{
int i; // CS0708
static int j; // OK
}
Referencia de Visual C#: errores y advertencias
// CS0709.cs
// compile with: /target:library
public static class Base {}
public class Derived : Base {} // CS0709
Referencia de Visual C#: errores y advertencias
// CS0710.cs
public static class C
{
public C() // CS0710
{
}
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0711.cs
public static class C
{
~C() // CS0711
{
}
// CS0712.cs
public static class SC
{
}
public class CMain
{
public static void Main()
{
SC sc = new SC(); // CS0712
}
}
Referencia de Visual C#: errores y advertencias
// CS0713.cs
public class Base
{
}
// CS0714.cs
interface I
{
}
public static class C : I // CS0714
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0715.cs
public static class C
{
public static C operator+(C c) // CS0715
{
}
// CS0716.cs
// CS0717.cs
// CS0718.cs
public static class SC
{
public static void F()
{
}
}
// CS0719.cs
public static class SC
{
public static void F()
{
}
}
// CS0720.cs
// CS0721.cs
public static class SC
{
}
// CS0722.cs
public static class SC
{
}
// CS0723.cs
public static class SC
{
}
// CS0724.cs
using System;
class X
{
static void Test()
{
try
{
throw new Exception();
}
catch
{
try
{
}
finally
{
throw; // CS0724
}
}
}
// CS0729.cs
// compile with: /target:library
using System.Runtime.CompilerServices;
[assembly:TypeForwardedTo(typeof(TestClass))] // CS0729
class TestClass {}
Referencia de Visual C#: errores y advertencias
// CS0730a.cs
// compile with: /t:library
public class Outer
{
public class Nested {}
}
// CS0730.cs
// compile with: /t:library /r:CS0730a.dll
using System.Runtime.CompilerServices;
[assembly:TypeForwardedToAttribute(typeof(Outer.Nested))] // CS0730
[assembly:TypeForwardedToAttribute(typeof(Outer))] // OK
Referencia de Visual C#: errores y advertencias
// Circular.il
// compile with: /DLL /out=Circular.dll
.assembly extern circular2
{
.ver 0:0:0:0
}
.assembly extern circular3
{
.ver 0:0:0:0
}
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly Circular
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAtt
ribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.class extern forwarder Circular.Referenced.TypeForwarder
{
.assembly extern circular2
}
.module Circular.dll
// MVID: {880C2329-C915-42A0-83E9-9D10C3E6DBD0}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x04E40000
// ======== CLASS MEMBERS DECLARATION =========
.class public abstract auto ansi sealed beforefieldinit User
extends [mscorlib]System.Object
{
.method public hidebysig static class [circular2]Circular.Referenced.TypeForwarder
F() cil managed
{
.maxstack 1
newobj instance void [circular2]Circular.Referenced.TypeForwarder::.ctor()
ret
}
}
// Circular2.il
// compile with: /DLL /out=Circular2.dll
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly extern Circular
{
.ver 0:0:0:0
}
.assembly circular2
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAtt
ribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.class extern forwarder Circular.Referenced.TypeForwarder
{
.assembly extern Circular
}
.module circular2.dll
// MVID: {8B3BE5C8-DBE1-49C4-BC72-DF35F0387C21}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x04E40000
// CS0731.cs
// compile with: /reference:circular.dll /reference:circular2.dll
// CS0731 expected
class A {
public static void Main() {
User.F();
}
}
Referencia de Visual C#: errores y advertencias
// CS0733a.cs
// compile with: /target:library
public class GenericType<T>
{
}
// CS0733.cs
// compile with: /target:library /r:CS0733a.dll
[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(GenericType<int>))] //
CS0733
Referencia de Visual C#: errores y advertencias
// CS0734.cs
// compile with: /moduleassemblyname:A
// CS0734 expected
public class Test {}
Referencia de Visual C#: errores y advertencias
// CS1001.cs
public class clx
{
enum splitch : int
{
'a', 'b' // CS1001, 'a' is not a valid int identifier
};
Los nombres de los parámetros son obligatorios aunque el compilador no los utilice, por ejemplo, en una definición de
interfaz. Estos nombres son necesarios para que los programadores que utilicen la interfaz tengan información sobre lo que
significan los parámetros.
// CS1001-2.cs
// compile with: /target:library
interface IMyTest
{
void TestFunc1(int, int); // CS1001
}
// CS1002.cs
namespace x
{
abstract public class clx
{
int i // CS1002, missing semicolon
// CS1003.cs
public class b
{
public static void Main()
{
int[] a;
a[); // CS1003
}
}
Referencia de Visual C#: errores y advertencias
// CS1004.cs
public class clx
{
public public static void Main() // CS1004, two public keywords
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1007.cs
public class clx
{
public int MyProperty
{
get
{
return 0;
}
get // CS1007, this is the second get method
{
return 0;
}
}
// CS1008.cs
abstract public class clx
{
enum splitch : char // CS1008, char not valid type for enums
{
x, y, z
}
// CS1009-a.cs
class MyClass
{
static void Main()
{
string a = "\m"; // CS1009
// try the following line instead
// string a = "\t";
}
}
Un caso común en que se produce este error es el uso de la barra diagonal inversa en un nombre de archivo, por ejemplo:
Para resolver este error, utilice "\\" o el literal de cadena entrecomillado y precedido por la @, como se muestra en el ejemplo
siguiente:
// CS1009-b.cs
class MyClass
{
static void Main()
{
string filename = "c:\myFolder\myFile.txt"; // CS1009
// try the one of the following lines instead
// string filename = "c:\\myFolder\\myFile.txt";
// string filename = @"c:\myFolder\myFile.txt";
}
}
Referencia de Visual C#: errores y advertencias
// CS1010.cs
class Sample
{
static void Main()
{
string a = "Hello World; // CS1010, add end quote
}
}
Referencia de Visual C#: errores y advertencias
// CS1011.cs
class Sample
{
public char CharField = ''; // CS1011
}
Referencia de Visual C#: errores y advertencias
// CS1012.cs
class Sample
{
static void Main()
{
char a = 'xx'; // CS1012
char a2 = 'x'; // OK
System.Console.WriteLine(a2);
}
}
Referencia de Visual C#: errores y advertencias
// CS1013.cs
class Sample
{
static void Main()
{
int i = 0x; // CS1013
}
}
Referencia de Visual C#: errores y advertencias
// CS1014.cs
// compile with: /target:library
class Sample
{
public int TestProperty
{
get
{
return 0;
}
int z; // CS1014 not get or set
}
}
Referencia de Visual C#: errores y advertencias
// CS1015.cs
class Sample
{
static void Main()
{
try
{
}
catch(int) // CS1015, int is not derived from System.Exception
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1016.cs
using System;
[AttributeUsage(AttributeTargets.Class)]
public class HelpAttribute : Attribute
{
public HelpAttribute(string url) // url is a positional parameter
{
m_url = url;
}
// CS1017.cs
using System;
namespace x
{
public class b : Exception
{
}
public class a
{
public static void Main()
{
try
{
}
catch(b)
{
throw;
}
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1018.cs
public class C
{
}
public class a : C
{
public a(int i)
{
}
public a () : // CS1018
// possible resolutions:
// public a () resolves by removing the colon
// public a () : base() calls C's default constructor
// public a () : this(1) calls the assignment constructor of class a
{
}
// CS1019.cs
public class ii
{
int i
{
get
{
return 0;
}
}
}
public class a
{
public static a operator ii(a aa) // CS1019
// try the following line instead
//public static a operator ++(a aa)
{
return new a();
}
// CS1020.cs
public class iii
{
public static int operator ++(iii aa, int bb) // CS1020, change ++ to +
{
return 0;
}
// CS1021.cs
enum F : int
{
a=(int)2590000000000000000000 // CS1021
}
// CS1022.cs
namespace x
{
}
} // CS1022
Referencia de Visual C#: errores y advertencias
// CS1023.cs
public class a
{
public static void Main()
{
if (1)
int i; // CS1023, declaration is not valid here
if (1)
xx : i++; // CS1023, labeled statement is not valid here
}
}
Referencia de Visual C#: errores y advertencias
// CS1024.cs
#import System // CS1024
Referencia de Visual C#: errores y advertencias
También puede ocurrir el error CS1025 si se intenta utilizar una directiva de preprocesador no válida como se indica a
continuación:
// CS1025.cs
#define a
class Sample
{
static void Main()
{
#if a 1 // CS1025, invalid syntax
System.Console.WriteLine("Hello, World!");
#endif
}
}
Referencia de Visual C#: errores y advertencias
Se interpreta así:
// CS1026.cs
#if (a == b // CS1026, add closing )
#endif
class x
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1027.cs
#if true // CS1027, uncomment next line to resolve
// #endif
namespace x
{
public class clx
{
public static void Main()
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1028.cs
#endif // CS1028, no matching #if
namespace x
{
public class clx
{
public static void Main()
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1029.cs
class Sample
{
static void Main()
{
#error Let's give an error here // CS1029
}
}
Referencia de Visual C#: errores y advertencias
// CS1031.cs
namespace x
{
public class ii
{
}
public class a
{
public static operator +(a aa) // CS1031
// try the following line instead
// public static ii operator +(a aa)
{
return new ii();
}
// CS1032.cs
namespace x
{
public class clx
{
#define a // CS1032, put before namespace
public static void Main()
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1035.cs
public class a
{
public static void Main()
{
}
}
/* // CS1035, needs closing comment
Referencia de Visual C#: errores y advertencias
// CS1038.cs
#region testing
// CS1039.cs
public class MyClass
{
public static void Main()
{
string b = @"hello, world; // CS1039
}
}
Referencia de Visual C#: errores y advertencias
// CS1040.cs
/* Define a symbol, X */ #define X // CS1040
// CS1041a.cs
class MyClass
{
public void f(int long) // CS1041
// Try the following instead:
// public void f(int i)
{
}
Cuando realice una importación desde otro lenguaje de programación que no tenga el mismo conjunto de palabras
reservadas, puede modificar el identificador reservado con el prefijo @, como se muestra en el ejemplo siguiente.
Un identificador que lleve el prefijo @ se denomina identificador literal.
// CS1041b.cs
class MyClass
{
public void f(int long) // CS1041
// Try the following instead:
// public void f(int @long)
{
}
// CS1043.cs
// compile with: /target:library
public class MyClass
{
public int DoSomething
{
get return 1; // CS1043
set {}
}
// OK
public int DoSomething2
{
get { return 1;}
}
}
Referencia de Visual C#: errores y advertencias
// CS1044.cs
using System;
// CS1055.cs
delegate void del();
class Test
{
public event del MyEvent
{
int i; // CS1055
// uncomment accessors and delete previous line to resolve
// add
// {
// MyEvent += value;
// }
// remove
// {
// MyEvent -= value;
// }
}
// CS1501.cs
public class a
{
// declare the following constructor to resolve this CS1501
/*
public a(int i)
{
}
*/
// CS1501a.cs
using System;
// CS1501b.cs
class Base
{
public Base(string s)
{
}
}
class Derived : Base
{ // CS1501
public Derived(string s)
{
}
// Try this instead:
// public Derived(string s) : base(s)
// {
// }
// CS1502.cs
namespace x
{
public class a
{
public a(char i)
// try the following constructor instead
// public a(int i)
{
}
/resource:anyfile.bmp,DuplicatIdent /linkresource:a.bmp,DuplicatIdent
Referencia de Visual C#: errores y advertencias
// CS1510.cs
public class C
{
public static int j = 0;
public static void mf(ref int j)
{
j++;
}
// CS1511.cs
// compile with: /target:library
public class A
{
public int j = 0;
}
class C : A
{
public void Method()
{
base.j = 3; // base allowed here
}
// CS1512.cs
using System;
class Base {}
// CS1513
namespace y // CS1513, no close curly brace
{
class x
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1514.cs
namespace x
// CS1514, no open curly brace
Referencia de Visual C#: errores y advertencias
using System;
class Driver
{
static void Main()
{
int[] arr = new int[] {1, 2, 3};
// CS1517.cs
#if symbol // OK
#endif
#if !symbol // OK
#endif
#if (symbol) // OK
#endif
#if true // OK
#endif
#if false // OK
#endif
#if 1 // CS1517
#endif
#if ~symbol // CS1517
#endif
#if * // CS1517
#endif
class x
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1518.cs
namespace x
{
sealed class c1 {}; // OK
namespace f2 {}; // OK
sealed f3 {}; // CS1518
}
Referencia de Visual C#: errores y advertencias
// CS1519.cs
public class IMyInterface
{
checked void f4(); // CS1519
// Remove "checked" from the line above.
lock void f5(); // CS1519
// Remove "lock" from the line above
namespace; // CS1519
// The line above should be removed entirely.
int i; // OK
}
Referencia de Visual C#: errores y advertencias
// CS1520a.cs
public class x
{
f7() // CS1520, needs return type
// try the following definition
// void f7()
{
}
Este error también puede producirse cuando el formato de mayúsculas y minúsculas del nombre de un constructor es
diferente del de la declaración de clase o estructura, como ocurre en el siguiente ejemplo:
// CS1520b.cs
public class Class1
{
public class1() // CS1520, incorrect case
{
}
static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1521.cs
class CMyClass
{
public static void Main()
{
}
}
// CS1524.cs
class x
{
public static void Main()
{
try
{
// Code here
}
catch
{
}
try
{
// Code here
}
finally
{
}
try
{
// Code here
}
} // CS1524, missing catch or finally
}
Referencia de Visual C#: errores y advertencias
// CS1525.cs
class x
{
public static void Main()
{
int i = 0;
i = i + // OK - identifier
'c' + // OK - character
(5) + // OK - parenthesis
[ + // CS1525, operator not a valid expression element
throw + // CS1525, keyword not allowed in expression
void; // CS1525, void not allowed in expression
}
}
Una etiqueta vacía también puede producir CS1525, como ocurre en el siguiente ejemplo:
// CS1525b.cs
using System;
public class MyClass
{
public static void Main()
{
goto FoundIt;
FoundIt: // CS1525
// Uncomment the following line to resolve:
// System.Console.Write("Hello");
}
}
Referencia de Visual C#: errores y advertencias
// CS1526.cs
public class y
{
public static int i = 0;
public int myi = 0;
}
public class z
{
public static void Main()
{
y py = new y; // CS1526
y[] aoys = new y[10]; // Array of Ys
// CS1527.cs
namespace Sample
{
private class C1 {}; // CS1527
protected class C2 {}; // CS1527
protected internal class C3 {}; // CS1527
}
Referencia de Visual C#: errores y advertencias
// CS1528.cs
using System;
public class B
{
public B(int i)
{
_i = i;
}
// CS1529.cs
namespace X
{
namespace Subspace
{
using Microsoft;
class SomeClass
{
};
// CS1530.cs
namespace a
{
new class i // CS1530
{
}
// CS1534.cs
class MyClass
{
public static MyClass operator - (MyClass MC1, MyClass MC2, MyClass MC3) // CS1534
// try the following line instead
// public static MyClass operator - (MyClass MC1, MyClass MC2)
{
return new MyClass();
}
// CS1535.cs
class MyClass
{
// uncomment the method parameter to resolve CS1535
public static MyClass operator ++ (/*MyClass MC1*/) // CS1535
{
return new MyClass();
}
// CS1536.cs
class a
{
public static int x( void ) // CS1536
// try the following line instead
// public static int x()
{
return 0;
}
// CS1537.cs
namespace x
{
using System;
using Object = System.Object;
using Object = System.Object; // CS1537, delete this line to resolve
using System = System;
}
Referencia de Visual C#: errores y advertencias
// CS1540.cs
public class Base
{
protected void func()
{
}
}
// CS1545.cs
// compile with: /r:CPP1545.dll
class x {
public static void Main() {
Manager Ed = new Manager();
Employee Bob = new Employee("Bob Smith", 12);
Ed.Report( Bob.name ) = Bob; // CS1545
Ed.set_Report( Bob.name, Bob); // OK
}
}
Referencia de Visual C#: errores y advertencias
// CPP1546.cpp
// compile with: /clr /LD
using namespace System;
public ref class MCPP
{
public:
property int Prop [int,int]
{
int get( int i, int b )
{
return i;
}
}
};
// CS1546.cs
// compile with: /r:CPP1546.dll
using System;
public class Test
{
public static void Main()
{
int i = 0;
MCPP mcpp = new MCPP();
i = mcpp.Prop(1,1); // CS1546
// Try the following line instead:
// i = mcpp.get_Prop(1,1);
}
}
Referencia de Visual C#: errores y advertencias
// CS1547.cs
public class MyClass
{
void BadMethod()
{
void i; // CS1547, cannot have variables of type void
}
// CS1551.cs
public class MyClass
{
int intI;
// CS1552.cs
public class C
{
public static void Main(string args[]) // CS1552
// try the following line instead
// public static void Main(string [] args)
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1553.cs
class MyClass
{
public static int implicit operator (MyClass f) // CS1553
// try the following line instead
// public static implicit operator int (MyClass f)
{
return 6;
}
// CS1554.cs
class MyClass
{
public static operator ++ MyClass (MyClass f) // CS1554
// try the following line instead
// public static MyClass operator ++ (MyClass f)
{
return new MyClass ();
}
// CS1558.cs
// compile with: /main:MyNamespace.MyClass
namespace MyNamespace
{
public class MyClass
{
public static float Main()
{
return 0.0; // CS1558 because the return type is a float.
}
}
}
Referencia de Visual C#: errores y advertencias
// cs1560.cs
using System;
class MyClass
{
public static void Main()
{
Console.WriteLine("Normal line #1.");
#line 21 "MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile12345
67890MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile
1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890.
txt" // CS1560
}
}
Referencia de Visual C#: errores y advertencias
El ejemplo anterior generó un archivo .xml que se estableció a continuación a sólo lectura. Este código de ejemplo intenta
escribir en el mismo archivo. El código siguiente genera el error CS1569.
// CS1569_a.cs
// compile with: /doc:CS1569.xml
// CS1569 expected
class Test
{
/// <summary>Test.</summary>
public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS1575.cs
// compile with: /unsafe
public class MyClass
{
unsafe public static void Main()
{
int *p = stackalloc int (30); // CS1575
// try the following line instead
// int *p = stackalloc int [30];
}
}
Referencia de Visual C#: errores y advertencias
// CS1576.cs
public class MyClass
{
static void Main()
{
#line "abc.sc" // CS1576
// try the following line instead
//#line 101 "abc.sc"
intt i; // error will be reported on line 101
}
}
Referencia de Visual C#: errores y advertencias
// CS1578.cs
class MyClass
{
static void Main()
{
#line 101 abc.cs // CS1578
// try the following line instead
//#line 101 "abc.cs"
intt i; // error will be reported on line 101
}
}
Referencia de Visual C#: errores y advertencias
Ejemplo
En este ejemplo, foreach no puede recorrer en iteración la colección porque no hay un método GetEnumerator public en
MyCollection.
// CS1579.cs
using System;
public class MyCollection
{
int[] items;
public MyCollection()
{
items = new int[5] {12, 44, 33, 2, 50};
}
// CS1585.cs
public class Class1
{
public void static Main(string[] args) // CS1585
// try the following line instead
// public static void Main(string[] args)
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1586.cs
using System;
class MyClass
{
public static void Main()
{
int[] a = new int[]; // CS1586
// try the following line instead
int[] b = new int[5];
}
}
Referencia de Visual C#: errores y advertencias
// CS1593.cs
using System;
delegate string func(int i); // declare delegate
class a
{
public static void Main()
{
func dt = new func(z);
x(dt);
}
// CS1594.cs
using System;
delegate string func(int i); // declare delegate
class a
{
public static void Main()
{
func dt = new func(z);
x(dt);
}
// CS1597.cs
class TestClass
{
public static void Main()
{
}; // CS1597, remove semicolon
}
Referencia de Visual C#: errores y advertencias
// CS1599.cs
using System;
class MyClass
{
public static void Main()
{
}
// CS1601.cs
using System;
class MyClass
{
public void Test1 (ref TypedReference t) // CS1601
{
}
// CS1609.cs
// compile with: /target:library
delegate int Del();
class A
{
public event Del MyEvent
{
private add {} // CS1609
// try the following line instead
// add {}
remove {}
}
}
Referencia de Visual C#: errores y advertencias
// CS1611.cs
public class MyClass
{
public static void Test(params ref int[] a) // CS1611, remove ref
{
}
// CS1612.cs
public struct MyStruct
{
public int Width;
}
// CS1613.cs
using System;
using System.Runtime.InteropServices;
[Guid("1FFD7840-E82D-4268-875C-80A160C23296")]
[ComImport()]
[CoClass(typeof(A))]
public interface IA{}
public class A : IA {}
public class AA
{
public static void Main()
{
IA i;
i = new IA(); // This is equivalent to new A().
// because of the CoClass attribute on IA
}
}
Referencia de Visual C#: errores y advertencias
// CS1614.cs
using System;
class MakeAWarning {
[MySpecial()] // CS1614
// Ambiguous: MySpecial or MySpecialAttribute?
public static void Main() {
}
[@MySpecial()] // This isn't ambiguous, it binds to the first attribute above.
public static void NoWarning() {
}
[MySpecialAttribute()] // This isn't ambiguous, it binds to the second attribute above.
public static void NoWarning2() {
}
[@MySpecialAttribute()] // This is also legal.
public static void NoWarning3() {
}
}
Referencia de Visual C#: errores y advertencias
// CS1615.cs
class C
{
public void f(int i) {}
public static void Main()
{
int i = 1;
f(ref i); // CS1615
}
}
Referencia de Visual C#: errores y advertencias
// CS1618.cs
using System;
using System.Diagnostics;
class MakeAnError {
public static void Main() {
del d = new del(ConditionalMethod); // CS1618
// Invalid because on builds where DEBUG is not set,
// there will be no "ConditionalMethod".
}
// To fix the error, remove the next line:
[Conditional("DEBUG")]
public static void ConditionalMethod()
{
Console.WriteLine("Do something only in debug");
}
}
Referencia de Visual C#: errores y advertencias
// CS1620.cs
class C
{
void f(ref int i) {}
public static void Main()
{
int x = 1;
f(out x); // CS1620 – f takes a ref parameter, not an out parameter
// Try this line instead:
// f(ref x);
}
}
Referencia de Visual C#: errores y advertencias
// CS1621.cs
using System.Collections;
class C : IEnumerable
{
public IEnumerator GetEnumerator()
{
MyDelegate d = delegate
{
yield return this; // CS1621
return this;
};
d();
// Try this instead:
// MyDelegate d = delegate { return this; };
// yield return d();
}
// CS1622.cs
// compile with: /target:library
using System.Collections;
class C : IEnumerable
{
public IEnumerator GetEnumerator()
{
return (IEnumerator) this; // CS1622
yield return this; // OK
}
}
Referencia de Visual C#: errores y advertencias
// CS1623.cs
using System.Collections;
class C : IEnumerable
{
public IEnumerator GetEnumerator()
{
yield return 0;
}
// CS1624.cs
using System;
using System.Collections;
class C
{
public int Iterator
// Try this instead:
// public IEnumerable Iterator
{
get // CS1624
{
yield return 1;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1625.cs
using System.Collections;
class C : IEnumerable
{
public IEnumerator GetEnumerator()
{
try
{
}
finally
{
yield return this; // CS1625
}
}
}
// CS1626.cs
using System.Collections;
class C : IEnumerable
{
public IEnumerator GetEnumerator()
{
try
{
yield return this; // CS1626
}
catch
{
}
}
}
// CS1627.cs
using System.Collections;
class C : IEnumerable
{
public IEnumerator GetEnumerator()
{
yield return; // CS1627
// To resolve, add the following line:
// yield return 0;
}
}
// CS1628.cs
class C
{
public static void F(ref int i)
{
MyDelegate d = delegate { return i; }; // CS1628
// Try this instead:
// int tmp = i;
// MyDelegate d = delegate { return tmp; };
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1629.cs
// compile with: /unsafe
using System.Collections.Generic;
class C
{
IEnumerator<int> IteratorMeth() {
int i;
unsafe // CS1629
{
int *p = &i;
yield return *p;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1631.cs
using System;
using System.Collections;
// CS1632.cs
// compile with: /target:library
delegate void MyDelegate();
class MyClass
{
public void Test()
{
for (int i = 0 ; i < 5 ; i++)
{
MyDelegate d = delegate {
break; // CS1632
};
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1637.cs
// compile with: /unsafe
using System.Collections;
// CS1638.cs
// compile with: /langversion:ISO-1
class bad__identifer // CS1638 (double underscores are not ISO compliant)
{
}
class CMain
{
public static void Main() { }
}
Vea también
Referencia
/langversion (Sintaxis compatible) (Opciones del compilador de C#)
Referencia de Visual C#: errores y advertencias
// CS1640.cs
using System;
using System.Collections;
using System.Collections.Generic;
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
yield break;
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)((IEnumerable<string>)this).GetEnumerator();
}
}
public class Test
{
public static int Main()
{
foreach (int i in new C()){} // CS1640
// Try specifing the type of IEnumerable<T>
// foreach (int i in (IEnumerable<int>)new C()){}
return 1;
}
}
Referencia de Visual C#: errores y advertencias
// CS1641.cs
// compile with: /unsafe /target:library
unsafe struct S {
fixed int [] a; // CS1641
// OK
fixed int b [10];
const int c = 10;
fixed int d [c];
}
Referencia de Visual C#: errores y advertencias
// CS1642.cs
// compile with: /unsafe /target:library
unsafe class C
{
fixed int a[10]; // CS1642
}
unsafe struct D
{
fixed int a[10];
}
unsafe class E
{
public int[] a = null;
}
Referencia de Visual C#: errores y advertencias
// CS1643.cs
delegate int MyDelegate();
class C
{
static void Main()
{
MyDelegate d = delegate
{ // CS1643
int i = 0;
if (i == 0)
return 1;
};
}
}
Referencia de Visual C#: errores y advertencias
// CS1644.cs
// compile with: /langversion:ISO-1 /target:library
class C<T> {} // CS1644
Referencia de Visual C#: errores y advertencias
// CS1646
class C
{
int i = @5; // CS1646
// Try this line instead:
// int i = 5;
}
Referencia de Visual C#: errores y advertencias
// CS1648.cs
public struct Inner
{
public int i;
}
class Outer
{
public readonly Inner inner = new Inner();
}
class D
{
static void Main()
{
Outer outer = new Outer();
outer.inner.i = 1; // CS1648
}
}
Referencia de Visual C#: errores y advertencias
// CS1649.cs
public struct Inner
{
public int i;
}
class Outer
{
public readonly Inner inner = new Inner();
}
class D
{
static void f(ref int iref)
{
}
// CS1650.cs
public struct Inner
{
public int i;
}
class Outer
{
public static readonly Inner inner = new Inner();
}
class D
{
static void Main()
{
Outer.inner.i = 1; // CS1650
}
}
Referencia de Visual C#: errores y advertencias
// CS1651.cs
public struct Inner
{
public int i;
}
class Outer
{
public static readonly Inner inner = new Inner();
}
class D
{
static void f(ref int iref)
{
}
// CS1654.cs
using System;
using System.Collections;
// CS1655.cs
struct S
{
public int i;
}
class CMain
{
static void f(ref int iref)
{
}
// CS1656.cs
// compile with: /unsafe
using System;
class C : IDisposable
{
public void Dispose() { }
}
class CMain
{
unsafe public static void Main()
{
using (C c = new C())
{
c = new C(); // CS1656
}
// CS1657.cs
using System;
class C : IDisposable
{
public int i;
public void Dispose() {}
}
class CMain
{
static void f(ref C c)
{
}
static void Main()
{
using (C c = new C())
{
f(ref c); // CS1657
}
}
}
// CS1657b.cs
// compile with: /unsafe
unsafe class C
{
static void F(ref int* p)
{
}
// CS1660.cs
delegate int MyDelegate();
class C {
static void Main()
{
int i = delegate { return 1; }; // CS1660
// Try this instead:
// MyDelegate myDelegate = delegate { return 1; };
// int i = myDelegate();
}
}
Referencia de Visual C#: errores y advertencias
// CS1661.cs
class C
{
public static void Main()
{
MyDelegate d = delegate(string s) { }; // CS1661
}
}
Referencia de Visual C#: errores y advertencias
// CS1662.cs
class C
{
// CS1663.cs
// compile with: /unsafe /target:library
unsafe struct C
{
fixed string ab[10]; // CS1663
}
Referencia de Visual C#: errores y advertencias
// CS1665.cs
// compile with: /unsafe /target:library
struct S
{
public unsafe fixed int A[0]; // CS1665
}
Referencia de Visual C#: errores y advertencias
// CS1666.cs
// compile with: /unsafe /target:library
unsafe struct S
{
public fixed int buffer[1];
}
unsafe class Test
{
S field = new S();
// CS1667.cs
using System;
public class C
{
private int i;
// CS1670.cs
public class C
{
public bool operator +(params int[] paramsList) // CS1670
{
return false;
}
// CS1671.cs
public namespace NS // CS1671
{
}
Referencia de Visual C#: errores y advertencias
// CS1673.cs
delegate int MyDelegate();
public struct S
{
int member;
};
return d();
}
}
class CMain
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1674.cs
class C
{
public static void Main()
{
int a = 0;
a++;
// CS1674_b.cs
using System;
class C {
public void Test() {
using (C c = new C()) {} // CS1674
}
}
// OK
class D : IDisposable {
void IDisposable.Dispose() {}
public void Dispose() {}
El caso siguiente ilustra la necesidad de utilizar una restricción de tipo de clase para garantizar que un parámetro de tipo
desconocido sea descartable. El código siguiente genera el error CS1674.
// CS1674_c.cs
// compile with: /target:library
using System;
public class C<T>
// Add a class type constraint that specifies a disposable class.
// Uncomment the following line to resolve.
// public class C<T> where T : IDisposable
{
public void F(T t)
{
using (t) {} // CS1674
}
}
Referencia de Visual C#: errores y advertencias
// CS1675.cs
enum E<T> // CS1675
{
}
class CMain
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1676.cs
delegate void E(ref int i);
class Errors
{
static void Main()
{
E e = delegate(out int i) { }; // CS1676
// To resolve, use the following line instead:
// E e = delegate(ref int i) { };
}
}
Referencia de Visual C#: errores y advertencias
// CS1677.cs
delegate void D(int i);
class Errors
{
static void Main()
{
D d = delegate(out int i) { }; // CS1677
// To resolve, use the following line instead:
// D d = delegate(int i) { };
// CS1678
delegate void D(int i);
class Errors
{
static void Main()
{
D d = delegate(string s) { }; // CS1678
// To resolve, use the following line instead:
// D d = delegate(int s) { };
}
}
Referencia de Visual C#: errores y advertencias
// CS1679.cs
// compile with: /reference:123$BadIdentifier%=System.dll
class TestClass {
static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1680.cs
// compile with: /reference:alias=
// CS1680 expected
// To resolve, specify the name of a file with an assembly manifest
class MyClass {}
Referencia de Visual C#: errores y advertencias
// CS1681.cs
// compile with: /reference:global=System.dll
// CS1681 expected
// CS1686.cs
// compile with: /unsafe /target:library
class MyClass
{
public unsafe delegate int * MyDelegate();
// CS1688.cs
using System;
delegate void OutParam(out int i);
class ErrorCS1676
{
static void Main()
{
OutParam o;
o = delegate // CS1688
// Try this instead:
// o = delegate(out int i)
{
Console.WriteLine("");
};
}
}
Referencia de Visual C#: errores y advertencias
// CS1689.cs
// compile with: /target:library
[System.Diagnostics.Conditional("A")] // CS1689
class MyClass {}
Referencia de Visual C#: errores y advertencias
// CS1690.cs
using System;
// OK
int i = e.i;
i.ToString();
e.i = i;
}
}
Referencia de Visual C#: errores y advertencias
using System;
public class A { }
using System;
public class A { }
// CS1704_a.cs
// compile with: /target:library /out:c:\\cs1704.dll
public class A {}
Este ejemplo crea un ensamblado con el mismo nombre que el ejemplo anterior, pero lo guarda a una ubicación diferente.
// CS1704_b.cs
// compile with: /target:library /out:cs1704.dll
public class A {}
En este ejemplo se intenta hacer referencia a ambos ensamblados. El código siguiente genera el error CS1704.
// CS1704_c.cs
// compile with: /target:library /r:A2=cs1704.dll /r:A1=c:\\cs1704.dll
// CS1704 expected
extern alias A1;
extern alias A2;
Referencia de Visual C#: errores y advertencias
// CS1705_a.cs
// compile with: /target:library /out:c:\\cs1705.dll /keyfile:mykey.snk
[assembly:System.Reflection.AssemblyVersion("1.0")]
public class A
{
public void M1() {}
public class N1 {}
public void M2() {}
public class N2 {}
}
public class C1 {}
public class C2 {}
A continuación aparece la versión 2.0 del ensamblado, de acuerdo con lo especificado por el atributo
AssemblyVersionAttribute.
// CS1705_b.cs
// compile with: /target:library /out:cs1705.dll /keyfile:mykey.snk
using System.Reflection;
[assembly:AssemblyVersion("2.0")]
public class A
{
public void M2() {}
public class N2 {}
public void M1() {}
public class N1 {}
}
public class C2 {}
public class C1 {}
Guarde este ejemplo en un archivo denominado CS1705ref.cs y compílelo con los indicadores siguientes: /t:library
/r:A2=.\bin2\CS1705a.dll /r:A1=.\bin1\CS1705a.dll
// CS1705_c.cs
// compile with: /target:library /r:A2=c:\\CS1705.dll /r:A1=CS1705.dll
extern alias A1;
extern alias A2;
using a1 = A1::A;
using a2 = A2::A;
using n1 = A1::A.N1;
using n2 = A2::A.N2;
public class Ref
{
public static a1 A1() { return new a1(); }
public static a2 A2() { return new a2(); }
public static A1::C1 M1() { return new A1::C1(); }
public static A2::C2 M2() { return new A2::C2(); }
public static n1 N1() { return new a1.N1(); }
public static n2 N2() { return new a2.N2(); }
}
El ejemplo siguiente hace referencia a la versión 1.0 del ensamblado CS1705.dll. Sin embargo, la instrucción Ref.A2().M2()
hace referencia al método A2 en la clase de CS1705_c.dll, que devuelve a2, cuyo alias es A2::A. Por su parte, A2 hace referencia
a la versión 2.0 a través de una instrucción extern, lo que provoca una diferencia de versiones.
El código siguiente genera el error CS1705.
// CS1705_d.cs
// compile with: /reference:c:\\CS1705.dll /reference:CS1705_c.dll
// CS1705 expected
class Tester
{
static void Main()
{
Ref.A1().M1();
Ref.A2().M2();
}
}
Referencia de Visual C#: errores y advertencias
// CS1706.cs
using System;
// CS1708.cs
// compile with: /unsafe
using System;
// CS1715.cs
abstract public class Base
{
abstract public int myProperty
{
get;
set;
}
}
// CS1716.cs
// compile with: /unsafe
using System;
using System.Runtime.CompilerServices;
public struct UnsafeStruct
{
[FixedBuffer(typeof(int), 4)] // CS1716
unsafe public int aField;
// Use this single line instead of the above two lines.
// unsafe public fixed int aField[4];
}
// CS1721.cs
public class A {}
public class B {}
public class MyClass : A, B {} // CS1721
Referencia de Visual C#: errores y advertencias
// CS1722.cs
// compile with: /target:library
public class A {}
interface I {}
// CS1724.cs
using System.Runtime.InteropServices;
// To resolve, replace 42 with a valid CharSet value.
[module:DefaultCharSetAttribute((CharSet)42)] // CS1724
class C {
[DllImport("F.Dll")]
extern static void FW1Named();
// CS1728.cs
// compile with: /W:2
class Test
{
delegate T GetT<T>();
delegate T GetT1<T>(T t);
// CS1900.cs
// compile with: /W:5
// CS1900 expected
class x
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1902.cs
// compile with: /debug:x
// CS1902 expected
class x
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1908.cs
// compile with: /target:library
using System.Runtime.InteropServices;
// CS1909.cs
// compile with: /target:library
using System.Runtime.InteropServices;
// CS1910.cs
// compile with: /target:library
using System.Runtime.InteropServices;
// CS2005.cs
// compile with: /recurse:
// CS2005 expected
class x
{
public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS2007.cs
// compile with: /recur
// CS2007 expected
class x
{
public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS2013.cs
// compile with: /target:library /baseaddress:x
// CS2013 expected
class MyClass
{
}
Referencia de Visual C#: errores y advertencias
// CS2016.cs
// compile with: /codepage:x
// CS2016 expected
class MyClass
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS2017.cs
// compile with: /main:MyClass /target:library
// CS2017 expected
class MyClass
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS2019.cs
// compile with: /target:libra
// CS2019 expected
class MyClass
{
}
Referencia de Visual C#: errores y advertencias
// CS2024.cs
// compile with: /filealign:ex
// CS2024 expected
class MyClass
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS2034.cs
// compile with: /r:A1=cs2034a1.dll;A2=cs2034a2.dll
// to fix, compile with: /r:A1=cs2034a1.dll /r:A2=cs2034a2.dll
// CS2034
extern alias A1;
extern alias A2;
using System;
Referencia de Visual C#: errores y advertencias
// CS2035.cs
// compile with: /baseaddress
// CS2035 expected
Referencia de Visual C#: errores y advertencias
// CS3027.cs
// compile with: /target:library
public interface IBase
{
void IMethod(uint i);
}
// CS3027_b.cs
// compile with: /reference:CS3027.dll /target:library /W:1
[assembly:System.CLSCompliant(true)]
public interface IDerived : IBase {}
Referencia de Visual C#: errores y advertencias
// CS5001.cs
// CS5001 expected
public class a
{
// Uncomment the following line to resolve.
// public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS0183.cs
// compile with: /W:1
using System;
public class Test
{
public static void F(Int32 i32, String str)
{
if (str is Object) // OK
Console.WriteLine( "str is an object" );
else
Console.WriteLine( "str is not an object" );
F(0, "CS0183");
F(120, null);
}
}
Referencia de Visual C#: errores y advertencias
// CS0184.cs
// compile with: /W:1
class MyClass
{
public static void Main()
{
int i = 0;
if (i is string) // CS0184
i++;
}
}
Referencia de Visual C#: errores y advertencias
// CS0420.cs
// compile with: /W:1
using System;
class TestClass
{
private volatile int i;
Si esta clase se utiliza como si fuera una clase base y la clase de la que se deriva define un destructor, éste reemplazará el
método Finalize de la clase base, no el método Finalize.
Ejemplo
El siguiente ejemplo genera la advertencia CS0465.
// CS0465.cs
// compile with: /target:library
class A
{
public virtual void Finalize() {} // CS0465
}
// OK
class B
{
~B() {}
}
Referencia de Visual C#: errores y advertencias
// CS0612.cs
// compile with: /W:1
using System;
class MyClass
{
[Obsolete]
public static void ObsoleteMethod()
{
}
[Obsolete]
public static int ObsoleteField;
}
class MainClass
{
static public void Main()
{
MyClass.ObsoleteMethod(); // CS0612 here: method is deprecated
MyClass.ObsoleteField = 0; // CS0612 here: field is deprecated
}
}
Referencia de Visual C#: errores y advertencias
// CS0626.cs
// compile with: /warnaserror
using System.Runtime.InteropServices;
// CS0658.cs
using System;
public class TestAttribute : Attribute{}
[badAttributeLocation: Test] // CS0658, badAttributeLocation is invalid
class ClassTest
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0672.cs
// compile with: /W:1
class MyClass
{
[System.Obsolete]
public virtual void ObsoleteMethod()
{
}
}
class MainClass
{
static public void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0684.cs
// compile with: /W:1
using System;
using System.Runtime.InteropServices;
[CoClass(typeof(C))] // CS0684
// try the following line instead
// [CoClass(typeof(C)), ComImport]
interface I
{
}
class C
{
static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS0688.cs
// compile with: /W:1
using System;
using System.Security.Permissions;
class Base
{
//Uncomment the following line to close the security hole
//[FileIOPermission(SecurityAction.LinkDemand, All=@"C:\\")]
public virtual void DoScaryFileStuff()
{
}
}
// CS1030.cs
class Sample
{
static void Main()
{
#warning Let's give a warning here // CS1030
}
}
Referencia de Visual C#: errores y advertencias
// CS1522.cs
// compile with: /W:1
using System;
class x
{
public static void Main()
{
int i = 6;
switch(i) // CS1522
{
// add something to the switch block, for example:
/*
case (5):
Console.WriteLine("5");
return;
default:
Console.WriteLine("not 5");
return;
*/
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1570.cs
// compile with: /W:1
namespace ns
{
// the following line generates CS1570
/// <summary> returns true if < 5 </summary>
// try this instead
// /// <summary> returns true if <5 </summary>
// CS1574.cs
// compile with: /W:1 /doc:x.xml
using System;
class TestClass
{
public static void Main()
{
try
{
}
catch(EClass)
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1580.cs
// compile with: /W:1 /doc:x.xml
using System;
// CS1581.cs
// compile with: /W:1 /doc:x.xml
// CS1584.cs
// compile with: /W:1 /doc:CS1584.xml
/// <remarks>Test class</remarks>
public class Test
{
/// <remarks>Called in <see cref="Test.Mai()n"/>.</remarks> // CS1584
// try the following line instead
// /// <remarks>Called in <see cref="Test.Main()"/>.</remarks>
public static void Test2() {}
// CS1589.cs
// compile with: /W:1 /doc:CS1589_out.xml
// CS1590.cs
// compile with: /W:1 /doc:x.xml
sn –k CS1616.snk
// CS1616.cs
// compile with: /keyfile:cs1616.snk
using System.Reflection;
class C
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1633.cs
// compile with: /W:1
#pragma unknown // CS1633
class C
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1634.cs
// compile with: /W:1
class MyClass
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1635.cs
// compile with: /w:1 /nowarn:162
class MyClass
{
public static void Main()
{
#pragma warning disable 162
if (MyEnum.three == MyEnum.two)
System.Console.WriteLine("Duplicate");
// CS1645.cs
// compile with: /W:1 /t:module /langversion:ISO-1
[assembly:System.CLSCompliant(false)]
// To supress the warning use the switch: /nowarn:1645
[module:System.CLSCompliant(false)] // CS1645
class Test
{
}
Referencia de Visual C#: errores y advertencias
// CS1658.cs
// compile with: /doc:x.xml
// CS1584 expected
/// <summary>
/// </summary>
public class C
{
/// <see cref="C.F(params object[])"/> // CS1658
public static void M()
{
}
/// <summary>
/// </summary>
public void F(params object[] o)
{
}
// CS1682_b.cs
// compile with: /target:library /reference:CS1682.dll
using System;
public class Ref {
// CS1682_c.cs
// compile with: /target:library /keyfile:mykey.snk /out:CS1682.dll
public class A {
public void M1() {}
}
// CS1682_d.cs
// compile with: /reference:CS1682.dll /reference:CS1682_b.dll /W:1
// CS1682 expected
class Tester {
static void Main()
{
Ref.A1().M1();
}
}
Referencia de Visual C#: errores y advertencias
public class C2 {}
// CS1684_b.cs
// compile with: /target:library /r:cs1684_a.dll
// post-build command: del /f CS1684_a.dll
using System;
public class Ref
{
public static A GetA() { return new A(); }
public static C2 GetC() { return new C2(); }
}
Volvemos a generar ahora el primer ensamblado, omitiendo la definición de la clase C2 que no se va a definir en la nueva
compilación.
// CS1684_c.cs
// compile with: /target:library /keyfile:CS1684.key /out:CS1684_a.dll
public class A {
public void Test() {}
}
Este módulo hace referencia al segundo módulo por medio del identificador Ref. Sin embargo, el segundo módulo contiene
una referencia a la clase C2 que ya no existe debido a la compilación del paso anterior y, por consiguiente, al compilar este
módulo se devuelve el mensaje de error CS1684.
// CS1684_d.cs
// compile with: /reference:cs1684_a.dll /reference:cs1684_b.dll
// CS1684 expected
class Tester
{
public static void Main()
{
Ref.GetA().Test();
}
}
Referencia de Visual C#: errores y advertencias
// CS1691.cs
public class C
{
int i = 1;
public static void Main()
{
C myC = new C();
#pragma warning disable 151 // CS1691
// Try the following line instead:
// #pragma warning disable 1645
myC.i++;
#pragma warning restore 151 // CS1691
// Try the following line instead:
// #pragma warning restore 1645
}
}
Referencia de Visual C#: errores y advertencias
// CS1692.cs
class A
{
static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// cs1694.cs
#pragma checksum "MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile123
4567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFi
le1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile1234567890MyFile123456789
0.txt" {00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F} // CS1694
class MyClass {}
Referencia de Visual C#: errores y advertencias
// CS1695.cs
// CS1696.cs
class Test
{
public static void Main()
{
#pragma warning disable 1030;219 // CS1696
#pragma warning disable 1030 // OK
}
}
Referencia de Visual C#: errores y advertencias
// CS1699.cs
// compile with: /target:library
[assembly:System.Reflection.AssemblyDelaySign(true)] // CS1699
Vea también
Tareas
Cómo: Firmar un ensamblado con un nombre seguro
Referencia
Página Firma, Diseñador de proyectos
Otros recursos
Administrar la firma de ensamblados y manifiestos
Referencia de Visual C#: errores y advertencias
// CS1709.cs
class Test
{
static void Main()
{
#pragma checksum "" "{406EA660-64CF-4C82-B6F0-42D48172A799}" "" // CS1709
}
}
Referencia de Visual C#: errores y advertencias
default(T).ToString()
Puesto que T es un tipo de referencia, su valor predeterminado es null y, al intentar para aplicarle el método ToString,
producirá una excepción NullReferenceException.
Ejemplo
La restricción de referencia de clase sobre el tipo T garantiza que T sea un tipo de referencia.
El código siguiente genera la advertencia CS1720.
// CS1720.cs
using System;
public class Tester
{
public static void GenericClass<T>(T t1) where T : class
{
Console.WriteLine(default(T).ToString()); // CS1720
}
public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS1723.cs
// compile with: /t:library /doc:filename.XML
///<summary>A generic list class.</summary>
///<see cref="T" /> // CS1723
// To resolve comment the previous line.
public class List<T>
{
}
Referencia de Visual C#: errores y advertencias
// CS1911.cs
// compile with: /W:1
using System;
class B {
protected virtual void M() {
Console.WriteLine("B.M");
}
}
class Der : B {
protected override void M() {
Console.WriteLine("D.M");
}
public D CallBaseM() {
return delegate () { base.M(); }; // CS1911
// try the following line instead
// return delegate () { Test(); };
}
class Program {
public static void Main() {
Der der = new Der();
D d = der.CallBaseM();
d();
RetD rd = der.DelToBaseM();
rd()();
}
}
Referencia de Visual C#: errores y advertencias
// CS2002.cs
// compile with: CS2002.cs
public class A
{
public static void Main(){}
}
// CS3000.cs
// compile with: /target:library
// CS3000 expected
[assembly:System.CLSCompliant(true)]
// CS3001.cs
[assembly:System.CLSCompliant(true)]
public class a
{
public void bad(ushort i) // CS3001
{
}
// CS3002.cs
[assembly:System.CLSCompliant(true)]
public class a
{
public ushort bad() // CS3002, public method
{
ushort a;
a = ushort.MaxValue;
return a;
}
// CS3003.cs
[assembly:System.CLSCompliant(true)]
public class a
{
public ushort a1; // CS3003, public variable
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS3005.cs
using System;
[assembly:CLSCompliant(true)]
public class a
{
public static int a1 = 0;
public static int A1 = 1; // CS3005
// CS3006.cs
using System;
[assembly: CLSCompliant(true)]
public class MyClass
{
public void f(int i)
{
}
// CS3007.cs
[assembly: System.CLSCompliant(true)]
public struct S
{
public void F(int[][] array) { }
public void F(byte[][] array) { } // CS3007
// Try this instead:
// public void F1(int[][] array) {}
// public void F2(byte[][] array) {}
// or
// public void F(int[,] array) {}
// public void F(byte[,] array) {}
}
Referencia de Visual C#: errores y advertencias
// CS3008.cs
using System;
[assembly:CLSCompliant(true)]
public class a
{
public static int _a = 0; // CS3008
// OK, private
// private static int _a1 = 0;
// CS3009.cs
using System;
[assembly:CLSCompliant(true)]
[CLSCompliant(false)]
public class B
{
}
// CS3010.cs
using System;
[assembly:CLSCompliant(true)]
public interface I
{
[CLSCompliant(false)]
int mf(); // CS3010
}
public class C : I
{
public int mf()
{
return 1;
}
// CS3011.cs
using System;
[assembly:CLSCompliant(true)]
public abstract class I
{
[CLSCompliant(false)]
public abstract int mf(); // CS3011
// OK
[CLSCompliant(false)]
public void mf2()
{
}
}
public class C : I
{
public override int mf()
{
return 1;
}
// CS3012.cs
// compile with: /W:1
[module:System.CLSCompliant(true)] // CS3012
public class C
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS3014.cs
using System;
// [assembly:CLSCompliant(true)]
public class I
{
[CLSCompliant(true)] // CS3014
public void mf()
{
}
// CS3015.cs
// compile with: /target:library
using System;
[assembly:CLSCompliant(true)]
public class MyAttribute : Attribute
{
public MyAttribute(int[] ai) {} // CS3015
// try the following line instead
// public MyAttribute(int ai) {}
}
Referencia de Visual C#: errores y advertencias
// CS3016.cs
using System;
[assembly : CLSCompliant(true)]
[C(new int[] {1, 2})] // CS3016
// try the following line instead
// [C()]
class C : Attribute
{
public C()
{
}
public C(int[] a)
{
}
// CS3017.cs
// compile with: /target:module
using System;
[module: CLSCompliant(true)]
[assembly: CLSCompliant(false)] // CS3017
// Try this line instead:
// [assembly: CLSCompliant(true)]
class C
{
static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS3018.cs
// compile with: /target:library
using System;
[assembly: CLSCompliant(true)]
[CLSCompliant(false)]
public class Outer
{
[CLSCompliant(true)] // CS3018
public class Nested {}
// OK
public class Nested2 {}
[CLSCompliant(false)]
public class Nested3 {}
}
Referencia de Visual C#: errores y advertencias
// CS3022.cs
// compile with: /W:1
using System;
[assembly: CLSCompliant(true)]
[CLSCompliant(true)]
public class C
{
public void F([CLSCompliant(true)] int i)
{
}
// C3023.cs
[assembly:System.CLSCompliant(true)]
public class Test
{
[return:System.CLSCompliant(true)] // CS3023
// Try this instead:
// [method:System.CLSCompliant(true)]
public static int Main()
{
return 0;
}
}
Referencia de Visual C#: errores y advertencias
// CS3026.cs
[assembly:System.CLSCompliant(true)]
public class Test
{
public volatile int v0 =0; // CS3026
// To resolve remove the CLS-CComplient attribute.
public static void Main() { }
}
Referencia de Visual C#: errores y advertencias
// CS0108.cs
// compile with: /W:2
using System;
namespace x
{
public class clx
{
public int i = 1;
}
// CS0114.cs
// compile with: /W:2 /warnaserror
abstract public class clx
{
public abstract void f();
}
// CS0162.cs
// compile with: /W:2
public class A
{
public static void Main()
{
goto lab1;
{
// The following statements cannot be reached:
int i = 9; // CS0162
i++;
}
lab1:
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0164.cs
// compile with: /W:2
public class a
{
public int i = 0;
// CS0251.cs
// compile with: /W:2
class MyClass
{
public static void Main()
{
int[] myarray = new int[] {1,2,3};
try
{
myarray[-1]++; // CS0251
// try the following line instead
// myarray[1]++;
}
catch (System.IndexOutOfRangeException e)
{
System.Console.WriteLine("{0}", e);
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0252.cs
// compile with: /W:2
using System;
class MyClass
{
public static void Main()
{
string s = "11";
object o = s + s;
bool b = o == s; // CS0252
// try the following line instead
// bool b = (string)o == s;
}
}
Referencia de Visual C#: errores y advertencias
// CS0253.cs
// compile with: /W:2
using System;
class MyClass
{
public static void Main()
{
string s = "11";
object o = s + s;
bool c = s == o; // CS0253
// try the following line instead
// bool c = s == (string)o;
}
}
Referencia de Visual C#: errores y advertencias
// CS0278.cs
using System.Collections.Generic;
public class myTest
{
public static void TestForeach<W>(W w)
where W: IEnumerable<int>, IEnumerable<string>
{
foreach (int i in w) {} // CS0278
}
}
Referencia de Visual C#: errores y advertencias
// CS0279.cs
using System;
using System.Collections;
public class myTest : IEnumerable
{
IEnumerator IEnumerable.GetEnumerator()
{
yield return 0;
}
// CS0280.cs
using System;
using System.Collections;
// CS0435_1.cs
// compile with: /t:library
public class Util
{
public class A { }
}
// CS0435_2.cs
// compile with: /r:CS0435_1.dll
using System;
namespace Util
{
public class A { }
}
// CS0436_b.cs
// compile with: /reference:CS0436_a.dll
// CS0436 expected
public class A {
public void Test() {
System.Console.WriteLine("CS0436_b");
}
}
// CS0437_b.cs
// compile with: /reference:CS0437_a.dll /W:2
// CS0437 expected
class Util
{
public class A {
public void Test() {
System.Console.WriteLine("CS0437_b.cs");
}
}
}
// CS0440.cs
// Compile with: /W:1
// CS0458.cs
using System;
public class Test
{
public static void Main()
{
int a = 5;
int? b = a + null; // CS0458
int? qa = 15;
b = qa + null; // CS0458
b -= null; // CS0458
int? qa2 = null;
b = qa2 + null; // CS0458
qa2 -= null; // CS0458
}
}
Referencia de Visual C#: errores y advertencias
// CS0464.cs
class MyClass
{
public static void Main()
{
int? i = 0;
if (i < null) ; // CS0464
i++;
}
}
Referencia de Visual C#: errores y advertencias
// CS0467.cs
interface IList
{
int Count { get; set; }
}
interface ICounter
{
void Count(int i);
}
class Driver
{
void Test(IListCounter x)
{
x.Count = 1;
x.Count(1); // CS0467
// To resolve change the method name "Count" to another name.
}
// CS0618.cs
// compile with: /W:2
using System;
public class C
{
[Obsolete("Use newMethod instead", false)] // warn if referenced
public static void m2()
{
}
class MyClass
{
public static void Main()
{
C.m2(); // CS0618
}
}
Referencia de Visual C#: errores y advertencias
// CS0652.cs
// compile with: /W:2
public class Class1
{
private static byte i = 0;
public static void Main()
{
short j = 256;
if (i == 256) // CS0652, 256 is out of range for byte
i = 0;
}
}
Referencia de Visual C#: errores y advertencias
En este caso se eliminará el valor original, como por ejemplo null, de la variable thisType cuando el bloque using termine la
ejecución, pero no se eliminará el objeto thisType creado dentro del bloque, aunque eventualmente se recogerá como
elemento no utilizado.
Para resolver este error, utilice el siguiente formulario.
using (thisType f = new thisType())
{
...
}
// CS0728.cs
using System;
public class ValidBase : IDisposable
{
public void Dispose() { }
}
// CS1571.cs
// compile with: /W:2 /doc:x.xml
// CS1572.cs
// compile with: /W:2 /doc:x.xml
// CS1587.cs
// compile with: /W:2 /doc:x.xml
/// <summary>test</summary> // CS1587, tag not allowed on namespace
namespace MySpace
{
class MyClass
{
public static void Main()
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS1698_b.cs
// compile with: /target:library /reference:CS1698_a.dll /keyfile:mykey.snk
public class CS1698_b : CS1698_a {}
// CS1698_c.cs
// compile with: /target:library /out:cs1698_a.dll /reference:cs1698_b.dll /keyfile:mykey.s
nk
// CS1698 expected
[assembly:System.Reflection.AssemblyVersion("3")]
public class CS1698_c : CS1698_b {}
public class CS1698_a {}
Referencia de Visual C#: errores y advertencias
// CS1701_a.cs
// compile with: /target:library /out:cs1701_d.dll /keyfile:mykey.snk
using System.Reflection;
[assembly:AssemblyVersion("1.0")]
public class A {
public void M1() {}
}
public class C1 {}
Éste es el código que crea la versión más reciente del ensamblado CS1701_d. Observe que se compila en un directorio
diferente que la versión antigua. Esto es necesario porque los archivos de resultados tienen los mismos nombres.
// CS1701_b.cs
// compile with: /target:library /out:c:\\cs1701_d.dll /keyfile:mykey.snk
using System.Reflection;
[assembly:AssemblyVersion("2.0")]
public class A {
public void M2() {}
public void M1() {}
}
public class C2 {}
public class C1 {}
// CS1701_c.cs
// compile with: /target:library /reference:A2=c:\\cs1701_d.dll /reference:A1=cs1701_d.dll
Este ejemplo llama a los métodos utilizando dos alias diferentes de A. que El ejemplo siguiente genera C1701.
// CS1701_d.cs
// compile with: /reference:c:\\CS1701_d.dll /reference:CS1701_c.dll
// CS1701 expected
class Tester {
public static void Main() {
Ref.A1().M1();
Ref.A2().M2();
}
}
Referencia de Visual C#: errores y advertencias
// CS1710.cs
// To resolve this warning, delete one of the duplicate <typeparam>'s.
using System;
class Stack<ItemType>
{
}
class CMain
{
public static void Main()
{
// Closed constructed type Stack<int>.
Stack<int> stackInt = new Stack<int>();
MyStackWrapper<int> MyStackWrapperInt =
new MyStackWrapper<int>(stackInt);
}
}
Referencia de Visual C#: errores y advertencias
// cs1711.cs
// compile with: /doc:cs1711.xml
// CS1711 expected
using System;
///<typeparam name="WrongName">can be an int</typeparam>
class CMain
{
public static void Main() { }
}
Referencia de Visual C#: errores y advertencias
// CS3019.cs
// compile with: /W:2
using System;
[assembly: CLSCompliant(true)]
Vea también
Conceptos
Common Language Specification
Referencia de Visual C#: errores y advertencias
// CS3021.cs
using System;
// Uncomment the following line to declare the assembly CLS Compliant,
// and avoid the warning without removing the attribute on the class.
//[assembly: CLSCompliant(true)]
Vea también
Conceptos
Common Language Specification
Referencia de Visual C#: errores y advertencias
// CS0067.cs
// compile with: /W:3
using System;
delegate void MyDelegate();
class MyClass
{
public event MyDelegate evt; // CS0067
// uncomment TestMethod to resolve this CS0067
/*
private void TestMethod()
{
if (evt != null)
evt();
}
*/
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0105.cs
// compile with: /W:3
using System;
using System; // CS0105
public class a
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0168.cs
// compile with: /W:3
public class clx
{
public int i;
}
// CS0219.cs
// compile with: /W:3
public class MyClass
{
public static void Main()
{
int a = 0; // CS0219
}
}
Referencia de Visual C#: errores y advertencias
partial struct A
{
int i;
}
partial struct A
{
int j;
}
Referencia de Visual C#: errores y advertencias
// CS0414
// compile with: /W3
class C
{
private int i = 1; // CS0414
// cs0419.cs
// compile with: /doc:x.xml /W:3
interface I
{
/// text for F(void)
void F();
/// text for F(int)
void F(int i);
}
/// text for class MyClass
public class MyClass
{
/// <see cref="I.F"/>
public static void MyMethod(int i)
{
}
/* Try this instead:
/// <see cref="I.F(int)"/>
public static void MyMethod(int i)
{
}
*/
/// text for Main
public static void Main ()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0469.cs
// compile with: /W:2
class Test
{
static void Main()
{
char c = (char)180;
switch (c)
{
case (char)127:
break;
case (char)180:
goto case 127; // CS0469
// try the following line instead
// goto case (char) 127;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0642.cs
// compile with: /W:3
class MyClass
{
public static void Main()
{
int i;
// CS0659.cs
// compile with: /W:3 /target:library
class Test
{
public override bool Equals(object o) { return true; } // CS0659
}
// OK
class Test2
{
public override bool Equals(object o) { return true; }
public override int GetHashCode() { return 0; }
}
Referencia de Visual C#: errores y advertencias
// CS0660.cs
// compile with: /W:3 /warnaserror
class Test // CS0660
{
public static bool operator == (object o, Test t)
{
return true;
}
// CS0661.cs
// compile with: /W:3
class Test // CS0661
{
public static bool operator == (object o, Test t)
{
return true;
}
// CS0665.cs
// compile with: /W:3
class Test
{
public static void Main()
{
bool i = false;
if (i = true) // CS0665
// try the following line instead
// if (i == true)
{
}
System.Console.WriteLine(i);
}
}
Referencia de Visual C#: errores y advertencias
// CS0675.cs
// compile with: /W:3
using System;
// CS0693.cs
// compile with: /W:3 /target:library
class Outer<T>
{
class Inner<T> {} // CS0693
// try the following line instead
// class Inner<U> {}
}
Referencia de Visual C#: errores y advertencias
// CS1700.cs
// compile with: /target:library
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("app2, Retargetable=f")] // CS1700
[assembly:InternalsVisibleTo("app2")] // OK
Referencia de Visual C#: errores y advertencias
En un constructor donde el parámetro tiene el mismo nombre que el campo, no se ha utilizado la palabra clave this: es
probable que se quiera decir this.a = a.
Ejemplo
El código siguiente genera la advertencia CS1717.
// CS1717.cs
// compile with: /W:3
public class Test
{
public static void Main()
{
int x = 0;
x = x; // CS1717
}
}
Referencia de Visual C#: errores y advertencias
// CS1718.cs
using System;
public class Tester
{
public static void Main()
{
int i = 0;
if (i == i) { // CS1718.cs
//if (true) {
i++;
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0028.cs
// compile with: /W:4 /warnaserror
public class a
{
public static double Main(int i) // CS0028
// Try the following line instead:
// public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0078.cs
// compile with: /W:4
class test {
public static void TestL(long i)
{
}
public static void TestL(int i)
{
}
// CS0109.cs
// compile with: /W:4
namespace x
{
public class a
{
public int i;
}
public class b : a
{
public new int i;
public new int j; // CS0109
public static void Main()
{
}
}
}
Referencia de Visual C#: errores y advertencias
// CS0402.cs
// compile with: /W:4
class C<T>
{
public static void Main() // CS0402
{
}
}
class CMain
{
public static void Main() {}
}
Referencia de Visual C#: errores y advertencias
// CS0429.cs
public class cs0429
{
public static void Main()
{
if (false && myTest()) // CS0429
// Try the following line instead:
// if (true && myTest())
{
}
else
{
int i = 0;
i++;
}
}
// CS0628.cs
// compile with: /W:4
sealed class C
{
protected int i; // CS0628
}
class MyClass
{
public static void Main()
{
}
}
Referencia de Visual C#: errores y advertencias
// CS0649.cs
// compile with: /W:4
using System.Collections;
class MyClass
{
Hashtable table; // CS0649
// You may have intended to initialize the variable to null
// Hashtable table = null;
// CS1573.cs
// compile with: /W:4
public class MyClass
{
/// <param name='Int1'>Used to indicate status.</param>
// enter a comment for Char1?
public static void MyMethod(int Int1, char Char1)
{
}
// CS1591.cs
// compile with: /W:4 /doc:x.xml
/// text
public class Test
{
// /// text
public static void Main() // CS1591, remove "//" from previous line
{
}
}
Referencia de Visual C#: errores y advertencias
// CS1712.cs
// compile with: /doc:cs1712.xml
using System;
class Test
{
public static void Main() {}
/// <param name="j"> This is the j parameter.</param>
/// <typeparam name="T"> This is the T type parameter.</typeparam>
public void bar<T,S>(int j) {} // CS1712
}
Referencia de Visual C#: errores y advertencias
// CS1725.cs
// compile with: /target:library
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("partial01,version=1.1.0.0")] // CS1725
// try the following line instead
// [assembly:InternalsVisibleTo("partial01")]
// CS1726.cs
// compile with: /keyfile:CS1726.key /target:library
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("UnsignedAssembly")] // CS1726
// try the following line instead
// [assembly:InternalsVisibleTo("SignedAssembly, PublicKey=00240000048000009400000006020000
00240000525341310004000001000100031d7b6f3abc16c7de526fd67ec2926fe68ed2f9901afbc5f1b6b428bf6
cd9086021a0b38b76bc340dc6ab27b65e4a593fa0e60689ac98dd71a12248ca025751d135df7b98c5f9d09172f7
b62dabdd302b2a1ae688731ff3fc7a6ab9e8cf39fb73c60667e1b071ef7da5838dc009ae0119a9cbff2c581fc0f
2d966b77114b2c4")]
class A {}
Referencia de Visual C#: errores y advertencias
// Comparison:
if (i == null) // CS0472
// To resolve, use a valid value for i.
counter++;
return counter;
}
}
Referencia de Visual C#: errores y advertencias
// CS1727.cs
// compile with: /errorreport:send
// CS1727 expected
class Test {}
Referencia de Visual C#: errores y advertencias
// CS735.cs
// compile with: /target:library
using System.Runtime.CompilerServices;
[assembly:TypeForwardedTo(typeof(int[]))] // CS0735
[assembly:TypeForwardedTo(typeof(string))] // OK
Referencia de Visual C#: errores y advertencias
// CS1057.cs
using System;
Ejemplo
El código siguiente genera el error CS1058.
// CS1058.cs
// CS1058 expected
using System.Runtime.CompilerServices;
class TestClass
{
static void Main()
{
try {}
catch (System.Exception e) {
System. Console.WriteLine("Caught exception {0}", e);
}
Terminología de C#
Campo [field]
Miembro de datos de una clase o estructura a la que se tiene acceso directamente.
Clase [class]
Tipo de datos que describe un objeto. Las clases contienen datos y métodos que actúan en los datos. Para obtener más
información, vea Clases.
Clase base [base class]
Clase heredada por otra clase 'derivada'. Para obtener más información, vea Herencia.
Clase derivada [derived class]
Clase que utiliza la herencia para obtener, aumentar o modificar el comportamiento y los datos de otra clase 'base'. Para
obtener más información, vea Herencia.
Constructor [constructor]
Método especial de una clase o estructura que inicializa objetos de ese tipo. Para obtener más información, vea
Constructores (Guía de programación de C#).
Delegado [delegate]
Un delegado es un tipo que hace referencia a un método. Cuando se asigna un método a un delegado, éste se comporta
exactamente como el método. Para obtener más información, vea Delegados (Guía de programación de C#).
Descriptor de acceso [accessor]
Método que establece o recupera el valor de un miembro de datos privado asociado a una propiedad. Las propiedades de
lectura y escritura tienen descriptores de acceso get y set. Las propiedades que son de sólo lectura pueden tener sólo un
descriptor de acceso get. Para obtener más información, vea Propiedades.
Destructor [destructor]
Método especial de una clase o estructura que prepara la instancia para su destrucción por el sistema. Para obtener más
información, vea Destructores (Guía de programación de C#).
Evento [event]
Miembro de una clase o estructura que envía notificaciones de un cambio. Para obtener más información, vea
Events (Guía de programación de C#).
Genéricos [generics]
Los genéricos permiten definir una clase o método definidos con un parámetro de tipo. Cuando el código de cliente crea
instancias del tipo, especifica un tipo determinado como un argumento. Para obtener más información, vea
Genéricos (Guía de programación de C#).
Herencia [inheritance]
C# admite la herencia, de manera que una clase que se deriva de otra clase, conocida como clase base, hereda los mismos
métodos y propiedades. La herencia implica clases base y clases derivadas. Para obtener más información, vea Herencia.
IDE [IDE]
Entorno de desarrollo integrado. Aplicación que proporciona la interfaz de usuario unificada para las distintas herramientas
de desarrollo como el compilador, depurador, editor de código y diseñadores.
Interfaz [interface]
Tipo que contiene sólo las firmas de métodos públicos, eventos y delegados. Un objeto que hereda la interfaz debe
implementar todos los métodos y eventos definidos en la interfaz. Las clases o estructuras pueden heredar cualquier número
de interfaces. Para obtener más información, vea Interfaces (Guía de programación de C#).
Iterador [iterator]
Un iterador es un método que permite a los consumidores de una clase que contiene una colección o matriz utilizar
foreach, in (Referencia de C#) para recorrer esa colección o matriz.
Método [method]
Bloque de código con nombre que proporciona el comportamiento de una clase o estructura.
Método anónimo [anonymous method]
Un método anónimo es un bloque de código que se pasa como parámetro a un delegado. Para obtener más información,
vea Métodos anónimos (Guía de programación de C#).
Miembro [member]
Campo, propiedad, método o evento declarado en una clase o estructura.
Miembro accesible [accessible member]
Miembro al que se puede tener acceso mediante un tipo determinado. Un miembro accesible para un tipo no es
necesariamente accesible para otro tipo. Para obtener más información, vea
Modificadores de acceso (Guía de programación de C#) y Ensamblados de confianza (Guía de programación de C#).
Miembro inaccesible [inaccessible member]
Miembro al que no se puede tener acceso mediante un tipo determinado. Un miembro inaccesible para un tipo no es
necesariamente inaccesible para otro tipo. Para obtener más información, vea
Modificadores de acceso (Guía de programación de C#).
Modificador de acceso [access modifier]
Una palabra clave, como private, protected, internal o public, que restringe el acceso a un tipo o miembro de tipo. Para
obtener más información, vea Modificadores de acceso (Guía de programación de C#).
Objeto [object]
Instancia de una clase. Un objeto existe en memoria y tiene los datos y métodos que actúan sobre los datos. Para obtener
más información, vea Objetos, clases y estructuras (Guía de programación de C#).
Pila de llamadas [call stack]
Serie de llamadas a métodos que conducen del principio del programa a la instrucción que se ejecuta actualmente en tiempo
de ejecución.
Propiedad [property]
Miembro de datos al que se obtiene acceso por medio de un descriptor de acceso. Para obtener más información, vea
Propiedades (Guía de programación de C#).
Refactorización [refactoring]
Reutilizar código previamente escrito. El Editor de código de Visual C# Express puede cambiar de manera inteligente el
formato del código a, por ejemplo, convertir un bloque de código resaltado en un método. Para obtener más información,
vea Refactorización.
static [static]
Una clase o método declarado como static existe sin crearse primero instancias utilizando la palabra clave new. Main() es un
método estático. Para obtener más información, vea Clases estáticas y sus miembros (Guía de programación de C#).
struct [struct]
Tipo de datos compuesto que se utiliza normalmente para contener unas variables que tienen alguna relación lógica. Las
estructuras también pueden contener métodos y eventos. Las estructuras no admiten la herencia pero admiten interfaces.
Una estructura es un tipo de valor, mientras que una clase es un tipo de referencia. Para obtener más información, vea
Estructuras (Guía de programación de C#).
Tipo anidado [nested type]
Tipo declarado dentro de la declaración de otro tipo.
Tipo de referencia [reference type]
Tipo de datos. Una variable declarada como un tipo de referencia señala una ubicación donde se almacenan los datos. Para
obtener más información, vea Tipos de referencia.
Tipo de valor [value type]
Un tipo de valor es un tipo de datos que se asigna en la pila, a diferencia de un tipo de referencia que está asignado en el
montón. Los tipos integrados, entre los que se incluyen los tipos numéricos así como el tipo de estructura y el tipo que
acepta valores NULL, son todos tipos de valor. El tipo class y el tipo string son tipos de referencia. Para obtener más
información, vea Tipos de valores (Referencia de C#).
Tipo inmutable [immutable type]
Tipo cuyos datos de instancia (campos y propiedades) no cambian después de crear la instancia. La mayoría de los tipos de
valor son inmutables.
Tipo mutable [mutable type]
Tipo cuyos datos de instancia (campos y propiedades) pueden cambiar después de crear la instancia. La mayoría de los
tipos de referencia son mutables.
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Referencia de C#
Referencia del lenguaje C#
Ejemplos de Visual C#
Puede tener acceso al código de ejemplo explorando los resúmenes de los ejemplos de esta sección. Cada resumen contiene
un vínculo para abrir o copiar los archivos del ejemplo. Además, el .NET Framework SDK incluye tecnología y ejemplos de
aplicaciones, así como tutoriales rápidos que muestran las características de .NET Framework y el código de Visual C#.
Los tutoriales son la forma más rápida de comprender lo que ofrece la tecnología de .NET Framework a los programadores.
Los tutoriales rápidos son una serie de ejemplos y documentación complementaria diseñados para informarle rápidamente de
la sintaxis, arquitectura y eficacia de Visual Studio y .NET Framework. Estos tutoriales incluyen ejemplos sobre aplicaciones
ASP.NET y formularios Windows Forms, así como muchas aplicaciones de aprendizaje que incluyen las características más
atractivas de la tecnología de .NET Framework.
Para tener acceso a los tutoriales rápidos, haga clic en Inicio, elija Programas, Microsoft .NET Framework SDK v2.0 y, a
continuación, haga clic en Tutoriales rápidos. Se muestra una página Web de la aplicación "Tutoriales rápidos de Microsoft
.NET Framework SDK". Para ejecutar los tutoriales rápidos, siga las instrucciones de esta página, que configura la base de datos
de ejemplos y finaliza la instalación. Para obtener más información, vea Ejemplos y tutoriales.
Nota
Los usuarios de Visual C# Express verán el mensaje siguiente al abrir el archivo de solución (.sln) de Visual Studio para cada
uno de estos ejemplos: "Las carpetas de soluciones no son compatibles con esta versión de de Visual Studio. La carp
eta de soluciones 'Solution Items' se mostrará como no disponible". Aunque esta carpeta no está disponible en Visual
C# Express, puede generar y ejecutar igualmente los proyectos.
En esta sección
Ejemplos preliminares
Ejemplo de delegados anónimos Muestra el uso de delegados sin nombre para reducir la complejidad de la a
plicación.
Ejemplo de clases de colección Muestra cómo crear clases de colección no genéricas que pueden utilizarse
con la instrucción foreach.
Ejemplo de clases genéricas (C#) Muestra cómo crear clases de colección genéricas que pueden utilizarse con
la instrucción foreach.
Ejemplo de parámetros de la línea de comandos Muestra el procesamiento sencillo de la línea de comandos y la indización d
e matrices.
Ejemplo de métodos condicionales Este tutorial trata sobre los métodos condicionales, los cuales proporcionan
un poderoso mecanismo con el que las llamadas a métodos se pueden incl
uir u omitir dependiendo de si se ha definido o no un símbolo.
Ejemplo de implementación explícita de interfaces Muestra cómo implementar explícitamente los miembros de interfaz.
Ejemplo de indizadores Muestra cómo utilizar la notación de matrices para obtener acceso a un obj
eto.
Ejemplo de propiedades indizadas Muestra cómo implementar una clase que utiliza propiedades indizadas. La
s propiedades indizadas permiten utilizar una clase que representa una cole
cción, semejante a una matriz, de diferentes tipos de elementos.
Ejemplo de propiedades Muestra cómo se declaran y utilizan las propiedades, así como el uso de las
propiedades abstractas.
Ejemplo Operator Overloading Muestra cómo las clases definidas por el usuario pueden sobrecargar opera
dores.
Ejemplo User-Defined Conversions Muestra cómo definir conversiones a o desde tipos definidos por el usuario.
Ejemplo del control de versiones Ilustra el control de versiones en C# mediante el uso de las palabras clave o
verride y new.
Ejemplo de devolución de resultados Muestra cómo utilizar la palabra clave yield para filtrar los elementos de un
a colección.
Ejemplos intermedios y avanzados
Ejemplo de atributos Este tutorial muestra cómo crear clases de atributos personalizados, utilizarlas en el c
ódigo y consultarlas a través del mecanismo de reflexión.
Interoperabilidad COM, parte 1: ejemplo Muestra cómo utilizar C# para interoperar con objetos COM.
Interoperabilidad COM, parte 2: ejemplo Este tutorial muestra el uso de un servidor C# con un cliente COM de C++.
Ejemplo de bibliotecas Muestra cómo utilizar las opciones del compilador para crear una biblioteca DLL para
varios archivos de código fuente, así como su uso en otros programas.
Ejemplo de OLE DB Muestra cómo utilizar una base de datos de Microsoft Access desde C#. Enseña a crea
r un conjunto de datos y agregarle tablas de una base de datos.
Ejemplo de tipos parciales Muestra cómo las clases y estructuras se pueden definir en varios archivos de código
fuente de C#.
Ejemplo Platform Invoke Muestra cómo llamar a las funciones exportadas de un archivo DLL desde C#.
Ejemplo de seguridad Trata sobre la seguridad en .NET Framework y muestra dos formas de modificar los p
ermisos de seguridad en C# mediante: clases y atributos de permisos.
Ejemplo de subprocesamiento Muestra varias actividades con subprocesos, como la creación y ejecución de un subp
roceso, la sincronización e interacción entre subprocesos y el uso de un grupo de sub
procesos.
Ejemplo XML Documentation Muestra cómo documentar el código desarrollado usando XML.
Secciones relacionadas
Ejemplos y tutoriales | Tutoriales de Visual C#
Ejemplos de Visual C#
cd HelloWorld1
csc Hello1.cs
Hello1
3. Escriba lo siguiente:
cd ..\HelloWorld2
csc Hello2.cs
Hello2
4. Escriba lo siguiente:
cd ..\HelloWorld3
csc Hello3.cs
Hello3 A B C D
5. Escriba lo siguiente:
cd ..\HelloWorld4
csc Hello4.cs
Hello4
Vea también
Conceptos
Hello World, su primer programa (Guía de programación de C#)
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc cmdline1.cs
cmdline1 A B C
Vea también
Tareas
Cómo: Mostrar argumentos de línea de comandos (Guía de programación de C#)
Cómo: Obtener acceso a argumentos de línea de comandos mediante Foreach (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo Arrays
Download sample
En este ejemplo se describen las matrices y se muestra cómo funcionan en C#. Para obtener más información, vea
Matrices (Guía de programación de C#).
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc arrays.cs
arrays
Vea también
Referencia
Pasar matrices como parámetros (Guía de programación de C#)
Pasar matrices mediante Ref y Out (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de propiedades
Download sample
En este ejemplo se muestra cómo las propiedades son una parte integrante del lenguaje de programación C#. Se explica cómo
se declaran y utilizan las propiedades. Vea Propiedades (Guía de programación de C#) para obtener más información.
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc person.cs
person
Vea también
Tareas
Cómo: Declarar y utilizar propiedades de lectura y escritura (Guía de programación de C#)
Cómo: Definir propiedades abstractas (Guía de programación de C#)
Referencia
Comparación entre propiedades e indizadores (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de bibliotecas
Download sample
En este ejemplo se muestra cómo crear y utilizar un archivo DLL en C#.
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
copy ..\Functions\Functions.dll .
csc /out:FunctionTest.exe /R:Functions.DLL FunctionClient.cs
FunctionTest 3 5 10
Vea también
Tareas
Cómo: Crear y utilizar archivos DLL de C# (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc versioning.cs
versioning
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc tokens.cs
tokens
csc tokens2.cs
tokens2
Vea también
Tareas
Cómo: Obtener acceso a una clase de colección mediante Foreach (Guía de programación de C#)
Referencia
System.Collections.Generic
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Tipos de colección utilizados normalmente
Ejemplos de Visual C#
Ejemplo Structs
Download sample
Este ejemplo presenta la sintaxis y el modo de uso de las estructuras. Asimismo, trata las diferencias principales entre clases y
estructuras. Para obtener más información, vea Objetos, clases y estructuras (Guía de programación de C#).
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc struct1.cs
struct1
csc struct2.cs
struct2
Vea también
Tareas
Cómo: Saber las diferencias entre pasar a un método una estructura y una referencia a clase (Guía de programación de C#)
Referencia
struct (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de indizadores
Download sample
En este ejemplo se muestra cómo las clases de C# pueden declarar indizadores para ofrecer un acceso a las clases similar al de
las matrices.
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc indexer.cs
2. El programa de ejemplo invierte los bytes de un archivo pasado como argumento de la línea de comandos. Por ejemplo,
para invertir los bytes en Test.txt y ver el resultado, emita los siguientes comandos:
indexers Test.txt
type Test.txt
3. Para restablecer el archivo invertido a su estado normal, ejecute el programa sobre el mismo archivo otra vez.
Vea también
Referencia
Utilizar indizadores (Guía de programación de C#)
Indizadores en interfaces (Guía de programación de C#)
Comparación entre propiedades e indizadores (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc indexedproperty.cs
indexedproperty
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc conversion.cs
conversion
csc structconversion.cs
structconversion
Vea también
Tareas
Cómo: Implementar conversiones entre estructuras definidas por el usuario (Guía de programación de C#)
Referencia
Tabla de conversiones numéricas implícitas (Referencia de C#)
Tabla de conversiones numéricas explícitas (Referencia de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc generics.cs
generics
Comentarios
Este ejemplo es una demostración que no debe utilizarse sin modificar el código de producción. Con el fin de obtener un
código de producción de calidad, es aconsejable utilizar las clases de colección del el espacio de nombres
System.Collections.Generic siempre que sea posible.
Vea también
Referencia
System.Collections.Generic
Conceptos
Genéricos (Guía de programación de C#)
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc complex.cs
complex
csc dbbool.cs
dbbool
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de delegados
Download sample
Este ejemplo trata sobre los tipos delegados. Se explica cómo asignar delegados a métodos de instancia y estáticos, y cómo
combinarlos para crear delegados de multidifusión.
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc bookstore.cs
bookstore
csc compose.cs
compose
Vea también
Tareas
Cómo: Combinar delegados (delegados de multidifusión) (Guía de programación de C#)
Referencia
Utilizar delegados (Guía de programación de C#)
Conceptos
Delegados (Guía de programación de C#)
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de eventos
Download sample
En este ejemplo se explica cómo declarar, invocar y configurar eventos en C#. Para obtener más información, vea
Eventos (Guía de programación de C#).
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc events1.cs
events1
csc events2.cs
events2
Vea también
Tareas
Cómo: Suscribir y cancelar la suscripción a eventos (Guía de programación de C#)
Cómo: Publicar eventos que cumplan las directrices de .NET Framework (Guía de programación de C#)
Cómo: Producir eventos de una clase base en clases derivadas (Guía de programación de C#)
Cómo: Implementar eventos de interfaz (Guía de programación de C#)
Cómo: Utilizar un diccionario para almacenar instancias de eventos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc explicit1.cs
explicit1
csc explicit2.cs
explicit2
Vea también
Tareas
Cómo: Implementar explícitamente miembros de interfaz (Guía de programación de C#)
Cómo: Implementar explícitamente miembros de interfaz con herencia (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Vea también
Referencia
Conditional (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
type XMLsample.xml
Vea también
Tareas
Cómo: Utilizar las características de documentación XML (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
csc PinvokeTest.cs
PinvokeTest
csc Marshal.cs
Marshal
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Para generar y ejecutar los ejemplos de interoperabilidad COM, parte 1, desde la línea de comandos
1. Utilice el comando Cambiar directorio para cambiar al directorio Interop1.
2. Escriba lo siguiente:
csc interop2.cs
interop2 %windir%\clock.avi
Vea también
Referencia
Interoperabilidad (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
copy ..\CSharpServer\CSharpServer.cs
3. Compile el servidor:
4. Compile el cliente (compruebe que las variables de ruta de acceso y de entorno están configuradas correctamente con
vcvars32.bat):
cl COMClient.cpp
5. Ejecute el cliente:
COMClient friend
Vea también
Referencia
Interoperabilidad (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de atributos
Download sample
En este ejemplo se muestra cómo crear clases de atributos personalizados, utilizarlos en el código y consultarlos a través del
mecanismo de reflexión. Para obtener más información sobre los atributos, vea Atributos (Guía de programación de C#).
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc AttributesTutorial.cs
AttributesTutorial
Vea también
Tareas
Cómo: Crear una unión de C/C++ mediante atributos (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de seguridad
Download sample
En este ejemplo se muestra cómo modificar los permisos de seguridad mediante clases de permiso y atributos de permiso.
Para obtener información adicional, vea Seguridad (Guía de programación de C#).
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc ImperativeSecurity.cs
ImperativeSecurity
csc DeclarativeSecurity.cs
DeclarativeSecurity
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de subprocesamiento
Download sample
Este ejemplo muestra las técnicas de subprocesamiento siguientes. Para obtener más información, vea
Subprocesamiento (Guía de programación de C#).
Crear, iniciar y finalizar un subproceso
Utilizar un grupo de subprocesos
Sincronización e interacción de subprocesos
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
cd ThreadStartStop
csc ThreadStartStop.cs
ThreadStartStop
3. Escriba lo siguiente:
cd ..\ThreadPool
csc ThreadPool.cs
ThreadPool
4. Escriba lo siguiente:
cd ..\ThreadSync
csc ThreadSync.cs
ThreadSync
Vea también
Tareas
Cómo: Crear y terminar subprocesos (Guía de programación de C#)
Cómo: Utilizar un grupo de subprocesos (Guía de programación de C#)
Cómo: Sincronizar un subproceso productor y un subproceso consumidor (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
cd FastCopy
csc FastCopy.cs /unsafe
FastCopy
3. Escriba lo siguiente:
cd ..\ReadFile
csc ReadFile.cs /unsafe
ReadFile ReadFile.cs
4. Escriba lo siguiente:
cd ..\PrintVersion
csc PrintVersion.cs /unsafe
PrintVersion
Vea también
Tareas
Cómo: Utilizar punteros para copiar una matriz de bytes (Guía de programación de C#)
Cómo: Utilizar la función ReadFile de Windows (Guía de programación de C#)
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo de OLE DB
Download sample
En este ejemplo se muestra cómo utilizar una base de datos de Microsoft Access desde C#. Enseña a crear un conjunto de
datos y agregarle tablas de una base de datos. La base de datos utilizada en el programa de ejemplo, BugTypes.mdb, es un
archivo .mdb de Microsoft Access 2000.
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o consecuentes en caso de que el código de ejemplo se utilice para propósitos distintos de aquellos para los que se concibió.
csc oledbsample.cs
oledbsample
Vea también
Conceptos
Guía de programación de C#
Otros recursos
Ejemplos de Visual C#
Obtener acceso a datos (Visual Studio)
Ejemplos de Visual C#
csc Yield.cs
Yield
Vea también
Referencia
yield (Referencia de C#)
Conceptos
Iteradores (Guía de programación de C#)
Otros recursos
Ejemplos de Visual C#
Ejemplo de clases genéricas (C#)
Ejemplos de Visual C#
csc AnonymousDelegates.cs
AnonymousDelegates
Vea también
Referencia
Métodos anónimos (Guía de programación de C#)
Conceptos
Delegados (Guía de programación de C#)
Otros recursos
Ejemplos de Visual C#
Referencia de C#
Ejemplos de Visual C#
csc PartialTypes.cs
PartialTypes
Vea también
Referencia
partial (Referencia de C#)
Definiciones de clase parciales (Guía de programación de C#)
Otros recursos
Ejemplos de Visual C#
Ejemplos de Visual C#
Ejemplo Nullable
Download sample
Este ejemplo muestra cómo utilizar tipos que aceptan valores NULL. Esta función permite a los tipos de valor tener un estado
no inicializado, o vacío, similar a la manera en que los tipos de referencia se pueden establecer en null.
Nota de seguridad
Este código de ejemplo se proporciona para ilustrar un concepto y no debe utilizarse en aplicaciones o sitios Web, ya que qui
zás no ilustre las prácticas de codificación más seguras. Microsoft no asume ninguna responsabilidad por daños incidentales
o especiales en caso de que el código de ejemplo se utilice para otros propósitos distintos de aquellos para los que se concibi
ó.
csc Boxing.cs
Boxing
csc Basics.cs
Basics
csc Operator.cs
Operator
Vea también
Conceptos
Tipos que aceptan valores NULL (Guía de programación de C#)
Otros recursos
Ejemplos de Visual C#