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 compilador de C# 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, lo que permite que C# sea 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 _ recupera 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 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 que las programas y las bibliotecas de C# pueden evolucionar a lo largo del tiempo de manera compatible, se ha puesto mucho énfasis en el versionamiento del diseño de C#.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 del diseño de C# afectados directamente por las consideraciones de versionamiento incluyen los modificadores virtual
y override
independientes, las reglas para la resolución de sobrecargas de métodos y la compatibilidad para 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 del lenguaje C#.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 "Hello, World" 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 método Main
se declara con el modificador static
.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 cuenta que C# 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 tiempo de ejecución de C#.Instead, the .NET Framework is the runtime library of C#.
Estructura del programaProgram structure
Los conceptos clave de la organización 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 la extensión de archivo .exe
o .dll
, dependiendo de si implementan aplicaciones o _ bibliotecas *.Assemblies typically have the file extension .exe
or .dll
, depending on whether they implement applications or _*libraries**.
En 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.Collections
.declares 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 con el formato _ Metadata *.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, se acme.dll
puede hacer referencia al ensamblado mediante la opción del compilador /r
: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 tipos 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).
Los tipos de valor de C# se dividen en *** tipos simples*, _tipos de enumeración_, _tipos de struct_ y tipos que _aceptan valores NULL_, y los tipos de referencia de C# se dividen en _tipos de clase_, tipos de _interfaz_, _tipos de matriz*_ y 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 general sobre el sistema de tipos de C#.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 ,long Signed integral: sbyte , short , int , long |
Entero sin signo: byte , ushort , uint ,ulong Unsigned integral: byte , ushort , uint , ulong |
||
Caracteres Unicode: char Unicode characters: char |
||
Punto flotante de IEEE: float , double IEEE floating point: float , double |
||
Decimal de alta precisión: decimal High-precision decimal: decimal |
||
Booleano: bool Boolean: 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 null Extensions 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: object Ultimate base class of all other types: object |
Cadenas Unicode: string Unicode 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
y double
, 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.
El tipo de C# bool
se usa para representar valores booleanos: valores que son true
o false
.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 resumen los tipos numéricos de C#.The following table summarizes C#'s numeric types.
CategoríaCategory | BitsBits | TipoType | 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 las categorías de tipos de C# las define el usuario: tipos de clase, tipos de estructura, tipos de interfaz, tipos de enumeración y tipos delegados.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 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.
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 int
y es una matriz unidimensional de int[][]
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 de valor que no acepta valores NULL T
, existe un tipo que acepta valores NULL correspondiente T?
, que puede contener un valor adicional null
.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
.
El sistema de tipos de C# 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 mediante la realización de operaciones *Boxing _ y _ *conversión 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 tipo object
, 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.
El sistema de tipos unificado de C# significa 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 a partir de _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, el *precedencia _ de los operadores controla el orden en el 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 resumen los operadores de C# y se enumeran 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 | ExpressionExpression | 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 T Obtain 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 T Obtain 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 T Explicitly convert x to type T |
|
await x |
esperar asincrónicamente a que finalice x Asynchronously wait for x to complete |
|
MultiplicativaMultiplicative | x * y |
MultiplicaciónMultiplication |
x / y |
DivisiónDivision | |
x % y |
RestoRemainder | |
AditivaAdditive | 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 false Return 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 T Return x typed as T , or null if x is not a T |
|
IgualdadEquality | x == y |
IgualEqual |
x != y |
No igual aNot equal | |
Y 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 |
O 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 y si x es true Evaluates y only if x is true |
OR condicionalConditional OR | x || y |
Solo evalúa y si x es false Evaluates 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 false Evaluates 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 de objetos que usan el new
operador, las asignaciones mediante =
y los operadores de asignación compuesta, las operaciones de incremento y decremento mediante los ++
--
operadores y y las 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
unchecked
instrucciones 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 if
if
statement
static void Main(string[] args) {
if (args.Length == 0) {
Console.WriteLine("No arguments");
}
else {
Console.WriteLine("One or more arguments");
}
}
Instrucción switch
switch
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 while
while
statement
static void Main(string[] args) {
int i = 0;
while (i < args.Length) {
Console.WriteLine(args[i]);
i++;
}
}
Instrucción do
do
statement
static void Main() {
string s;
do {
s = Console.ReadLine();
if (s != null) Console.WriteLine(s);
} while (s != null);
}
Instrucción for
for
statement
static void Main(string[] args) {
for (int i = 0; i < args.Length; i++) {
Console.WriteLine(args[i]);
}
}
Instrucción foreach
foreach
statement
static void Main(string[] args) {
foreach (string s in args) {
Console.WriteLine(s);
}
}
Instrucción break
break
statement
static void Main() {
while (true) {
string s = Console.ReadLine();
if (s == null) break;
Console.WriteLine(s);
}
}
Instrucción continue
continue
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 goto
goto
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 return
return
statement
static int Add(int a, int b) {
return a + b;
}
static void Main() {
Console.WriteLine(Add(1, 2));
return;
}
Instrucción yield
yield
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);
}
}
throw``try
instrucciones 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!");
}
}
checked``unchecked
instrucciones 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 lock
lock
statement
class Account
{
decimal balance;
public void Withdraw(decimal amount) {
lock (this) {
if (amount > balance) {
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
Instrucción using
using
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 las 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 la herencia y el 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 objetos Point
y almacenan las referencias en 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.
MemberMember | 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 |
EventsEvents | 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. Estos se resumen en la siguiente tabla.These are summarized in the following table.
AccesibilidadAccessibility | SignificadoMeaning |
---|---|
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 pueden usarse luego en el cuerpo de las declaraciones de clase para definir a los miembros de la clase.The type parameters can then 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, como Pair<int,string>
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);
CamposFields
Un campo es una variable que está asociada con 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 un readonly
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. Se tiene acceso a los métodos estáticos a través de la clase.Static methods are accessed through the class. _ Se tiene acceso a los métodos de instancia* 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 *Parameters _, que representan valores o referencias a 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 de un método es void
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 métodos Write
y WriteLine
de la clase System.Console
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 void
instrucciones no, 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 modificador static
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 modificador static
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 de la clase Entity
.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 virtual
modificador, 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 de tiempo de ejecución* de la instancia para la que tiene lugar la invocación determina la implementación de método real que se va a 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 de 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 incluye un override
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 el abstract
modificador y solo se permite en una clase que también se declara abstract
.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 VariableReference
implementació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
El método *Overloading _ permite que varios métodos de la misma clase tengan el mismo nombre siempre y cuando tengan firmas ú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 _ Overload Resolution* para determinar el método específico que se va a 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 función admitidos por C#: 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 genérica denominada List<T>
, 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 _ static* 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 un modificador static
, 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 dos List<string>
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
*Properties _ 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. En su lugar, las propiedades tienen _ descriptores de acceso* que especifican las instrucciones que se ejecutarán cuando se lean o escriban 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 o un set
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 descriptor de acceso get
como un set
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 lectura y una propiedad que solo tiene un set
descriptor de acceso es una 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 un solo parámetro denominado value
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 --
, el set
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.
IndexadoresIndexers
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, excepto por el hecho de que la declaración incluye una palabra clave event
, y el tipo debe ser un tipo 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 campo es null
.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 Changed
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).The 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 de dos instancias List<T>
como la comparación de cada uno de los objetos contenidos con sus métodos Equals
.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 de si Point
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
*Array _ es una estructura de datos que contiene un número de variables a las que se tiene acceso a través de í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, también denominadas elementos de la matriz, son todas del mismo tipo y este tipo se denomina el 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 mediante el new
operador.Actual array instances are created dynamically at run-time using the new
operator. La operación new
especifica la longitud de la nueva instancia de matriz, que luego se fija para la vigencia 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]);
}
}
}
En este ejemplo se crea y funciona 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, también conocido como el _ rango* del tipo de matriz, es uno 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 operador new
permite especificar los valores iniciales de los elementos de matriz mediante un inicializador de matriz, que es una lista de las 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 de un objeto y de la IControl
IDataBound
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 EditBox
clase anterior, el Paint
método de la IControl
interfaz y el Bind
método de la IDataBound
interfaz se implementan mediante public
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 el struct pueden evitar la creación de miembros public
.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 EditBox
clase anterior solo se puede invocar convirtiendo primero la EditBox
referencia al IControl
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 de enumeración denominado Color
con tres valores constantes,, Red
Green
y Blue
.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 subyacente de int
.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 enumeración denominado Alignment
con un tipo subyacente de sbyte
.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 se 0
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 método Apply
aplica un elemento Function
determinado a los elementos de double[]
y devuelve double[]
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 sin usar una Multiplier
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 en Attribute
, 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 un HelpAttribute
a la Widget
clase y otro HelpAttribute
al Display
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.