IntroducciónIntroduction

C# (pronunciado "si sharp" en inglés) es un lenguaje de programación sencillo, moderno, orientado a objetos y con seguridad de tipos.C# (pronounced "See Sharp") is a simple, modern, object-oriented, and type-safe programming language. C#tiene sus raíces en la familia de lenguajes C y será inmediatamente familiar para los programadores de C, C++y Java.C# has its roots in the C family of languages and will be immediately familiar to C, C++, and Java programmers. C#está normalizado por ECMA International como el estándar ECMA-334 y por ISO/IEC como el estándar iso/IEC 23270 .C# is standardized by ECMA International as the ECMA-334 standard and by ISO/IEC as the ISO/IEC 23270 standard. El C# compilador de Microsoft para el .NET Framework es una implementación compatible de ambos estándares.Microsoft's C# compiler for the .NET Framework is a conforming implementation of both of these standards.

C# es un lenguaje orientado a objetos, pero también incluye compatibilidad para programación orientada a componentes.C# is an object-oriented language, but C# further includes support for component-oriented programming. El diseño de software contemporáneo se basa cada vez más en componentes de software en forma de paquetes independientes y autodescriptivos de funcionalidad.Contemporary software design increasingly relies on software components in the form of self-contained and self-describing packages of functionality. La clave de estos componentes es que presentan un modelo de programación con propiedades, métodos y eventos; tienen atributos que proporcionan información declarativa sobre el componente; e incorporan su propia documentación.Key to such components is that they present a programming model with properties, methods, and events; they have attributes that provide declarative information about the component; and they incorporate their own documentation. C#proporciona construcciones de lenguaje para admitir directamente estos conceptos, con C# lo que se crea un lenguaje muy natural en el que crear y usar componentes de software.C# provides language constructs to directly support these concepts, making C# a very natural language in which to create and use software components.

Varias características de C# ayudan en la construcción de aplicaciones sólidas y duraderas: La recolección de elementos no utilizados reclama automáticamente la memoria ocupada por objetos no usados. el control de excepciones proporciona un enfoque estructurado y extensible para la detección y recuperación de errores. y el diseño con seguridad de tipos del lenguaje hace que sea imposible leer desde variables no inicializadas, indizar matrices más allá de sus límites o realizar conversiones de tipo no comprobadas.Several C# features aid in the construction of robust and durable applications: Garbage collection automatically reclaims memory occupied by unused objects; exception handling provides a structured and extensible approach to error detection and recovery; and the type-safe design of the language makes it impossible to read from uninitialized variables, to index arrays beyond their bounds, or to perform unchecked type casts.

C# tiene un sistema de tipo unificado.C# has a unified type system. Todos los tipos de C#, incluidos los tipos primitivos como int y double, se heredan de un único tipo object raíz.All C# types, including primitive types such as int and double, inherit from a single root object type. Por lo tanto, todos los tipos comparten un conjunto de operaciones comunes, y los valores de todos los tipos se pueden almacenar, transportar y utilizar de manera coherente.Thus, all types share a set of common operations, and values of any type can be stored, transported, and operated upon in a consistent manner. Además, C# admite tipos de valor y tipos de referencia definidos por el usuario, lo que permite la asignación dinámica de objetos, así como almacenamiento en línea de estructuras ligeras.Furthermore, C# supports both user-defined reference types and value types, allowing dynamic allocation of objects as well as in-line storage of lightweight structures.

Para asegurarse de C# que los programas y las bibliotecas pueden evolucionar con el tiempo de una manera compatible, se ha hecho mucho C#hincapié en el control de versiones en el diseño de.To ensure that C# programs and libraries can evolve over time in a compatible manner, much emphasis has been placed on versioning in C#'s design. Muchos lenguajes de programación prestan poca atención a este problema y, como resultado, los programas escritos en dichos lenguajes se interrumpen con más frecuencia de lo necesario cuando se introducen nuevas versiones de las bibliotecas dependientes.Many programming languages pay little attention to this issue, and, as a result, programs written in those languages break more often than necessary when newer versions of dependent libraries are introduced. Los aspectos C#del diseño de que se vieron afectados directamente por las consideraciones sobre el virtual control override de versiones son los modificadores y independientes, las reglas para la resolución de sobrecarga de métodos y la compatibilidad con las declaraciones explícitas de miembros de interfaz.Aspects of C#'s design that were directly influenced by versioning considerations include the separate virtual and override modifiers, the rules for method overload resolution, and support for explicit interface member declarations.

En el resto de este capítulo se describen las características esenciales C# del lenguaje.The rest of this chapter describes the essential features of the C# language. Aunque los capítulos posteriores describen las reglas y las excepciones en un modo orientado a los detalles y, a veces, de forma matemática, en este capítulo se realiza una mayor claridad y una brevedad a costa de la integridad.Although later chapters describe rules and exceptions in a detail-oriented and sometimes mathematical manner, this chapter strives for clarity and brevity at the expense of completeness. La intención es proporcionar al lector una introducción al lenguaje que facilitará la escritura de programas iniciales y la lectura de capítulos posteriores.The intent is to provide the reader with an introduction to the language that will facilitate the writing of early programs and the reading of later chapters.

Hola a todosHello world

El programa "Hola mundo" tradicionalmente se usa para presentar un lenguaje de programación.The "Hello, World" program is traditionally used to introduce a programming language. En este caso, se usa C#:Here it is in C#:

using System;

class Hello
{
    static void Main() {
        Console.WriteLine("Hello, World");
    }
}

Normalmente, los archivos de código fuente de C# tienen la extensión de archivo .cs.C# source files typically have the file extension .cs. Suponiendo que el programa "Hola mundo" se almacena en el archivo hello.cs, el programa se puede compilar con el compilador de Microsoft C# mediante la línea de comandos.Assuming that the "Hello, World" program is stored in the file hello.cs, the program can be compiled with the Microsoft C# compiler using the command line

csc hello.cs

que genera un ensamblado ejecutable denominado hello.exe.which produces an executable assembly named hello.exe. La salida generada por esta aplicación cuando se ejecuta esThe output produced by this application when it is run is

Hello, World

El programa "Hola mundo" empieza con una directiva using que hace referencia al espacio de nombres System.The "Hello, World" program starts with a using directive that references the System namespace. Los espacios de nombres proporcionan un método jerárquico para organizar las bibliotecas y los programas de C#.Namespaces provide a hierarchical means of organizing C# programs and libraries. Los espacios de nombres contienen tipos y otros espacios de nombres; por ejemplo, el espacio de nombres System contiene varios tipos, como la clase Console a la que se hace referencia en el programa, y otros espacios de nombres, como IO y Collections.Namespaces contain types and other namespaces—for example, the System namespace contains a number of types, such as the Console class referenced in the program, and a number of other namespaces, such as IO and Collections. Una directiva using que hace referencia a un espacio de nombres determinado permite el uso no calificado de los tipos que son miembros de ese espacio de nombres.A using directive that references a given namespace enables unqualified use of the types that are members of that namespace. Debido a la directiva using, puede utilizar el programa Console.WriteLine como abreviatura de System.Console.WriteLine.Because of the using directive, the program can use Console.WriteLine as shorthand for System.Console.WriteLine.

La clase Hello declarada por el programa "Hola mundo" tiene un miembro único, el método llamado Main.The Hello class declared by the "Hello, World" program has a single member, the method named Main. El Main método se declara con el static modificador.The Main method is declared with the static modifier. Mientras que los métodos de instancia pueden hacer referencia a una instancia de objeto envolvente determinada utilizando la palabra clave this, los métodos estáticos funcionan sin referencia a un objeto determinado.While instance methods can reference a particular enclosing object instance using the keyword this, static methods operate without reference to a particular object. Por convención, un método estático denominado Main sirve como punto de entrada de un programa.By convention, a static method named Main serves as the entry point of a program.

La salida del programa la genera el método WriteLine de la clase Console en el espacio de nombres System.The output of the program is produced by the WriteLine method of the Console class in the System namespace. Esta clase la proporcionan las bibliotecas de clases de .NET Framework, a las que, de forma predeterminada, el compilador de Microsoft C# hace referencia automáticamente.This class is provided by the .NET Framework class libraries, which, by default, are automatically referenced by the Microsoft C# compiler. Tenga en C# cuenta que no tiene una biblioteca en tiempo de ejecución independiente.Note that C# itself does not have a separate runtime library. En su lugar, el .NET Framework es la biblioteca en C#tiempo de ejecución de.Instead, the .NET Framework is the runtime library of C#.

Estructura del programaProgram structure

Los principales conceptos organizativos en C# son programas, espacios de nombres, tipos, miembros y ensamblados.The key organizational concepts in C# are programs, namespaces, types, members, and assemblies. Los programas de C# constan de uno o más archivos de origen.C# programs consist of one or more source files. Los programas declaran tipos, que contienen miembros y pueden organizarse en espacios de nombres.Programs declare types, which contain members and can be organized into namespaces. Las clases e interfaces son ejemplos de tipos.Classes and interfaces are examples of types. Los campos, los métodos, las propiedades y los eventos son ejemplos de miembros.Fields, methods, properties, and events are examples of members. Cuando se compilan programas de C#, se empaquetan físicamente en ensamblados.When C# programs are compiled, they are physically packaged into assemblies. Normalmente, los ensamblados tienen .exe la .dllextensión de archivo o, dependiendo de si implementan aplicaciones o bibliotecas.Assemblies typically have the file extension .exe or .dll, depending on whether they implement applications or libraries.

El ejemploThe example

using System;

namespace Acme.Collections
{
    public class Stack
    {
        Entry top;

        public void Push(object data) {
            top = new Entry(top, data);
        }

        public object Pop() {
            if (top == null) throw new InvalidOperationException();
            object result = top.data;
            top = top.next;
            return result;
        }

        class Entry
        {
            public Entry next;
            public object data;
    
            public Entry(Entry next, object data) {
                this.next = next;
                this.data = data;
            }
        }
    }
}

declara una clase denominada Stack en un espacio de nombres denominado. Acme.Collectionsdeclares a class named Stack in a namespace called Acme.Collections. El nombre completo de esta clase es Acme.Collections.Stack.The fully qualified name of this class is Acme.Collections.Stack. La clase contiene varios miembros: un campo denominado top, dos métodos denominados Push y Pop, y una clase anidada denominada Entry.The class contains several members: a field named top, two methods named Push and Pop, and a nested class named Entry. La clase Entry contiene además tres miembros: un campo denominado next, un campo denominado data y un constructor.The Entry class further contains three members: a field named next, a field named data, and a constructor. Suponiendo que el código fuente del ejemplo se almacene en el archivo acme.cs, la línea de comandosAssuming that the source code of the example is stored in the file acme.cs, the command line

csc /t:library acme.cs

compila el ejemplo como una biblioteca (código sin un punto de entrada Main y genera un ensamblado denominado acme.dll.compiles the example as a library (code without a Main entry point) and produces an assembly named acme.dll.

Los ensamblados contienen código ejecutable en forma de instrucciones de lenguaje intermedio (IL) e información simbólica en forma de metadatos.Assemblies contain executable code in the form of Intermediate Language (IL) instructions, and symbolic information in the form of metadata. Antes de ejecutarlo, el código de IL de un ensamblado se convierte automáticamente en código específico del procesador mediante el compilador de Just in Time (JIT) de .NET Common Language Runtime.Before it is executed, the IL code in an assembly is automatically converted to processor-specific code by the Just-In-Time (JIT) compiler of .NET Common Language Runtime.

Dado que un ensamblado es una unidad autodescriptiva de funcionalidad que contiene código y metadatos, no hay necesidad de directivas #include ni archivos de encabezado de C#.Because an assembly is a self-describing unit of functionality containing both code and metadata, there is no need for #include directives and header files in C#. Los tipos y miembros públicos contenidos en un ensamblado determinado estarán disponibles en un programa de C# simplemente haciendo referencia a dicho ensamblado al compilar el programa.The public types and members contained in a particular assembly are made available in a C# program simply by referencing that assembly when compiling the program. Por ejemplo, este programa usa la clase Acme.Collections.Stack desde el ensamblado acme.dll:For example, this program uses the Acme.Collections.Stack class from the acme.dll assembly:

using System;
using Acme.Collections;

class Test
{
    static void Main() {
        Stack s = new Stack();
        s.Push(1);
        s.Push(10);
        s.Push(100);
        Console.WriteLine(s.Pop());
        Console.WriteLine(s.Pop());
        Console.WriteLine(s.Pop());
    }
}

Si el programa se almacena en el archivo test.cs, cuando test.cs se compila, acme.dll se puede hacer referencia al ensamblado mediante la opción /r del compilador:If the program is stored in the file test.cs, when test.cs is compiled, the acme.dll assembly can be referenced using the compiler's /r option:

csc /r:acme.dll test.cs

Esto crea un ensamblado ejecutable denominado test.exe, que, cuando se ejecuta, produce el resultado:This creates an executable assembly named test.exe, which, when run, produces the output:

100
10
1

C# permite que el texto de origen de un programa se almacene en varios archivos de origen.C# permits the source text of a program to be stored in several source files. Cuando se compila un programa de C# de varios archivos, todos los archivos de origen se procesan juntos y los archivos de origen pueden hacerse referencia mutuamente de forma libre; desde un punto de vista conceptual, es como si todos los archivos de origen estuvieran concatenados en un archivo de gran tamaño antes de ser procesados.When a multi-file C# program is compiled, all of the source files are processed together, and the source files can freely reference each other—conceptually, it is as if all the source files were concatenated into one large file before being processed. En C# nunca se necesitan declaraciones adelantadas porque, excepto en contadas ocasiones, el orden de declaración es insignificante.Forward declarations are never needed in C# because, with very few exceptions, declaration order is insignificant. C# no limita un archivo de origen a declarar solamente un tipo público ni precisa que el nombre del archivo de origen coincida con un tipo declarado en el archivo de origen.C# does not limit a source file to declaring only one public type nor does it require the name of the source file to match a type declared in the source file.

Tipos y variablesTypes and variables

Hay dos clases de tipos en C#: tipos de valor y tipos de referencia.There are two kinds of types in C#: value types and reference types. Las variables de tipos de valor contienen directamente los datos, mientras que las variables de los tipos de referencia almacenan referencias a los datos, lo que se conoce como objetos.Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. Con los tipos de referencia, es posible que dos variables hagan referencia al mismo objeto y que, por tanto, las operaciones en una variable afecten al objeto al que hace referencia la otra variable.With reference types, it is possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. Con los tipos de valor, cada variable tiene su propia copia de los datos y no es posible que las operaciones en una variable afecten a la otra (excepto en el caso de las variables de parámetro ref y out).With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other (except in the case of ref and out parameter variables).

C#los tipos de valor de se dividen en tipos simples, tipos de enumeración, tipos de structy tipos que C# aceptan valores NULL, y los tipos de referencia de se dividen en tipos de clase, tipos de interfaz, matriz tiposy tipos de delegado.C#'s value types are further divided into simple types, enum types, struct types, and nullable types, and C#'s reference types are further divided into class types, interface types, array types, and delegate types.

En la tabla siguiente se proporciona información C#general sobre el sistema de tipos de.The following table provides an overview of C#'s type system.

CategoríaCategory DescripciónDescription
Tipos de valorValue types Tipos simplesSimple types Entero con signo: sbyte, short, int,longSigned integral: sbyte, short, int, long
Entero sin signo: byte, ushort, uint,ulongUnsigned integral: byte, ushort, uint, ulong
Caracteres Unicode: charUnicode characters: char
Punto flotante de IEEE: float, doubleIEEE floating point: float, double
Decimal de alta precisión: decimalHigh-precision decimal: decimal
Booleano: boolBoolean: bool
Tipos de enumeraciónEnum types Tipos definidos por el usuario con el formato enum E {...}User-defined types of the form enum E {...}
Tipos de estructuraStruct types Tipos definidos por el usuario con el formato struct S {...}User-defined types of the form struct S {...}
Tipos que aceptan valores NULLNullable types Extensiones de todos los demás tipos de valor con un valor nullExtensions of all other value types with a null value
Tipos de referenciaReference types Tipos de claseClass types Clase base definitiva de todos los demás tipos: objectUltimate base class of all other types: object
Cadenas Unicode: stringUnicode strings: string
Tipos definidos por el usuario con el formato class C {...}User-defined types of the form class C {...}
Tipos de interfazInterface types Tipos definidos por el usuario con el formato interface I {...}User-defined types of the form interface I {...}
Tipos de matrizArray types Unidimensional y multidimensional; por ejemplo, int[] y int[,]Single- and multi-dimensional, for example, int[] and int[,]
Tipos delegadosDelegate types Tipos definidos por el usuario del formulario, por ejemplo,delegate int D(...)User-defined types of the form e.g. delegate int D(...)

Los ocho tipos enteros proporcionan compatibilidad con valores de 8, 16, 32 y 64 bits en formato con o sin signo.The eight integral types provide support for 8-bit, 16-bit, 32-bit, and 64-bit values in signed or unsigned form.

Los dos tipos de punto flotante float , doubley, se representan mediante los formatos IEEE 754 de precisión sencilla de 32 bits y de doble precisión de 64 bits.The two floating point types, float and double, are represented using the 32-bit single-precision and 64-bit double-precision IEEE 754 formats.

El tipo decimal es un tipo de datos de 128 bits adecuado para cálculos financieros y monetarios.The decimal type is a 128-bit data type suitable for financial and monetary calculations.

C#el bool tipo de se usa para representar valores booleanos: valores que true son falseo.C#'s bool type is used to represent boolean values—values that are either true or false.

El procesamiento de caracteres y cadenas en C# utiliza la codificación Unicode.Character and string processing in C# uses Unicode encoding. El tipo char representa una unidad de código UTF-16 y el tipo string representa una secuencia de unidades de código UTF-16.The char type represents a UTF-16 code unit, and the string type represents a sequence of UTF-16 code units.

En la tabla siguiente se C#resumen los tipos numéricos de.The following table summarizes C#'s numeric types.

CategoríaCategory ParadaBits TypeType Intervalo/precisiónRange/Precision
Entero con signoSigned integral 88 sbyte -128... 127-128...127
1616 short -32768... 32, 767-32,768...32,767
3232 int -2147483648... 2, 147, 483, 647-2,147,483,648...2,147,483,647
6464 long -9223372036854775808... 9, 223, 372, 036, 854, 775, 807-9,223,372,036,854,775,808...9,223,372,036,854,775,807
Entero sin signoUnsigned integral 88 byte 0... 2550...255
1616 ushort 0... 65, 5350...65,535
3232 uint 0... 4, 294, 967, 2950...4,294,967,295
6464 ulong 0... 18, 446, 744, 073, 709, 551, 6150...18,446,744,073,709,551,615
Punto flotanteFloating point 3232 float 1,5 × 10 ^ − 45 a 3,4 × 10 ^ 38, precisión de 7 dígitos1.5 × 10^−45 to 3.4 × 10^38, 7-digit precision
6464 double 5,0 × 10 ^ − 324 a 1,7 × 10 ^ 308, precisión de 15 dígitos5.0 × 10^−324 to 1.7 × 10^308, 15-digit precision
DecimalDecimal 128128 decimal 1,0 × 10 ^ − 28 a 7,9 × 10 ^ 28, precisión de 28 dígitos1.0 × 10^−28 to 7.9 × 10^28, 28-digit precision

Los programas de C# utilizan declaraciones de tipos para crear nuevos tipos.C# programs use type declarations to create new types. Una declaración de tipos especifica el nombre y los miembros del nuevo tipo.A type declaration specifies the name and the members of the new type. Cinco de C#las categorías de tipos de son definibles por el usuario: tipos de clase, tipos de struct, tipos de interfaz, tipos de enumeración y tipos de delegado.Five of C#'s categories of types are user-definable: class types, struct types, interface types, enum types, and delegate types.

Un tipo de clase define una estructura de datos que contiene miembros de datos (campos) y miembros de función (métodos, propiedades, etc.).A class type defines a data structure that contains data members (fields) and function members (methods, properties, and others). Los tipos de clase admiten herencia única y polimorfismo, mecanismos por los que las clases derivadas pueden extender y especializar clases base.Class types support single inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes.

Un tipo de estructura es similar a un tipo de clase en que representa una estructura con miembros de datos y miembros de función.A struct type is similar to a class type in that it represents a structure with data members and function members. Sin embargo, a diferencia de las clases, las estructuras son tipos de valor y no requieren la asignación del montón.However, unlike classes, structs are value types and do not require heap allocation. Los tipos struct no admiten la herencia especificada por el usuario y todos los tipos de struct se heredan implícitamente del tipo object.Struct types do not support user-specified inheritance, and all struct types implicitly inherit from type object.

Un tipo de interfaz define un contrato como un conjunto con nombre de miembros de función públicos.An interface type defines a contract as a named set of public function members. Una clase o estructura que implementa una interfaz debe proporcionar implementaciones de los miembros de función de la interfaz.A class or struct that implements an interface must provide implementations of the interface's function members. Una interfaz puede heredar de varias interfaces base, y una clase o estructura puede implementar varias interfaces.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

Un tipo de delegado representa referencias a métodos con una lista de parámetros determinada y un tipo de valor devuelto.A delegate type represents references to methods with a particular parameter list and return type. Los delegados permiten tratar métodos como entidades que se puedan asignar a variables y se puedan pasar como parámetros.Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Los delegados son similares al concepto de punteros de función en otros lenguajes, pero a diferencia de los punteros de función, los delegados están orientados a objetos y presentan seguridad de tipos.Delegates are similar to the concept of function pointers found in some other languages, but unlike function pointers, delegates are object-oriented and type-safe.

Los tipos de clase, estructura, interfaz y delegado admiten genéricos, mediante los cuales se pueden parametrizar con otros tipos.Class, struct, interface and delegate types all support generics, whereby they can be parameterized with other types.

Un tipo de enumeración es un tipo distinto con constantes con nombre.An enum type is a distinct type with named constants. Cada tipo de enumeración tiene un tipo subyacente, que debe ser uno de los ocho tipos enteros.Every enum type has an underlying type, which must be one of the eight integral types. El conjunto de valores de un tipo de enumeración es igual que el conjunto de valores del tipo subyacente.The set of values of an enum type is the same as the set of values of the underlying type.

C# admite matrices unidimensionales y multidimensionales de cualquier tipo.C# supports single- and multi-dimensional arrays of any type. A diferencia de los tipos enumerados anteriormente, los tipos de matriz no tienen que ser declarados antes de usarlos.Unlike the types listed above, array types do not have to be declared before they can be used. En su lugar, los tipos de matriz se crean mediante un nombre de tipo entre corchetes.Instead, array types are constructed by following a type name with square brackets. Por ejemplo, int[] es una matriz unidimensional de int, int[,] es una matriz bidimensional de inty int[][] es una matriz unidimensional de Matrices unidimensionales de int.For example, int[] is a single-dimensional array of int, int[,] is a two-dimensional array of int, and int[][] is a single-dimensional array of single-dimensional arrays of int.

Los tipos que aceptan valores NULL tampoco tienen que declararse antes de que se puedan utilizar.Nullable types also do not have to be declared before they can be used. Para cada tipo T de valor que no acepta valores NULL, existe un tipo T?que acepta valores NULL correspondiente, que puede nullcontener un valor adicional.For each non-nullable value type T there is a corresponding nullable type T?, which can hold an additional value null. Por ejemplo, int? es un tipo que puede contener cualquier entero de 32 bits o el valor null.For instance, int? is a type that can hold any 32 bit integer or the value null.

C#el sistema de tipos de está unificado, de modo que un valor de cualquier tipo se puede tratar como un objeto.C#'s type system is unified such that a value of any type can be treated as an object. Todos los tipos de C# directa o indirectamente se derivan del tipo de clase object, y object es la clase base definitiva de todos los tipos.Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Los valores de tipos de referencia se tratan como objetos mediante la visualización de los valores como tipo object.Values of reference types are treated as objects simply by viewing the values as type object. Los valores de los tipos de valor se tratan como objetos realizando operaciones de conversión boxing y unboxing .Values of value types are treated as objects by performing boxing and unboxing operations. En el ejemplo siguiente, un valor int se convierte en object y vuelve a int.In the following example, an int value is converted to object and back again to int.

using System;

class Test
{
    static void Main() {
        int i = 123;
        object o = i;          // Boxing
        int j = (int)o;        // Unboxing
    }
}

Cuando un valor de un tipo de valor se convierte al objecttipo, se asigna una instancia de objeto, también denominada "box", para contener el valor, y el valor se copia en ese cuadro.When a value of a value type is converted to type object, an object instance, also called a "box," is allocated to hold the value, and the value is copied into that box. Por el contrario, cuando una object referencia se convierte en un tipo de valor, se realiza una comprobación de que el objeto al que se hace referencia es un cuadro del tipo de valor correcto y, si la comprobación se realiza correctamente, se copia el valor en el cuadro.Conversely, when an object reference is cast to a value type, a check is made that the referenced object is a box of the correct value type, and, if the check succeeds, the value in the box is copied out.

C#el sistema de tipos unificado significa de forma eficaz que los tipos de valor pueden convertirse en objetos "a petición".C#'s unified type system effectively means that value types can become objects "on demand." Debido a la unificación, las bibliotecas de uso general que utilizan el tipo object pueden usarse con tipos de referencia y tipos de valor.Because of the unification, general-purpose libraries that use type object can be used with both reference types and value types.

Hay varios tipos de variables en C#, entre otras, campos, elementos de matriz, variables locales y parámetros.There are several kinds of variables in C#, including fields, array elements, local variables, and parameters. Las variables representan ubicaciones de almacenamiento, y cada variable tiene un tipo que determina qué valores se pueden almacenar en la variable, como se muestra en la tabla siguiente.Variables represent storage locations, and every variable has a type that determines what values can be stored in the variable, as shown by the following table.

Tipo de variableType of Variable Contenido posiblePossible Contents
Tipo de valor distinto a NULLNon-nullable value type Un valor de ese tipo exactoA value of that exact type
Tipos de valor NULLNullable value type Un valor null o un valor de ese tipo exactoA null value or a value of that exact type
object Una referencia nula, una referencia a un objeto de cualquier tipo de referencia o una referencia a un valor de conversión boxing de cualquier tipo de valorA null reference, a reference to an object of any reference type, or a reference to a boxed value of any value type
Tipo de claseClass type Una referencia nula, una referencia a una instancia de ese tipo de clase o una referencia a una instancia de una clase derivada de ese tipo de clase.A null reference, a reference to an instance of that class type, or a reference to an instance of a class derived from that class type
Tipo de interfazInterface type Una referencia nula, una referencia a una instancia de un tipo de clase que implementa ese tipo de interfaz o una referencia a un valor de conversión boxing de un tipo de valor que implementa ese tipo de interfaz.A null reference, a reference to an instance of a class type that implements that interface type, or a reference to a boxed value of a value type that implements that interface type
Tipo de matrizArray type Una referencia nula, una referencia a una instancia de ese tipo de matriz o una referencia a una instancia de un tipo de matriz compatibleA null reference, a reference to an instance of that array type, or a reference to an instance of a compatible array type
Tipo delegadoDelegate type Una referencia nula o una referencia a una instancia de ese tipo de delegado.A null reference or a reference to an instance of that delegate type

ExpresionesExpressions

Las expresiones se construyen con operandos y operadores.Expressions are constructed from operands and operators. Los operadores de una expresión indican qué operaciones se aplican a los operandos.The operators of an expression indicate which operations to apply to the operands. Ejemplos de operadores incluyen +, -, *, / y new.Examples of operators include +, -, *, /, and new. Algunos ejemplos de operandos son literales, campos, variables locales y expresiones.Examples of operands include literals, fields, local variables, and expressions.

Cuando una expresión contiene varios operadores, la precedencia de los operadores controla el orden en que se evalúan los operadores individuales.When an expression contains multiple operators, the precedence of the operators controls the order in which the individual operators are evaluated. Por ejemplo, la expresión x + y * z se evalúa como x + (y * z) porque el operador * tiene mayor precedencia que el operador +.For example, the expression x + y * z is evaluated as x + (y * z) because the * operator has higher precedence than the + operator.

La mayoría de los operadores se pueden sobrecargar.Most operators can be overloaded. La sobrecarga de operador permite la especificación de implementaciones de operadores definidas por el usuario para operaciones donde uno o ambos operandos son de un tipo de struct o una clase definidos por el usuario.Operator overloading permits user-defined operator implementations to be specified for operations where one or both of the operands are of a user-defined class or struct type.

En la tabla siguiente se C#resumen los operadores de, que muestran las categorías de operador en orden de prioridad, de mayor a menor.The following table summarizes C#'s operators, listing the operator categories in order of precedence from highest to lowest. Los operadores de la misma categoría tienen la misma precedencia.Operators in the same category have equal precedence.

CategoríaCategory ExpresiónExpression DescripciónDescription
PrincipalPrimary x.m Acceso a miembrosMember access
x(...) Invocación de método y delegadoMethod and delegate invocation
x[...] Acceso a matriz e indizadorArray and indexer access
x++ PostincrementoPost-increment
x-- PostdecrementoPost-decrement
new T(...) Creación de objetos y delegadosObject and delegate creation
new T(...){...} creación de objetos con inicializadorObject creation with initializer
new {...} inicializador de objetos anónimosAnonymous object initializer
new T[...] creación de matrizArray creation
typeof(T) obtener el objeto System.Type para TObtain System.Type object for T
checked(x) Evaluar expresión en contexto comprobadoEvaluate expression in checked context
unchecked(x) Evaluar expresión en contexto no comprobadoEvaluate expression in unchecked context
default(T) obtener valor predeterminado de tipo TObtain default value of type T
delegate {...} Función anónima (método anónimo)Anonymous function (anonymous method)
UnarioUnary +x identidadIdentity
-x NegaciónNegation
!x Negación lógicaLogical negation
~x Negación bit a bitBitwise negation
++x PreincrementoPre-increment
--x PredecrementoPre-decrement
(T)x convertir explícitamente x en el tipo TExplicitly convert x to type T
await x esperar asincrónicamente a que finalice xAsynchronously wait for x to complete
MultiplicativoMultiplicative x * y MultiplicaciónMultiplication
x / y DivisiónDivision
x % y RestoRemainder
AditivoAdditive x + y Suma, concatenación de cadenas, combinación de delegadosAddition, string concatenation, delegate combination
x - y Resta, eliminación de delegadosSubtraction, delegate removal
ShiftShift x << y Desplazamiento a la izquierdaShift left
x >> y Desplazamiento a la derechaShift right
Comprobación de tipos y relacionalRelational and type testing x < y Menor queLess than
x > y Mayor queGreater than
x <= y Menor o igual queLess than or equal
x >= y Mayor o igual queGreater than or equal
x is T volver a ejecutar true si x es una T, de lo contrario falseReturn true if x is a T, false otherwise
x as T volver a ejecutar x con tipo T, o null si x no es una TReturn x typed as T, or null if x is not a T
IgualdadEquality x == y IgualEqual
x != y No igualNot equal
AND lógicoLogical AND x & y AND bit a bit entero, AND lógico booleanoInteger bitwise AND, boolean logical AND
XOR lógicoLogical XOR x ^ y XOR bit a bit entero, XOR lógico booleanoInteger bitwise XOR, boolean logical XOR
OR lógicoLogical OR x | y OR bit a bit entero, OR lógico booleanoInteger bitwise OR, boolean logical OR
AND condicionalConditional AND x && y Solo evalúa si xes y``trueEvaluates y only if x is true
OR condicionalConditional OR x || y Solo evalúa si xes y``falseEvaluates y only if x is false
Uso combinado de NULLNull coalescing x ?? y Se evalúa como y si x es null, en x caso contrario,.Evaluates to y if x is null, to x otherwise
CondicionalConditional x ? y : z se evalúa como y si x es true o z si x es falseEvaluates y if x is true, z if x is false
Asignación o función anónimaAssignment or anonymous function x = y AsignaciónAssignment
x op= y Asignación compuesta; los operadores admitidos son *= /= %= += -= <<= >>= &= ^=|=Compound assignment; supported operators are *= /= %= += -= <<= >>= &= ^= |=
(T x) => y Función anónima (expresión lambda)Anonymous function (lambda expression)

InstruccionesStatements

Las acciones de un programa se expresan mediante instrucciones.The actions of a program are expressed using statements. C# admite varios tipos de instrucciones diferentes, varias de las cuales se definen en términos de instrucciones insertadas.C# supports several different kinds of statements, a number of which are defined in terms of embedded statements.

Un bloque permite que se escriban varias instrucciones en contextos donde se permite una única instrucción.A block permits multiple statements to be written in contexts where a single statement is allowed. Un bloque se compone de una lista de instrucciones escritas entre los delimitadores { y }.A block consists of a list of statements written between the delimiters { and }.

Las instrucciones de declaración se usan para declarar variables locales y constantes.Declaration statements are used to declare local variables and constants.

Las instrucciones de expresión se usan para evaluar expresiones.Expression statements are used to evaluate expressions. Entre las expresiones que se pueden utilizar como instrucciones se incluyen las invocaciones de método, las asignaciones new de objetos que usan el operador = , las asignaciones mediante y los operadores de asignación compuesta, las operaciones de incremento y decremento mediante el ++operadores -- y y expresiones Await.Expressions that can be used as statements include method invocations, object allocations using the new operator, assignments using = and the compound assignment operators, increment and decrement operations using the ++ and -- operators and await expressions.

Las instrucciones de selección se usan para seleccionar una de varias instrucciones posibles para su ejecución en función del valor de alguna expresión.Selection statements are used to select one of a number of possible statements for execution based on the value of some expression. En este grupo están las instrucciones if y switch.In this group are the if and switch statements.

Las instrucciones de iteración se utilizan para ejecutar repetidamente una instrucción incrustada.Iteration statements are used to repeatedly execute an embedded statement. En este grupo están las instrucciones while, do, for y foreach.In this group are the while, do, for, and foreach statements.

Las instrucciones de salto se usan para transferir el control.Jump statements are used to transfer control. En este grupo están las instrucciones break, continue, goto, throw, return y yield.In this group are the break, continue, goto, throw, return, and yield statements.

La instrucción try... catch se usa para detectar excepciones que se producen durante la ejecución de un bloque, y la instrucción try... finally se usa para especificar el código de finalización que siempre se ejecuta, tanto si se ha producido una excepción como si no.The try...catch statement is used to catch exceptions that occur during execution of a block, and the try...finally statement is used to specify finalization code that is always executed, whether an exception occurred or not.

Las checked instrucciones unchecked y se utilizan para controlar el contexto de comprobación de desbordamiento para conversiones y operaciones aritméticas de tipo entero.The checked and unchecked statements are used to control the overflow checking context for integral-type arithmetic operations and conversions.

La instrucción lock se usa para obtener el bloqueo de exclusión mutua para un objeto determinado, ejecutar una instrucción y, luego, liberar el bloqueo.The lock statement is used to obtain the mutual-exclusion lock for a given object, execute a statement, and then release the lock.

La instrucción using se usa para obtener un recurso, ejecutar una instrucción y, luego, eliminar dicho recurso.The using statement is used to obtain a resource, execute a statement, and then dispose of that resource.

A continuación se muestran ejemplos de cada tipo de instrucciónBelow are examples of each kind of statement

Declaraciones de variables localesLocal variable declarations

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

Declaración de constante localLocal constant declaration

static void Main() {
    const float pi = 3.1415927f;
    const int r = 25;
    Console.WriteLine(pi * r * r);
}

Expression (instrucción)Expression statement

static void Main() {
    int i;
    i = 123;                // Expression statement
    Console.WriteLine(i);   // Expression statement
    i++;                    // Expression statement
    Console.WriteLine(i);   // Expression statement
}

Instrucción ifif statement

static void Main(string[] args) {
    if (args.Length == 0) {
        Console.WriteLine("No arguments");
    }
    else {
        Console.WriteLine("One or more arguments");
    }
}

Instrucción switchswitch statement

static void Main(string[] args) {
    int n = args.Length;
    switch (n) {
        case 0:
            Console.WriteLine("No arguments");
            break;
        case 1:
            Console.WriteLine("One argument");
            break;
        default:
            Console.WriteLine("{0} arguments", n);
            break;
    }
}

Instrucción whilewhile statement

static void Main(string[] args) {
    int i = 0;
    while (i < args.Length) {
        Console.WriteLine(args[i]);
        i++;
    }
}

Instrucción dodo statement

static void Main() {
    string s;
    do {
        s = Console.ReadLine();
        if (s != null) Console.WriteLine(s);
    } while (s != null);
}

Instrucción forfor statement

static void Main(string[] args) {
    for (int i = 0; i < args.Length; i++) {
        Console.WriteLine(args[i]);
    }
}

Instrucción foreachforeach statement

static void Main(string[] args) {
    foreach (string s in args) {
        Console.WriteLine(s);
    }
}

Instrucción breakbreak statement

static void Main() {
    while (true) {
        string s = Console.ReadLine();
        if (s == null) break;
        Console.WriteLine(s);
    }
}

Instrucción continuecontinue statement

static void Main(string[] args) {
    for (int i = 0; i < args.Length; i++) {
        if (args[i].StartsWith("/")) continue;
        Console.WriteLine(args[i]);
    }
}

Instrucción gotogoto statement

static void Main(string[] args) {
    int i = 0;
    goto check;
    loop:
    Console.WriteLine(args[i++]);
    check:
    if (i < args.Length) goto loop;
}

Instrucción returnreturn statement

static int Add(int a, int b) {
    return a + b;
}

static void Main() {
    Console.WriteLine(Add(1, 2));
    return;
}

Instrucción yieldyield statement

static IEnumerable<int> Range(int from, int to) {
    for (int i = from; i < to; i++) {
        yield return i;
    }
    yield break;
}

static void Main() {
    foreach (int x in Range(-10,10)) {
        Console.WriteLine(x);
    }
}

throwinstrucciones try ythrow and try statements

static double Divide(double x, double y) {
    if (y == 0) throw new DivideByZeroException();
    return x / y;
}

static void Main(string[] args) {
    try {
        if (args.Length != 2) {
            throw new Exception("Two numbers required");
        }
        double x = double.Parse(args[0]);
        double y = double.Parse(args[1]);
        Console.WriteLine(Divide(x, y));
    }
    catch (Exception e) {
        Console.WriteLine(e.Message);
    }
    finally {
        Console.WriteLine("Good bye!");
    }
}

checkedinstrucciones unchecked ychecked and unchecked statements

static void Main() {
    int i = int.MaxValue;
    checked {
        Console.WriteLine(i + 1);        // Exception
    }
    unchecked {
        Console.WriteLine(i + 1);        // Overflow
    }
}

Instrucción locklock statement

class Account
{
    decimal balance;
    public void Withdraw(decimal amount) {
        lock (this) {
            if (amount > balance) {
                throw new Exception("Insufficient funds");
            }
            balance -= amount;
        }
    }
}

Instrucción usingusing statement

static void Main() {
    using (TextWriter w = File.CreateText("test.txt")) {
        w.WriteLine("Line one");
        w.WriteLine("Line two");
        w.WriteLine("Line three");
    }
}

Clases y objetosClasses and objects

Las clases son los tipos más fundamentales de C#.Classes are the most fundamental of C#'s types. Una clase es una estructura de datos que combina estados (campos) y acciones (métodos y otros miembros de función) en una sola unidad.A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. Una clase proporciona una definición para instancias creadas dinámicamente de la clase, también conocidas como objetos.A class provides a definition for dynamically created instances of the class, also known as objects. Las clases admiten herencia y polimorfismo, mecanismos por los que las clases derivadas pueden extender y especializar clases base.Classes support inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes.

Las clases nuevas se crean mediante declaraciones de clase.New classes are created using class declarations. Una declaración de clase se inicia con un encabezado que especifica los atributos y modificadores de la clase, el nombre de la clase, la clase base (si se indica) y las interfaces implementadas por la clase.A class declaration starts with a header that specifies the attributes and modifiers of the class, the name of the class, the base class (if given), and the interfaces implemented by the class. Al encabezado le sigue el cuerpo de la clase, que consta de una lista de declaraciones de miembros escritas entre los delimitadores { y }.The header is followed by the class body, which consists of a list of member declarations written between the delimiters { and }.

La siguiente es una declaración de una clase simple denominada Point:The following is a declaration of a simple class named Point:

public class Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Las instancias de clases se crean mediante el operador new, que asigna memoria para una nueva instancia, invoca un constructor para inicializar la instancia y devuelve una referencia a la instancia.Instances of classes are created using the new operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. Las instrucciones siguientes crean dos Point objetos y almacenan las referencias a esos objetos en dos variables:The following statements create two Point objects and store references to those objects in two variables:

Point p1 = new Point(0, 0);
Point p2 = new Point(10, 20);

La memoria ocupada por un objeto se recupera automáticamente cuando el objeto ya no está en uso.The memory occupied by an object is automatically reclaimed when the object is no longer in use. No es necesario ni posible desasignar explícitamente objetos en C#.It is neither necessary nor possible to explicitly deallocate objects in C#.

MiembrosMembers

Los miembros de una clase son miembros estáticos o miembros de instancia.The members of a class are either static members or instance members. Los miembros estáticos pertenecen a clases y los miembros de instancia pertenecen a objetos (instancias de clases).Static members belong to classes, and instance members belong to objects (instances of classes).

En la tabla siguiente se proporciona información general sobre los tipos de miembros que puede contener una clase.The following table provides an overview of the kinds of members a class can contain.

MiembroMember DescripciónDescription
ConstantesConstants Valores constantes asociados a la claseConstant values associated with the class
CamposFields Variables de la claseVariables of the class
MétodosMethods Cálculos y acciones que pueden realizarse mediante la claseComputations and actions that can be performed by the class
PropiedadesProperties Acciones asociadas a la lectura y escritura de propiedades con nombre de la claseActions associated with reading and writing named properties of the class
IndizadoresIndexers Acciones asociadas a la indexación de instancias de la clase como una matrizActions associated with indexing instances of the class like an array
EventosEvents Notificaciones que puede generar la claseNotifications that can be generated by the class
OperadoresOperators Conversiones y operadores de expresión admitidos por la claseConversions and expression operators supported by the class
ConstructoresConstructors Acciones necesarias para inicializar instancias de la clase o la clase propiamente dichaActions required to initialize instances of the class or the class itself
DestructoresDestructors Acciones que deben realizarse antes de que las instancias de la clase se descarten de forma permanenteActions to perform before instances of the class are permanently discarded
TiposTypes Tipos anidados declarados por la claseNested types declared by the class

AccesibilidadAccessibility

Cada miembro de una clase tiene asociada una accesibilidad, que controla las regiones del texto del programa que pueden tener acceso al miembro.Each member of a class has an associated accessibility, which controls the regions of program text that are able to access the member. Existen cinco formas posibles de accesibilidad.There are five possible forms of accessibility. Se resumen en la tabla siguiente.These are summarized in the following table.

AccesibilidadAccessibility AlMeaning
public Acceso no limitadoAccess not limited
protected Acceso limitado a esta clase o a las clases derivadas de esta claseAccess limited to this class or classes derived from this class
internal Acceso limitado a este programaAccess limited to this program
protected internal Acceso limitado a este programa o a las clases derivadas de esta claseAccess limited to this program or classes derived from this class
private Acceso limitado a esta claseAccess limited to this class

Parámetros de tipoType parameters

Una definición de clase puede especificar un conjunto de parámetros de tipo poniendo tras el nombre de clase una lista de nombres de parámetro de tipo entre corchetes angulares.A class definition may specify a set of type parameters by following the class name with angle brackets enclosing a list of type parameter names. Los parámetros de tipo se pueden usar en el cuerpo de las declaraciones de clase para definir los miembros de la clase.The type parameters can the be used in the body of the class declarations to define the members of the class. En el ejemplo siguiente, los parámetros de tipo de Pair son TFirst y TSecond:In the following example, the type parameters of Pair are TFirst and TSecond:

public class Pair<TFirst,TSecond>
{
    public TFirst First;
    public TSecond Second;
}

Un tipo de clase que se declara para tomar parámetros de tipo se denomina tipo de clase genérico.A class type that is declared to take type parameters is called a generic class type. Los tipos struct, interfaz y delegado también pueden ser genéricos.Struct, interface and delegate types can also be generic.

Cuando se usa la clase genérica, se deben proporcionar argumentos de tipo para cada uno de los parámetros de tipo:When the generic class is used, type arguments must be provided for each of the type parameters:

Pair<int,string> pair = new Pair<int,string> { First = 1, Second = "two" };
int i = pair.First;     // TFirst is int
string s = pair.Second; // TSecond is string

Un tipo genérico con argumentos de tipo proporcionados Pair<int,string> , como el anterior, se denomina tipo construido.A generic type with type arguments provided, like Pair<int,string> above, is called a constructed type.

Clases baseBase classes

Una declaración de clase puede especificar una clase base colocando después del nombre de clase y los parámetros de tipo dos puntos seguidos del nombre de la clase base.A class declaration may specify a base class by following the class name and type parameters with a colon and the name of the base class. Omitir una especificación de la clase base es igual que derivarla del tipo object.Omitting a base class specification is the same as deriving from type object. En el ejemplo siguiente, la clase base de Point3D es Point y la clase base de Point es object:In the following example, the base class of Point3D is Point, and the base class of Point is object:

public class Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

public class Point3D: Point
{
    public int z;

    public Point3D(int x, int y, int z): base(x, y) {
        this.z = z;
    }
}

Una clase hereda a los miembros de su clase base.A class inherits the members of its base class. La herencia significa que una clase contiene implícitamente todos los miembros de su clase base, excepto la instancia y constructores estáticos, y los destructores de la clase base.Inheritance means that a class implicitly contains all members of its base class, except for the instance and static constructors, and the destructors of the base class. Una clase derivada puede agregar nuevos miembros a aquellos de los que hereda, pero no puede quitar la definición de un miembro heredado.A derived class can add new members to those it inherits, but it cannot remove the definition of an inherited member. En el ejemplo anterior, Point3D hereda los campos x y y de Point y cada instancia de Point3D contiene tres campos: x, y y z.In the previous example, Point3D inherits the x and y fields from Point, and every Point3D instance contains three fields, x, y, and z.

Existe una conversión implícita de un tipo de clase a cualquiera de sus tipos de clase base.An implicit conversion exists from a class type to any of its base class types. Por lo tanto, una variable de un tipo de clase puede hacer referencia a una instancia de esa clase o a una instancia de cualquier clase derivada.Therefore, a variable of a class type can reference an instance of that class or an instance of any derived class. Por ejemplo, dadas las declaraciones de clase anteriores, una variable de tipo Point puede hacer referencia a una instancia de Point o Point3D:For example, given the previous class declarations, a variable of type Point can reference either a Point or a Point3D:

Point a = new Point(10, 20);
Point b = new Point3D(10, 20, 30);

FieldsFields

Un campo es una variable que está asociada a una clase o a una instancia de una clase.A field is a variable that is associated with a class or with an instance of a class.

Un campo declarado con el static modificador define un campo estático.A field declared with the static modifier defines a static field. Un campo estático identifica exactamente una ubicación de almacenamiento.A static field identifies exactly one storage location. Independientemente del número de instancias de una clase que se creen, siempre solo hay una copia de un campo estático.No matter how many instances of a class are created, there is only ever one copy of a static field.

Un campo declarado sin el static modificador define un campo de instancia.A field declared without the static modifier defines an instance field. Cada instancia de una clase contiene una copia independiente de todos los campos de instancia de esa clase.Every instance of a class contains a separate copy of all the instance fields of that class.

En el ejemplo siguiente, cada instancia de la clase Color tiene una copia independiente de los campos de instancia r, g y b, pero solo hay una copia de los campos estáticos Black, White, Red, Green y Blue:In the following example, each instance of the Color class has a separate copy of the r, g, and b instance fields, but there is only one copy of the Black, White, Red, Green, and Blue static fields:

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
    private byte r, g, b;

    public Color(byte r, byte g, byte b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }
}

Como se muestra en el ejemplo anterior, los campos de solo lectura se puede declarar con un modificador readonly.As shown in the previous example, read-only fields may be declared with a readonly modifier. La asignación a readonly un campo solo se puede producir como parte de la declaración del campo o en un constructor de la misma clase.Assignment to a readonly field can only occur as part of the field's declaration or in a constructor in the same class.

MétodosMethods

Un método es un miembro que implementa un cálculo o una acción que puede realizar un objeto o una clase.A method is a member that implements a computation or action that can be performed by an object or class. A los métodos estáticos se accede a través de la clase.Static methods are accessed through the class. A los métodos de instancia se accede a través de instancias de la clase.Instance methods are accessed through instances of the class.

Los métodos tienen una lista (posiblemente vacía) de parámetros, que representan valores o referencias de variables que se pasan al método, y un tipo de valor devuelto, que especifica el tipo del valor calculado y devuelto por el método.Methods have a (possibly empty) list of parameters, which represent values or variable references passed to the method, and a return type, which specifies the type of the value computed and returned by the method. El tipo de valor devuelto void de un método es si no devuelve un valor.A method's return type is void if it does not return a value.

Al igual que los tipos, los métodos también pueden tener un conjunto de parámetros de tipo, para lo cuales se deben especificar argumentos de tipo cuando se llama al método.Like types, methods may also have a set of type parameters, for which type arguments must be specified when the method is called. A diferencia de los tipos, los argumentos de tipo a menudo se pueden deducir de los argumentos de una llamada al método y no es necesario proporcionarlos explícitamente.Unlike types, the type arguments can often be inferred from the arguments of a method call and need not be explicitly given.

La signatura de un método debe ser única en la clase en la que se declara el método.The signature of a method must be unique in the class in which the method is declared. La signatura de un método se compone del nombre del método, el número de parámetros de tipo y el número, los modificadores y los tipos de sus parámetros.The signature of a method consists of the name of the method, the number of type parameters and the number, modifiers, and types of its parameters. La signatura de un método no incluye el tipo de valor devuelto.The signature of a method does not include the return type.

ParámetrosParameters

Los parámetros se usan para pasar valores o referencias a variables a métodos.Parameters are used to pass values or variable references to methods. Los parámetros de un método obtienen sus valores reales de los argumentos que se especifican cuando se invoca el método.The parameters of a method get their actual values from the arguments that are specified when the method is invoked. Hay cuatro tipos de parámetros: parámetros de valor, parámetros de referencia, parámetros de salida y matrices de parámetros.There are four kinds of parameters: value parameters, reference parameters, output parameters, and parameter arrays.

Un parámetro de valor se usa para el paso de parámetros de entrada.A value parameter is used for input parameter passing. Un parámetro de valor corresponde a una variable local que obtiene su valor inicial del argumento que se ha pasado para el parámetro.A value parameter corresponds to a local variable that gets its initial value from the argument that was passed for the parameter. Las modificaciones en un parámetro de valor no afectan el argumento que se pasa para el parámetro.Modifications to a value parameter do not affect the argument that was passed for the parameter.

Los parámetros de valor pueden ser opcionales; se especifica un valor predeterminado para que se puedan omitir los argumentos correspondientes.Value parameters can be optional, by specifying a default value so that corresponding arguments can be omitted.

Un parámetro de referencia se usa para el paso de parámetros de entrada y salida.A reference parameter is used for both input and output parameter passing. El argumento pasado para un parámetro de referencia debe ser una variable, y durante la ejecución del método, el parámetro de referencia representa la misma ubicación de almacenamiento que la variable del argumento.The argument passed for a reference parameter must be a variable, and during execution of the method, the reference parameter represents the same storage location as the argument variable. Un parámetro de referencia se declara con el modificador ref.A reference parameter is declared with the ref modifier. En el ejemplo siguiente se muestra el uso de parámetros ref.The following example shows the use of ref parameters.

using System;

class Test
{
    static void Swap(ref int x, ref int y) {
        int temp = x;
        x = y;
        y = temp;
    }

    static void Main() {
        int i = 1, j = 2;
        Swap(ref i, ref j);
        Console.WriteLine("{0} {1}", i, j);            // Outputs "2 1"
    }
}

Un parámetro de salida se usa para pasar parámetros de salida.An output parameter is used for output parameter passing. Un parámetro de salida es similar a un parámetro de referencia, salvo que el valor inicial del argumento proporcionado por el llamador no es importante.An output parameter is similar to a reference parameter except that the initial value of the caller-provided argument is unimportant. Un parámetro de salida se declara con el modificador out.An output parameter is declared with the out modifier. En el ejemplo siguiente se muestra el uso de parámetros out.The following example shows the use of out parameters.

using System;

class Test
{
    static void Divide(int x, int y, out int result, out int remainder) {
        result = x / y;
        remainder = x % y;
    }

    static void Main() {
        int res, rem;
        Divide(10, 3, out res, out rem);
        Console.WriteLine("{0} {1}", res, rem);    // Outputs "3 1"
    }
}

Una matriz de parámetros permite que se pasen a un método un número variable de argumentos.A parameter array permits a variable number of arguments to be passed to a method. Una matriz de parámetros se declara con el modificador params.A parameter array is declared with the params modifier. Solo el último parámetro de un método puede ser una matriz de parámetros y el tipo de una matriz de parámetros debe ser un tipo de matriz unidimensional.Only the last parameter of a method can be a parameter array, and the type of a parameter array must be a single-dimensional array type. Los Write métodos WriteLine y de la System.Console clase son buenos ejemplos de uso de la matriz de parámetros.The Write and WriteLine methods of the System.Console class are good examples of parameter array usage. Se declaran de la manera siguiente.They are declared as follows.

public class Console
{
    public static void Write(string fmt, params object[] args) {...}
    public static void WriteLine(string fmt, params object[] args) {...}
    ...
}

Dentro de un método que usa una matriz de parámetros, la matriz de parámetros se comporta exactamente igual que un parámetro normal de un tipo de matriz.Within a method that uses a parameter array, the parameter array behaves exactly like a regular parameter of an array type. Sin embargo, en una invocación de un método con una matriz de parámetros, es posible pasar un único argumento del tipo de matriz de parámetros o cualquier número de argumentos del tipo de elemento de la matriz de parámetros.However, in an invocation of a method with a parameter array, it is possible to pass either a single argument of the parameter array type or any number of arguments of the element type of the parameter array. En este caso, una instancia de matriz se e inicializa automáticamente con los argumentos dados.In the latter case, an array instance is automatically created and initialized with the given arguments. Este ejemploThis example

Console.WriteLine("x={0} y={1} z={2}", x, y, z);

es equivalente a escribir lo siguiente.is equivalent to writing the following.

string s = "x={0} y={1} z={2}";
object[] args = new object[3];
args[0] = x;
args[1] = y;
args[2] = z;
Console.WriteLine(s, args);

Cuerpo del método y variables localesMethod body and local variables

El cuerpo de un método especifica las instrucciones que se ejecutan cuando se invoca el método.A method's body specifies the statements to execute when the method is invoked.

Un cuerpo del método puede declarar variables que son específicas de la invocación del método.A method body can declare variables that are specific to the invocation of the method. Estas variables se denominan variables locales.Such variables are called local variables. Una declaración de variable local especifica un nombre de tipo, un nombre de variable y, posiblemente, un valor inicial.A local variable declaration specifies a type name, a variable name, and possibly an initial value. En el ejemplo siguiente se declara una variable local i con un valor inicial de cero y una variable local j sin ningún valor inicial.The following example declares a local variable i with an initial value of zero and a local variable j with no initial value.

using System;

class Squares
{
    static void Main() {
        int i = 0;
        int j;
        while (i < 10) {
            j = i * i;
            Console.WriteLine("{0} x {0} = {1}", i, j);
            i = i + 1;
        }
    }
}

C# requiere que se asigne definitivamente una variable local antes de que se pueda obtener su valor.C# requires a local variable to be definitely assigned before its value can be obtained. Por ejemplo, si la declaración de i anterior no incluyera un valor inicial, el compilador notificaría un error con los usos posteriores de i porque i no se asignaría definitivamente en esos puntos del programa.For example, if the declaration of the previous i did not include an initial value, the compiler would report an error for the subsequent usages of i because i would not be definitely assigned at those points in the program.

Puede usar una instrucción return para devolver el control a su llamador.A method can use return statements to return control to its caller. En un método que devuelve void, las instrucciones return no pueden especificar una expresión.In a method returning void, return statements cannot specify an expression. En un método que devuelve instruccionesvoidno return , debe incluir una expresión que calcule el valor devuelto.In a method returning non-void, return statements must include an expression that computes the return value.

Métodos estáticos y de instanciaStatic and instance methods

Un método declarado con un static modificador es un método estático.A method declared with a static modifier is a static method. Un método estático no opera en una instancia específica y solo puede acceder directamente a miembros estáticos.A static method does not operate on a specific instance and can only directly access static members.

Un método declarado sin un static modificador es un método de instancia.A method declared without a static modifier is an instance method. Un método de instancia opera en una instancia específica y puede acceder a miembros estáticos y de instancia.An instance method operates on a specific instance and can access both static and instance members. Se puede acceder explícitamente a la instancia en la que se invoca un método de instancia como this.The instance on which an instance method was invoked can be explicitly accessed as this. Es un error hacer referencia a this en un método estático.It is an error to refer to this in a static method.

La siguiente clase Entity tiene miembros estáticos y de instancia.The following Entity class has both static and instance members.

class Entity
{
    static int nextSerialNo;
    int serialNo;

    public Entity() {
        serialNo = nextSerialNo++;
    }

    public int GetSerialNo() {
        return serialNo;
    }

    public static int GetNextSerialNo() {
        return nextSerialNo;
    }

    public static void SetNextSerialNo(int value) {
        nextSerialNo = value;
    }
}

Cada instancia Entity contiene un número de serie (y probablemente alguna otra información que no se muestra aquí).Each Entity instance contains a serial number (and presumably some other information that is not shown here). El constructor Entity (que es como un método de instancia) inicializa la nueva instancia con el siguiente número de serie disponible.The Entity constructor (which is like an instance method) initializes the new instance with the next available serial number. Dado que el constructor es un miembro de instancia, se le permite acceder al campo de instancia serialNo y al campo estático nextSerialNo.Because the constructor is an instance member, it is permitted to access both the serialNo instance field and the nextSerialNo static field.

Los métodos estáticos GetNextSerialNo y SetNextSerialNo pueden acceder al campo estático nextSerialNo, pero sería un error para ellas acceder directamente al campo de instancia serialNo.The GetNextSerialNo and SetNextSerialNo static methods can access the nextSerialNo static field, but it would be an error for them to directly access the serialNo instance field.

En el ejemplo siguiente se muestra el uso Entity de la clase.The following example shows the use of the Entity class.

using System;

class Test
{
    static void Main() {
        Entity.SetNextSerialNo(1000);
        Entity e1 = new Entity();
        Entity e2 = new Entity();
        Console.WriteLine(e1.GetSerialNo());           // Outputs "1000"
        Console.WriteLine(e2.GetSerialNo());           // Outputs "1001"
        Console.WriteLine(Entity.GetNextSerialNo());   // Outputs "1002"
    }
}

Tenga en cuenta que los métodos estáticos SetNextSerialNo y GetNextSerialNo se invocan en la clase, mientras que el método de instancia GetSerialNo se invoca en instancias de la clase.Note that the SetNextSerialNo and GetNextSerialNo static methods are invoked on the class whereas the GetSerialNo instance method is invoked on instances of the class.

Métodos virtual, de reemplazo y abstractoVirtual, override, and abstract methods

Cuando una declaración de método de instancia incluye un modificador virtual, se dice que el método es un método virtual.When an instance method declaration includes a virtual modifier, the method is said to be a virtual method. Cuando no virtual existe ningún modificador, se dice que el método es un método no virtual.When no virtual modifier is present, the method is said to be a non-virtual method.

Cuando se invoca un método virtual, el tipo en tiempo de ejecución de la instancia para la que tiene lugar esa invocación determina la implementación del método real que se invocará.When a virtual method is invoked, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke. En una invocación de método no virtual, el tipo en tiempo de compilación de la instancia es el factor determinante.In a nonvirtual method invocation, the compile-time type of the instance is the determining factor.

Un método virtual puede ser reemplazado en una clase derivada.A virtual method can be overridden in a derived class. Cuando una declaración de método de instancia override incluye un modificador, el método invalida un método virtual heredado con la misma firma.When an instance method declaration includes an override modifier, the method overrides an inherited virtual method with the same signature. Mientras que una declaración de método virtual introduce un método nuevo, una declaración de método de reemplazo especializa un método virtual heredado existente proporcionando una nueva implementación de ese método.Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method.

Un método abstracto es un método virtual sin implementación.An abstract method is a virtual method with no implementation. Un método abstracto se declara con abstract el modificador y solo se permite en una clase que también se abstractdeclara.An abstract method is declared with the abstract modifier and is permitted only in a class that is also declared abstract. Un método abstracto debe reemplazarse en todas las clases derivadas no abstractas.An abstract method must be overridden in every non-abstract derived class.

En el ejemplo siguiente se declara una clase abstracta, Expression, que representa un nodo de árbol de expresión y tres clases derivadas, Constant, VariableReference y Operation, que implementan nodos de árbol de expresión para constantes, referencias a variables y operaciones aritméticas.The following example declares an abstract class, Expression, which represents an expression tree node, and three derived classes, Constant, VariableReference, and Operation, which implement expression tree nodes for constants, variable references, and arithmetic operations. (Esto es similar a, pero no debe confundirse con los tipos de árbol de expresión introducidos en los tipos de árbol de expresión).(This is similar to, but not to be confused with the expression tree types introduced in Expression tree types).

using System;
using System.Collections;

public abstract class Expression
{
    public abstract double Evaluate(Hashtable vars);
}

public class Constant: Expression
{
    double value;

    public Constant(double value) {
        this.value = value;
    }

    public override double Evaluate(Hashtable vars) {
        return value;
    }
}

public class VariableReference: Expression
{
    string name;

    public VariableReference(string name) {
        this.name = name;
    }

    public override double Evaluate(Hashtable vars) {
        object value = vars[name];
        if (value == null) {
            throw new Exception("Unknown variable: " + name);
        }
        return Convert.ToDouble(value);
    }
}

public class Operation: Expression
{
    Expression left;
    char op;
    Expression right;

    public Operation(Expression left, char op, Expression right) {
        this.left = left;
        this.op = op;
        this.right = right;
    }

    public override double Evaluate(Hashtable vars) {
        double x = left.Evaluate(vars);
        double y = right.Evaluate(vars);
        switch (op) {
            case '+': return x + y;
            case '-': return x - y;
            case '*': return x * y;
            case '/': return x / y;
        }
        throw new Exception("Unknown operator");
    }
}

Las cuatro clases anteriores se pueden usar para modelar expresiones aritméticas.The previous four classes can be used to model arithmetic expressions. Por ejemplo, usando instancias de estas clases, la expresión x + 3 se puede representar de la manera siguiente.For example, using instances of these classes, the expression x + 3 can be represented as follows.

Expression e = new Operation(
    new VariableReference("x"),
    '+',
    new Constant(3));

El método Evaluate de una instancia Expression se invoca para evaluar la expresión determinada y generar un valor double.The Evaluate method of an Expression instance is invoked to evaluate the given expression and produce a double value. El método toma como argumento un Hashtable que contiene nombres de variables (como claves de las entradas) y valores (como valores de las entradas).The method takes as an argument a Hashtable that contains variable names (as keys of the entries) and values (as values of the entries). El Evaluate método es un método abstracto virtual, lo que significa que las clases derivadas no abstractas deben invalidarlo para proporcionar una implementación real.The Evaluate method is a virtual abstract method, meaning that non-abstract derived classes must override it to provide an actual implementation.

Una implementación de Constant de Evaluate simplemente devuelve la constante almacenada.A Constant's implementation of Evaluate simply returns the stored constant. Una VariableReferenceimplementación de busca el nombre de la variable en la tabla hash y devuelve el valor resultante.A VariableReference's implementation looks up the variable name in the hashtable and returns the resulting value. Una implementación de Operation evalúa primero los operandos izquierdo y derecho (mediante la invocación recursiva de sus métodos Evaluate) y luego realiza la operación aritmética correspondiente.An Operation's implementation first evaluates the left and right operands (by recursively invoking their Evaluate methods) and then performs the given arithmetic operation.

El siguiente programa usa las clases Expression para evaluar la expresión x * (y + 2) para los distintos valores de x y y.The following program uses the Expression classes to evaluate the expression x * (y + 2) for different values of x and y.

using System;
using System.Collections;

class Test
{
    static void Main() {
        Expression e = new Operation(
            new VariableReference("x"),
            '*',
            new Operation(
                new VariableReference("y"),
                '+',
                new Constant(2)
            )
        );
        Hashtable vars = new Hashtable();
        vars["x"] = 3;
        vars["y"] = 5;
        Console.WriteLine(e.Evaluate(vars));        // Outputs "21"
        vars["x"] = 1.5;
        vars["y"] = 9;
        Console.WriteLine(e.Evaluate(vars));        // Outputs "16.5"
    }
}

Sobrecarga de métodosMethod overloading

La sobrecarga de métodos permite que varios métodos de la misma clase tengan el mismo nombre mientras tengan signaturas únicas.Method overloading permits multiple methods in the same class to have the same name as long as they have unique signatures. Al compilar una invocación de un método sobrecargado, el compilador usa la resolución de sobrecarga para determinar el método concreto que de invocará.When compiling an invocation of an overloaded method, the compiler uses overload resolution to determine the specific method to invoke. La resolución de sobrecarga busca el método que mejor coincida con los argumentos o informa de un error si no se puede encontrar ninguna mejor coincidencia.Overload resolution finds the one method that best matches the arguments or reports an error if no single best match can be found. En el ejemplo siguiente se muestra la resolución de sobrecarga en vigor.The following example shows overload resolution in effect. El comentario para cada invocación del método Main muestra qué método se invoca realmente.The comment for each invocation in the Main method shows which method is actually invoked.

class Test
{
    static void F() {
        Console.WriteLine("F()");
    }

    static void F(object x) {
        Console.WriteLine("F(object)");
    }

    static void F(int x) {
        Console.WriteLine("F(int)");
    }

    static void F(double x) {
        Console.WriteLine("F(double)");
    }

    static void F<T>(T x) {
        Console.WriteLine("F<T>(T)");
    }

    static void F(double x, double y) {
        Console.WriteLine("F(double, double)");
    }

    static void Main() {
        F();                 // Invokes F()
        F(1);                // Invokes F(int)
        F(1.0);              // Invokes F(double)
        F("abc");            // Invokes F(object)
        F((double)1);        // Invokes F(double)
        F((object)1);        // Invokes F(object)
        F<int>(1);           // Invokes F<T>(T)
        F(1, 1);             // Invokes F(double, double)
    }
}

Tal como se muestra en el ejemplo, un método determinado siempre se puede seleccionar mediante la conversión explícita de los argumentos en los tipos de parámetros exactos o el suministro explícito de los argumentos de tipo.As shown by the example, a particular method can always be selected by explicitly casting the arguments to the exact parameter types and/or explicitly supplying type arguments.

Otros miembros de funciónOther function members

Los miembros que contienen código ejecutable se conocen colectivamente como miembros de función de una clase.Members that contain executable code are collectively known as the function members of a class. En la sección anterior se han descrito métodos, que son el tipo principal de los miembros de función.The preceding section describes methods, which are the primary kind of function members. En esta sección se describen los demás tipos de miembros de C#función admitidos por: constructores, propiedades, indexadores, eventos, operadores y destructores.This section describes the other kinds of function members supported by C#: constructors, properties, indexers, events, operators, and destructors.

En el código siguiente se muestra una clase List<T>genérica denominada, que implementa una lista de objetos que se va a ampliar.The following code shows a generic class called List<T>, which implements a growable list of objects. La clase contiene varios ejemplos de los tipos más comunes de miembros de función.The class contains several examples of the most common kinds of function members.

public class List<T> {
    // Constant...
    const int defaultCapacity = 4;

    // Fields...
    T[] items;
    int count;

    // Constructors...
    public List(int capacity = defaultCapacity) {
        items = new T[capacity];
    }

    // Properties...
    public int Count {
        get { return count; }
    }
    public int Capacity {
        get {
            return items.Length;
        }
        set {
            if (value < count) value = count;
            if (value != items.Length) {
                T[] newItems = new T[value];
                Array.Copy(items, 0, newItems, 0, count);
                items = newItems;
            }
        }
    }

    // Indexer...
    public T this[int index] {
        get {
            return items[index];
        }
        set {
            items[index] = value;
            OnChanged();
        }
    }

    // Methods...
    public void Add(T item) {
        if (count == Capacity) Capacity = count * 2;
        items[count] = item;
        count++;
        OnChanged();
    }
    protected virtual void OnChanged() {
        if (Changed != null) Changed(this, EventArgs.Empty);
    }
    public override bool Equals(object other) {
        return Equals(this, other as List<T>);
    }
    static bool Equals(List<T> a, List<T> b) {
        if (a == null) return b == null;
        if (b == null || a.count != b.count) return false;
        for (int i = 0; i < a.count; i++) {
            if (!object.Equals(a.items[i], b.items[i])) {
                return false;
            }
        }
        return true;
    }

    // Event...
    public event EventHandler Changed;

    // Operators...
    public static bool operator ==(List<T> a, List<T> b) {
        return Equals(a, b);
    }
    public static bool operator !=(List<T> a, List<T> b) {
        return !Equals(a, b);
    }
}

ConstructoresConstructors

C# admite constructores de instancia y estáticos.C# supports both instance and static constructors. Un constructor de instancia es un miembro que implementa las acciones necesarias para inicializar una instancia de una clase.An instance constructor is a member that implements the actions required to initialize an instance of a class. Un constructor estático es un miembro que implementa las acciones necesarias para inicializar una clase en sí misma cuando se carga por primera vez.A static constructor is a member that implements the actions required to initialize a class itself when it is first loaded.

Un constructor se declara como un método sin ningún tipo de valor devuelto y el mismo nombre que la clase contenedora.A constructor is declared like a method with no return type and the same name as the containing class. Si una declaración de constructor incluye static un modificador, declara un constructor estático.If a constructor declaration includes a static modifier, it declares a static constructor. De lo contrario, declara un constructor de instancia.Otherwise, it declares an instance constructor.

Los constructores de instancias se pueden sobrecargar.Instance constructors can be overloaded. Por ejemplo, la clase List<T> declara dos constructores de instancia, una sin parámetros y otra que toma un parámetro int.For example, the List<T> class declares two instance constructors, one with no parameters and one that takes an int parameter. Los constructores de instancia se invocan mediante el operador new.Instance constructors are invoked using the new operator. Las instrucciones siguientes asignan List<string> dos instancias de mediante cada uno de los constructores de la List clase.The following statements allocate two List<string> instances using each of the constructors of the List class.

List<string> list1 = new List<string>();
List<string> list2 = new List<string>(10);

A diferencia de otros miembros, los constructores de instancia no se heredan y una clase no tiene ningún constructor de instancia que no sea el que se declara realmente en la clase.Unlike other members, instance constructors are not inherited, and a class has no instance constructors other than those actually declared in the class. Si no se proporciona ningún constructor de instancia para una clase, se proporciona automáticamente uno vacío sin ningún parámetro.If no instance constructor is supplied for a class, then an empty one with no parameters is automatically provided.

PropiedadesProperties

Las propiedades son una extensión natural de los campos.Properties are a natural extension of fields. Ambos son miembros con nombre con tipos asociados y la sintaxis para acceder a los campos y las propiedades es la misma.Both are named members with associated types, and the syntax for accessing fields and properties is the same. Sin embargo, a diferencia de los campos, las propiedades no denotan ubicaciones de almacenamiento.However, unlike fields, properties do not denote storage locations. Las propiedades tienen descriptores de acceso que especifican las instrucciones que se ejecutan cuando se leen o escriben sus valores.Instead, properties have accessors that specify the statements to be executed when their values are read or written.

Una propiedad se declara como un campo, salvo que la declaración finaliza con un get descriptor de acceso set o un descriptor de acceso { escrito } entre los delimitadores y en lugar de terminar en un punto y coma.A property is declared like a field, except that the declaration ends with a get accessor and/or a set accessor written between the delimiters { and } instead of ending in a semicolon. Una propiedad que tiene tanto un get descriptor set de acceso como un descriptor de acceso es una propiedad de lectura y escritura, una propiedad que solo tiene un get descriptor de acceso es una propiedad de solo lecturay una propiedad que solo tiene un set descriptor de acceso es un propiedad de solo escritura.A property that has both a get accessor and a set accessor is a read-write property, a property that has only a get accessor is a read-only property, and a property that has only a set accessor is a write-only property.

Un get descriptor de acceso corresponde a un método sin parámetros con un valor devuelto del tipo de propiedad.A get accessor corresponds to a parameterless method with a return value of the property type. Excepto como destino de una asignación, cuando se hace referencia a una propiedad en una expresión, el get descriptor de acceso de la propiedad se invoca para calcular el valor de la propiedad.Except as the target of an assignment, when a property is referenced in an expression, the get accessor of the property is invoked to compute the value of the property.

Un set descriptor de acceso corresponde a un método con value un solo parámetro denominado y ningún tipo de valor devuelto.A set accessor corresponds to a method with a single parameter named value and no return type. Cuando se hace referencia a una propiedad como el destino de una asignación o como el operando --de o set , el descriptor de ++ acceso se invoca con un argumento que proporciona el nuevo valor.When a property is referenced as the target of an assignment or as the operand of ++ or --, the set accessor is invoked with an argument that provides the new value.

La clase List<T> declara dos propiedades, Count y Capacity, que son de solo lectura y de lectura y escritura, respectivamente.The List<T> class declares two properties, Count and Capacity, which are read-only and read-write, respectively. El siguiente es un ejemplo de uso de estas propiedades.The following is an example of use of these properties.

List<string> names = new List<string>();
names.Capacity = 100;            // Invokes set accessor
int i = names.Count;             // Invokes get accessor
int j = names.Capacity;          // Invokes get accessor

De forma similar a los campos y métodos, C# admite propiedades de instancia y propiedades estáticas.Similar to fields and methods, C# supports both instance properties and static properties. Las propiedades estáticas se declaran con el static modificador y las propiedades de instancia se declaran sin ella.Static properties are declared with the static modifier, and instance properties are declared without it.

Los descriptores de acceso de una propiedad pueden ser virtuales.The accessor(s) of a property can be virtual. Cuando una declaración de propiedad incluye un modificador virtual, abstract o override, se aplica a los descriptores de acceso de la propiedad.When a property declaration includes a virtual, abstract, or override modifier, it applies to the accessor(s) of the property.

IndizadoresIndexers

Un indexador es un miembro que permite indexar de la misma manera que una matriz.An indexer is a member that enables objects to be indexed in the same way as an array. Un indexador se declara como una propiedad, excepto por el hecho que el nombre del miembro es this, seguido por una lista de parámetros que se escriben entre los delimitadores [ y ].An indexer is declared like a property except that the name of the member is this followed by a parameter list written between the delimiters [ and ]. Los parámetros están disponibles en los descriptores de acceso del indexador.The parameters are available in the accessor(s) of the indexer. De forma similar a las propiedades, los indexadores pueden ser lectura y escritura, de solo lectura y de solo escritura, y los descriptores de acceso de un indexador pueden ser virtuales.Similar to properties, indexers can be read-write, read-only, and write-only, and the accessor(s) of an indexer can be virtual.

La clase List declara un único indexador de lectura y escritura que toma un parámetro int.The List class declares a single read-write indexer that takes an int parameter. El indexador permite indexar instancias de List con valores int.The indexer makes it possible to index List instances with int values. Por ejemploFor example

List<string> names = new List<string>();
names.Add("Liz");
names.Add("Martha");
names.Add("Beth");
for (int i = 0; i < names.Count; i++) {
    string s = names[i];
    names[i] = s.ToUpper();
}

Los indexadores se pueden sobrecargar, lo que significa que una clase puede declarar varios indexadores siempre y cuando el número o los tipos de sus parámetros sean diferentes.Indexers can be overloaded, meaning that a class can declare multiple indexers as long as the number or types of their parameters differ.

EventosEvents

Un evento es un miembro que permite que una clase u objeto proporcionen notificaciones.An event is a member that enables a class or object to provide notifications. Un evento se declara como un campo salvo que la Declaración incluye una event palabra clave y el tipo debe ser un tipo de delegado.An event is declared like a field except that the declaration includes an event keyword and the type must be a delegate type.

Dentro de una clase que declara un miembro de evento, el evento se comporta como un campo de un tipo delegado (siempre que el evento no sea abstracto y no declare descriptores de acceso).Within a class that declares an event member, the event behaves just like a field of a delegate type (provided the event is not abstract and does not declare accessors). El campo almacena una referencia a un delegado que representa los controladores de eventos que se han agregado al evento.The field stores a reference to a delegate that represents the event handlers that have been added to the event. Si no hay ningún controlador de eventos presente, el nullcampo es.If no event handles are present, the field is null.

La clase List<T> declara un único miembro de evento llamado Changed, lo que indica que se ha agregado un nuevo elemento a la lista.The List<T> class declares a single event member called Changed, which indicates that a new item has been added to the list. El evento lo desencadena el OnChanged método virtual, que primero comprueba si el evento es null (lo que significa que no hay ningún controlador presente). ChangedThe Changed event is raised by the OnChanged virtual method, which first checks whether the event is null (meaning that no handlers are present). La noción de generar un evento es equivalente exactamente a invocar el delegado representado por el evento; por lo tanto, no hay ninguna construcción especial de lenguaje para generar eventos.The notion of raising an event is precisely equivalent to invoking the delegate represented by the event—thus, there are no special language constructs for raising events.

Los clientes reaccionan a los eventos mediante controladores de eventos.Clients react to events through event handlers. Los controladores de eventos se asocian mediante el operador += y se quitan con el operador -=.Event handlers are attached using the += operator and removed using the -= operator. En el ejemplo siguiente se asocia un controlador de eventos con el evento Changed de un objeto List<string>.The following example attaches an event handler to the Changed event of a List<string>.

using System;

class Test
{
    static int changeCount;

    static void ListChanged(object sender, EventArgs e) {
        changeCount++;
    }

    static void Main() {
        List<string> names = new List<string>();
        names.Changed += new EventHandler(ListChanged);
        names.Add("Liz");
        names.Add("Martha");
        names.Add("Beth");
        Console.WriteLine(changeCount);        // Outputs "3"
    }
}

Para escenarios avanzados donde se desea controlar el almacenamiento subyacente de un evento, una declaración de evento puede proporcionar explícitamente los descriptores de acceso add y remove, que son similares en cierto modo al descriptor de acceso set de una propiedad.For advanced scenarios where control of the underlying storage of an event is desired, an event declaration can explicitly provide add and remove accessors, which are somewhat similar to the set accessor of a property.

OperadoresOperators

Un operador es un miembro que define el significado de aplicar un operador de expresión determinado a las instancias de una clase.An operator is a member that defines the meaning of applying a particular expression operator to instances of a class. Se pueden definir tres tipos de operadores: operadores unarios, operadores binarios y operadores de conversión.Three kinds of operators can be defined: unary operators, binary operators, and conversion operators. Todos los operadores se deben declarar como public y static.All operators must be declared as public and static.

La clase List<T> declara dos operadores, operator== y operator!=, y de este modo proporciona un nuevo significado a expresiones que aplican esos operadores a instancias List.The List<T> class declares two operators, operator== and operator!=, and thus gives new meaning to expressions that apply those operators to List instances. En concreto, los operadores definen la igualdad List<T> de dos instancias como la comparación de cada uno de los Equals objetos contenidos mediante sus métodos.Specifically, the operators define equality of two List<T> instances as comparing each of the contained objects using their Equals methods. En el ejemplo siguiente se usa el operador == para comparar dos instancias List<int>.The following example uses the == operator to compare two List<int> instances.

using System;

class Test
{
    static void Main() {
        List<int> a = new List<int>();
        a.Add(1);
        a.Add(2);
        List<int> b = new List<int>();
        b.Add(1);
        b.Add(2);
        Console.WriteLine(a == b);        // Outputs "True"
        b.Add(3);
        Console.WriteLine(a == b);        // Outputs "False"
    }
}

El primer objeto Console.WriteLine genera True porque las dos listas contienen el mismo número de objetos con los mismos valores en el mismo orden.The first Console.WriteLine outputs True because the two lists contain the same number of objects with the same values in the same order. Si List<T> no hubiera definido operator==, el primer objeto Console.WriteLine habría generado False porque a y b hacen referencia a diferentes instancias de List<int>.Had List<T> not defined operator==, the first Console.WriteLine would have output False because a and b reference different List<int> instances.

DestructoresDestructors

Un destructor es un miembro que implementa las acciones necesarias para destruir una instancia de una clase.A destructor is a member that implements the actions required to destruct an instance of a class. Los destructores no pueden tener parámetros, no pueden tener modificadores de accesibilidad y no se pueden invocar explícitamente.Destructors cannot have parameters, they cannot have accessibility modifiers, and they cannot be invoked explicitly. El destructor de una instancia se invoca automáticamente durante la recolección de elementos no utilizados.The destructor for an instance is invoked automatically during garbage collection.

El recolector de elementos no utilizados tiene una latitud ancha a la hora de decidir cuándo recopilar objetos y ejecutar destructores.The garbage collector is allowed wide latitude in deciding when to collect objects and run destructors. En concreto, el tiempo de las invocaciones de destructor no es determinista y los destructores se pueden ejecutar en cualquier subproceso.Specifically, the timing of destructor invocations is not deterministic, and destructors may be executed on any thread. Por estas y otras razones, las clases deben implementar destructores solo cuando no sean factibles otras soluciones.For these and other reasons, classes should implement destructors only when no other solutions are feasible.

La instrucción using proporciona un mejor enfoque para la destrucción de objetos.The using statement provides a better approach to object destruction.

EstructurasStructs

Al igual que las clases, los structs son estructuras de datos que pueden contener miembros de datos y miembros de función, pero a diferencia de las clases, los structs son tipos de valor y no requieren asignación del montón.Like classes, structs are data structures that can contain data members and function members, but unlike classes, structs are value types and do not require heap allocation. Una variable de un tipo de struct almacena directamente los datos del struct, mientras que una variable de un tipo de clase almacena una referencia a un objeto asignado dinámicamente.A variable of a struct type directly stores the data of the struct, whereas a variable of a class type stores a reference to a dynamically allocated object. Los tipos struct no admiten la herencia especificada por el usuario y todos los tipos de struct se heredan implícitamente del tipo object.Struct types do not support user-specified inheritance, and all struct types implicitly inherit from type object.

Los structs son particularmente útiles para estructuras de datos pequeñas que tengan semánticas de valor.Structs are particularly useful for small data structures that have value semantics. Los números complejos, los puntos de un sistema de coordenadas o los pares clave-valor de un diccionario son buenos ejemplos de structs.Complex numbers, points in a coordinate system, or key-value pairs in a dictionary are all good examples of structs. El uso de un struct en lugar de una clase para estructuras de datos pequeñas puede suponer una diferencia sustancial en el número de asignaciones de memoria que realiza una aplicación.The use of structs rather than classes for small data structures can make a large difference in the number of memory allocations an application performs. Por ejemplo, el siguiente programa crea e inicializa una matriz de 100 puntos.For example, the following program creates and initializes an array of 100 points. Si Point se implementa como una clase, se crean instancias de 101 objetos distintos: uno para la matriz y uno por cada uno de los 100 elementos.With Point implemented as a class, 101 separate objects are instantiated—one for the array and one each for the 100 elements.

class Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

class Test
{
    static void Main() {
        Point[] points = new Point[100];
        for (int i = 0; i < 100; i++) points[i] = new Point(i, i);
    }
}

Una alternativa es crear Point un struct.An alternative is to make Point a struct.

struct Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Ahora, se crea la instancia de un solo objeto: la de la matriz, y las instancias de Point se asignan en línea dentro de la matriz.Now, only one object is instantiated—the one for the array—and the Point instances are stored in-line in the array.

Los structs se invocan con el operador new, pero eso no implica que se asigne memoria.Struct constructors are invoked with the new operator, but that does not imply that memory is being allocated. En lugar de asignar dinámicamente un objeto y devolver una referencia a él, un constructor de structs simplemente devuelve el valor del struct propiamente dicho (normalmente en una ubicación temporal en la pila) y este valor se copia luego cuando es necesario.Instead of dynamically allocating an object and returning a reference to it, a struct constructor simply returns the struct value itself (typically in a temporary location on the stack), and this value is then copied as necessary.

Con las clases, es posible que dos variables hagan referencia al mismo objeto y, que por tanto, las operaciones en una variable afecten al objeto al que hace referencia la otra variable.With classes, it is possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. Con los struct, cada variable tiene su propia copia de los datos y no es posible que las operaciones en una afecten a la otra.With structs, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other. Por ejemplo, la salida generada por el fragmento de código siguiente depende Point de si es una clase o un struct.For example, the output produced by the following code fragment depends on whether Point is a class or a struct.

Point a = new Point(10, 10);
Point b = a;
a.x = 20;
Console.WriteLine(b.x);

Si Point es una clase, el resultado es 20 porque a y b hacen referencia al mismo objeto.If Point is a class, the output is 20 because a and b reference the same object. Si Point es un struct, el resultado es 10 porque la asignación de a a b crea una copia del valor, y esta copia no se ve afectada por la asignación subsiguiente a a.x.If Point is a struct, the output is 10 because the assignment of a to b creates a copy of the value, and this copy is unaffected by the subsequent assignment to a.x.

En el ejemplo anterior se resaltan dos de las limitaciones de los structs.The previous example highlights two of the limitations of structs. En primer lugar, copiar un struct entero normalmente es menos eficaz que copiar una referencia a un objeto, por lo que el paso de parámetros de asignación y valor puede ser más costoso con structs que con tipos de referencia.First, copying an entire struct is typically less efficient than copying an object reference, so assignment and value parameter passing can be more expensive with structs than with reference types. En segundo lugar, a excepción de los parámetros ref y out, no es posible crear referencias a structs, que excluyen su uso en varias situaciones.Second, except for ref and out parameters, it is not possible to create references to structs, which rules out their usage in a number of situations.

MatricesArrays

Una matriz es una estructura de datos que contiene un número de variables a las que se accede mediante índices calculados.An array is a data structure that contains a number of variables that are accessed through computed indices. Las variables contenidas en una matriz, denominadas también elementos de la matriz, son todas del mismo tipo y este tipo se conoce como tipo de elemento de la matriz.The variables contained in an array, also called the elements of the array, are all of the same type, and this type is called the element type of the array.

Los tipos de matriz son tipos de referencia, y la declaración de una variable de matriz simplemente establece un espacio reservado para una referencia a una instancia de matriz.Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Las instancias de matriz reales se crean dinámicamente en tiempo de ejecución new mediante el operador.Actual array instances are created dynamically at run-time using the new operator. La new operación especifica la longitud de la nueva instancia de la matriz, que se corrige para la duración de la instancia.The new operation specifies the length of the new array instance, which is then fixed for the lifetime of the instance. Los índices de los elementos de una matriz van de 0 a Length - 1.The indices of the elements of an array range from 0 to Length - 1. El operador new inicializa automáticamente los elementos de una matriz a su valor predeterminado, que, por ejemplo, es cero para todos los tipos numéricos y null para todos los tipos de referencias.The new operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and null for all reference types.

En el ejemplo siguiente se crea una matriz de elementos int, se inicializa la matriz y se imprime el contenido de la matriz.The following example creates an array of int elements, initializes the array, and prints out the contents of the array.

using System;

class Test
{
    static void Main() {
        int[] a = new int[10];
        for (int i = 0; i < a.Length; i++) {
            a[i] = i * i;
        }
        for (int i = 0; i < a.Length; i++) {
            Console.WriteLine("a[{0}] = {1}", i, a[i]);
        }
    }
}

Este ejemplo se crea y se pone en funcionamiento en una matriz unidimensional.This example creates and operates on a single-dimensional array. C# también admite matrices multidimensionales.C# also supports multi-dimensional arrays. El número de dimensiones de un tipo de matriz, conocido también como rango del tipo de matriz, es una más el número de comas escritas entre los corchetes del tipo de matriz.The number of dimensions of an array type, also known as the rank of the array type, is one plus the number of commas written between the square brackets of the array type. En el ejemplo siguiente se asigna una matriz unidimensional, bidimensional y de tres dimensiones.The following example allocates a one-dimensional, a two-dimensional, and a three-dimensional array.

int[] a1 = new int[10];
int[,] a2 = new int[10, 5];
int[,,] a3 = new int[10, 5, 2];

La matriz a1 contiene 10 elementos, la matriz a2 50 (10 × 5) elementos y la matriz a3 100 (10 × 5 × 2) elementos.The a1 array contains 10 elements, the a2 array contains 50 (10 × 5) elements, and the a3 array contains 100 (10 × 5 × 2) elements.

El tipo de elemento de una matriz puede ser cualquiera, incluido un tipo de matriz.The element type of an array can be any type, including an array type. Una matriz con elementos de un tipo de matriz a veces se conoce como matriz escalonada porque las longitudes de las matrices de elementos no tienen que ser iguales.An array with elements of an array type is sometimes called a jagged array because the lengths of the element arrays do not all have to be the same. En el ejemplo siguiente se asigna una matriz de matrices de int:The following example allocates an array of arrays of int:

int[][] a = new int[3][];
a[0] = new int[10];
a[1] = new int[5];
a[2] = new int[20];

La primera línea crea una matriz con tres elementos, cada uno de tipo int[] y cada uno con un valor inicial de null.The first line creates an array with three elements, each of type int[] and each with an initial value of null. Las líneas posteriores inicializan entonces los tres elementos con referencias a instancias de matriz individuales de longitud variable.The subsequent lines then initialize the three elements with references to individual array instances of varying lengths.

El new operador permite especificar los valores iniciales de los elementos de la matriz mediante un inicializador de matriz, que es una lista de expresiones escritas entre { los delimitadores y. }The new operator permits the initial values of the array elements to be specified using an array initializer, which is a list of expressions written between the delimiters { and }. En el ejemplo siguiente se asigna e inicializa un tipo int[] con tres elementos.The following example allocates and initializes an int[] with three elements.

int[] a = new int[] {1, 2, 3};

Tenga en cuenta que la longitud de la matriz se deduce del número de expresiones { entre }y.Note that the length of the array is inferred from the number of expressions between { and }. Las declaraciones de variable local y campo se pueden acortar más para que así no sea necesario reformular el tipo de matriz.Local variable and field declarations can be shortened further such that the array type does not have to be restated.

int[] a = {1, 2, 3};

Los dos ejemplos anteriores son equivalentes a lo siguiente:Both of the previous examples are equivalent to the following:

int[] t = new int[3];
t[0] = 1;
t[1] = 2;
t[2] = 3;
int[] a = t;

InterfacesInterfaces

Una interfaz define un contrato que se puede implementar mediante clases y structs.An interface defines a contract that can be implemented by classes and structs. Una interfaz puede contener métodos, propiedades, eventos e indexadores.An interface can contain methods, properties, events, and indexers. Una interfaz no proporciona implementaciones de los miembros que define, simplemente especifica los miembros que se deben proporcionar mediante clases o structs que implementan la interfaz.An interface does not provide implementations of the members it defines—it merely specifies the members that must be supplied by classes or structs that implement the interface.

Las interfaces pueden usar herencia múltiple.Interfaces may employ multiple inheritance. En el ejemplo siguiente, la interfaz IComboBox hereda de ITextBox y IListBox.In the following example, the interface IComboBox inherits from both ITextBox and IListBox.

interface IControl
{
    void Paint();
}

interface ITextBox: IControl
{
    void SetText(string text);
}

interface IListBox: IControl
{
    void SetItems(string[] items);
}

interface IComboBox: ITextBox, IListBox {}

Las clases y los structs pueden implementar varias interfaces.Classes and structs can implement multiple interfaces. En el ejemplo siguiente, la clase EditBox implementa IControl y IDataBound.In the following example, the class EditBox implements both IControl and IDataBound.

interface IDataBound
{
    void Bind(Binder b);
}

public class EditBox: IControl, IDataBound
{
    public void Paint() {...}
    public void Bind(Binder b) {...}
}

Cuando una clase o un struct implementan una interfaz determinada, las instancias de esa clase o struct se pueden convertir implícitamente a ese tipo de interfaz.When a class or struct implements a particular interface, instances of that class or struct can be implicitly converted to that interface type. Por ejemploFor example

EditBox editBox = new EditBox();
IControl control = editBox;
IDataBound dataBound = editBox;

En casos donde una instancia no se conoce estáticamente para implementar una interfaz determinada, se pueden usar conversiones de tipo dinámico.In cases where an instance is not statically known to implement a particular interface, dynamic type casts can be used. Por ejemplo, las siguientes instrucciones usan conversiones de tipo dinámico para obtener las implementaciones IDataBound de un objeto y de la IControl interfaz.For example, the following statements use dynamic type casts to obtain an object's IControl and IDataBound interface implementations. Dado que el tipo real del objeto es EditBox, las conversiones se realizan correctamente.Because the actual type of the object is EditBox, the casts succeed.

object obj = new EditBox();
IControl control = (IControl)obj;
IDataBound dataBound = (IDataBound)obj;

En la clase EditBox anterior, el Paint método de la IControl interfaz y el Bind método de la IDataBound interfaz se implementan public mediante miembros.In the previous EditBox class, the Paint method from the IControl interface and the Bind method from the IDataBound interface are implemented using public members. C#también admite implementaciones explícitas de miembros de interfaz, con las que la clase o estructura puede publicevitar la creación de miembros.C# also supports explicit interface member implementations, using which the class or struct can avoid making the members public. Una implementación de miembro de interfaz explícito se escribe con el nombre de miembro de interfaz completo.An explicit interface member implementation is written using the fully qualified interface member name. Por ejemplo, la clase EditBox podría implementar los métodos IControl.Paint y IDataBound.Bind mediante implementaciones de miembros de interfaz explícitos del modo siguiente.For example, the EditBox class could implement the IControl.Paint and IDataBound.Bind methods using explicit interface member implementations as follows.

public class EditBox: IControl, IDataBound
{
    void IControl.Paint() {...}
    void IDataBound.Bind(Binder b) {...}
}

Solo se puede acceder a los miembros de interfaz explícitos mediante el tipo de interfaz.Explicit interface members can only be accessed via the interface type. Por ejemplo, la implementación de IControl.Paint proporcionada por la clase EditBox anterior solo se puede invocar IControl convirtiendo primero la EditBox referencia al tipo de interfaz.For example, the implementation of IControl.Paint provided by the previous EditBox class can only be invoked by first converting the EditBox reference to the IControl interface type.

EditBox editBox = new EditBox();
editBox.Paint();                        // Error, no such method
IControl control = editBox;
control.Paint();                        // Ok

EnumeracionesEnums

Un tipo de enumeración es un tipo de valor distinto con un conjunto de constantes con nombre.An enum type is a distinct value type with a set of named constants. En el ejemplo siguiente se declara y se utiliza un tipo Color de enumeración denominado con Redtres Greenvalores constantes Blue,, y.The following example declares and uses an enum type named Color with three constant values, Red, Green, and Blue.

using System;

enum Color
{
    Red,
    Green,
    Blue
}

class Test
{
    static void PrintColor(Color color) {
        switch (color) {
            case Color.Red:
                Console.WriteLine("Red");
                break;
            case Color.Green:
                Console.WriteLine("Green");
                break;
            case Color.Blue:
                Console.WriteLine("Blue");
                break;
            default:
                Console.WriteLine("Unknown color");
                break;
        }
    }

    static void Main() {
        Color c = Color.Red;
        PrintColor(c);
        PrintColor(Color.Blue);
    }
}

Cada tipo de enumeración tiene un tipo entero correspondiente denominado el tipo subyacente del tipo de enumeración.Each enum type has a corresponding integral type called the underlying type of the enum type. Un tipo de enumeración que no declara explícitamente un tipo subyacente tiene un tipo intsubyacente de.An enum type that does not explicitly declare an underlying type has an underlying type of int. El formato de almacenamiento y el intervalo de valores posibles de un tipo enum vienen determinados por su tipo subyacente.An enum type's storage format and range of possible values are determined by its underlying type. El conjunto de valores que puede tomar un tipo de enumeración no está limitado por sus miembros de enumeración.The set of values that an enum type can take on is not limited by its enum members. En concreto, cualquier valor del tipo subyacente de una enumeración se puede convertir al tipo de enumeración y es un valor válido distinto de ese tipo de enumeración.In particular, any value of the underlying type of an enum can be cast to the enum type and is a distinct valid value of that enum type.

En el ejemplo siguiente se declara un tipo de Alignment enumeración denominado con un sbytetipo subyacente de.The following example declares an enum type named Alignment with an underlying type of sbyte.

enum Alignment: sbyte
{
    Left = -1,
    Center = 0,
    Right = 1
}

Como se muestra en el ejemplo anterior, una declaración de miembro de enumeración puede incluir una expresión constante que especifique el valor del miembro.As shown by the previous example, an enum member declaration can include a constant expression that specifies the value of the member. El valor constante para cada miembro de la enumeración debe estar en el intervalo del tipo subyacente de la enumeración.The constant value for each enum member must be in the range of the underlying type of the enum. Cuando una declaración de miembro de enumeración no especifica explícitamente un valor, el miembro recibe el valor cero (si es el primer miembro del tipo de enumeración) o el valor del miembro de enumeración anterior textual más uno.When an enum member declaration does not explicitly specify a value, the member is given the value zero (if it is the first member in the enum type) or the value of the textually preceding enum member plus one.

Los valores de enumeración se pueden convertir en valores enteros y viceversa mediante conversiones de tipos.Enum values can be converted to integral values and vice versa using type casts. Por ejemploFor example

int i = (int)Color.Blue;        // int i = 2;
Color c = (Color)2;             // Color c = Color.Blue;

El valor predeterminado de cualquier tipo de enumeración es el valor entero cero convertido al tipo de enumeración.The default value of any enum type is the integral value zero converted to the enum type. En los casos en los que las variables se inicializan automáticamente en un valor predeterminado, este es el valor dado a las variables de los tipos de enumeración.In cases where variables are automatically initialized to a default value, this is the value given to variables of enum types. Para que el valor predeterminado de un tipo de enumeración sea fácilmente disponible, el literal 0 se convierte implícitamente a cualquier tipo de enumeración.In order for the default value of an enum type to be easily available, the literal 0 implicitly converts to any enum type. Por tanto, el siguiente código es válido.Thus, the following is permitted.

Color c = 0;

DelegadosDelegates

Un tipo de delegado representa las referencias a métodos con una lista de parámetros determinada y un tipo de valor devuelto.A delegate type represents references to methods with a particular parameter list and return type. Los delegados permiten tratar métodos como entidades que se puedan asignar a variables y se puedan pasar como parámetros.Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Los delegados son similares al concepto de punteros de función en otros lenguajes, pero a diferencia de los punteros de función, los delegados están orientados a objetos y presentan seguridad de tipos.Delegates are similar to the concept of function pointers found in some other languages, but unlike function pointers, delegates are object-oriented and type-safe.

En el siguiente ejemplo se declara y usa un tipo de delegado denominado Function.The following example declares and uses a delegate type named Function.

using System;

delegate double Function(double x);

class Multiplier
{
    double factor;

    public Multiplier(double factor) {
        this.factor = factor;
    }

    public double Multiply(double x) {
        return x * factor;
    }
}

class Test
{
    static double Square(double x) {
        return x * x;
    }

    static double[] Apply(double[] a, Function f) {
        double[] result = new double[a.Length];
        for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
        return result;
    }

    static void Main() {
        double[] a = {0.0, 0.5, 1.0};
        double[] squares = Apply(a, Square);
        double[] sines = Apply(a, Math.Sin);
        Multiplier m = new Multiplier(2.0);
        double[] doubles =  Apply(a, m.Multiply);
    }
}

Una instancia del tipo de delegado Function puede hacer referencia a cualquier método que tome un argumento double y devuelva un valor double.An instance of the Function delegate type can reference any method that takes a double argument and returns a double value. El Apply método aplica un determinado Function a los elementos de un double[], devolviendo double[] un con los resultados.The Apply method applies a given Function to the elements of a double[], returning a double[] with the results. En el método Main, Apply se usa para aplicar tres funciones diferentes a un valor double[].In the Main method, Apply is used to apply three different functions to a double[].

Un delegado puede hacer referencia a un método estático (como Square o Math.Sin en el ejemplo anterior) o un método de instancia (como m.Multiply en el ejemplo anterior).A delegate can reference either a static method (such as Square or Math.Sin in the previous example) or an instance method (such as m.Multiply in the previous example). Un delegado que hace referencia a un método de instancia también hace referencia a un objeto determinado y, cuando se invoca el método de instancia a través del delegado, ese objeto se convierte en this en la invocación.A delegate that references an instance method also references a particular object, and when the instance method is invoked through the delegate, that object becomes this in the invocation.

Los delegados también pueden crearse mediante funciones anónimas, que son "métodos insertados" que se crean sobre la marcha.Delegates can also be created using anonymous functions, which are "inline methods" that are created on the fly. Las funciones anónimas pueden ver las variables locales de los métodos adyacentes.Anonymous functions can see the local variables of the surrounding methods. Por lo tanto, el ejemplo de multiplicador anterior se puede escribir más fácilmente Multiplier sin usar una clase:Thus, the multiplier example above can be written more easily without using a Multiplier class:

double[] doubles =  Apply(a, (double x) => x * 2.0);

Una propiedad interesante y útil de un delegado es que no sabe ni necesita conocer la clase del método al que hace referencia; lo único que importa es que el método al que se hace referencia tenga los mismos parámetros y el tipo de valor devuelto que el delegado.An interesting and useful property of a delegate is that it does not know or care about the class of the method it references; all that matters is that the referenced method has the same parameters and return type as the delegate.

AtributosAttributes

Los tipos, los miembros y otras entidades en un programa de C # admiten modificadores que controlan ciertos aspectos de su comportamiento.Types, members, and other entities in a C# program support modifiers that control certain aspects of their behavior. Por ejemplo, la accesibilidad de un método se controla mediante los modificadores public, protected, internal y private.For example, the accessibility of a method is controlled using the public, protected, internal, and private modifiers. C # generaliza esta funcionalidad de manera que los tipos de información declarativa definidos por el usuario se puedan adjuntar a las entidades del programa y recuperarse en tiempo de ejecución.C# generalizes this capability such that user-defined types of declarative information can be attached to program entities and retrieved at run-time. Los programas especifican esta información declarativa adicional mediante la definición y el uso de atributos.Programs specify this additional declarative information by defining and using attributes.

En el ejemplo siguiente se declara un atributo HelpAttribute que se puede colocar en entidades de programa para proporcionar vínculos a la documentación asociada.The following example declares a HelpAttribute attribute that can be placed on program entities to provide links to their associated documentation.

using System;

public class HelpAttribute: Attribute
{
    string url;
    string topic;

    public HelpAttribute(string url) {
        this.url = url;
    }

    public string Url {
        get { return url; }
    }

    public string Topic {
        get { return topic; }
        set { topic = value; }
    }
}

Todas las clases de atributo derivan de la System.Attribute clase base proporcionada por el .NET Framework.All attribute classes derive from the System.Attribute base class provided by the .NET Framework. Los atributos se pueden aplicar proporcionando su nombre, junto con cualquier argumento, entre corchetes, justo antes de la declaración asociada.Attributes can be applied by giving their name, along with any arguments, inside square brackets just before the associated declaration. Si el nombre de un atributo termina Attributeen, esa parte del nombre se puede omitir cuando se hace referencia al atributo.If an attribute's name ends in Attribute, that part of the name can be omitted when the attribute is referenced. Por ejemplo, el atributo HelpAttribute se puede usar de la manera siguiente.For example, the HelpAttribute attribute can be used as follows.

[Help("http://msdn.microsoft.com/.../MyClass.htm")]
public class Widget
{
    [Help("http://msdn.microsoft.com/.../MyClass.htm", Topic = "Display")]
    public void Display(string text) {}
}

En este ejemplo se adjunta HelpAttribute un a Widget la Display clase y HelpAttribute otro al método en la clase.This example attaches a HelpAttribute to the Widget class and another HelpAttribute to the Display method in the class. Los constructores públicos de una clase de atributos controlan la información que se debe proporcionar cuando el atributo se adjunta a una entidad de programa.The public constructors of an attribute class control the information that must be provided when the attribute is attached to a program entity. Se puede proporcionar información adicional haciendo referencia a las propiedades públicas de lectura y escritura de la clase de atributos (como la referencia a la propiedad Topic usada anteriormente).Additional information can be provided by referencing public read-write properties of the attribute class (such as the reference to the Topic property previously).

En el ejemplo siguiente se muestra cómo se puede recuperar la información de atributos de una entidad de programa determinada en tiempo de ejecución mediante la reflexión.The following example shows how attribute information for a given program entity can be retrieved at run-time using reflection.

using System;
using System.Reflection;

class Test
{
    static void ShowHelp(MemberInfo member) {
        HelpAttribute a = Attribute.GetCustomAttribute(member,
            typeof(HelpAttribute)) as HelpAttribute;
        if (a == null) {
            Console.WriteLine("No help for {0}", member);
        }
        else {
            Console.WriteLine("Help for {0}:", member);
            Console.WriteLine("  Url={0}, Topic={1}", a.Url, a.Topic);
        }
    }

    static void Main() {
        ShowHelp(typeof(Widget));
        ShowHelp(typeof(Widget).GetMethod("Display"));
    }
}

Cuando se solicita un atributo determinado mediante reflexión, se invoca al constructor de la clase de atributos con la información proporcionada en el origen del programa y se devuelve la instancia de atributo resultante.When a particular attribute is requested through reflection, the constructor for the attribute class is invoked with the information provided in the program source, and the resulting attribute instance is returned. Si se proporciona información adicional mediante propiedades, dichas propiedades se establecen en los valores dados antes de devolver la instancia del atributo.If additional information was provided through properties, those properties are set to the given values before the attribute instance is returned.