Documente Academic
Documente Profesional
Documente Cultură
Clases y structs
Clases
Objects
Estructuras
Utilizar estructuras
Herencia
Polimorfismo
Control de versiones con las palabras clave Override y New
Saber cundo utilizar las palabras clave Override y New
Cmo: Invalidar el mtodo ToString
Clases y miembros de clase abstractos y sellados
Cmo: Definir propiedades abstractas
Clases estticas y sus miembros
Miembros
Modificadores de acceso
Campos
Constantes
Cmo: Definir constantes en C#
Propiedades
Utilizar propiedades
Propiedades de interfaz
Restringir la accesibilidad del descriptor de acceso
Cmo: Declarar y usar propiedades de lectura y escritura
Propiedades autoimplementadas
Cmo: Implementar una clase ligera con propiedades autoimplementadas
Mtodos
Funciones locales
Devoluciones y variables locales ref
Pasar parmetros
Variables locales con asignacin implcita de tipos
Mtodos de extensin
Argumentos opcionales y con nombre
Constructores
Utilizar constructores
Constructores de instancias
Constructores privados
Constructores estticos
Cmo: Escribir un constructor Copy
Finalizadores
Inicializadores de objeto y coleccin
Cmo: Inicializar un objeto usando un inicializador de objeto
Cmo: Inicializar un diccionario con un inicializador de coleccin
Cmo: Obtener acceso a una clase de coleccin mediante Foreach
Tipos anidados
Clases y mtodos parciales
Tipos annimos
Cmo: Devolver subconjuntos de propiedades de elementos en una consulta
Clases y structs (Gua de programacin de C#)
03/10/2017 6 min to read Edit Online
Las clases y estructuras son dos de las construcciones bsicas de Common Type System en .NET Framework.
Cada una de ellas es bsicamente una estructura de datos que encapsula un conjunto de datos y
comportamientos que forman un conjunto como una unidad lgica. Los datos y comportamientos son los
miembros de la clase o estructura, e incluyen sus mtodos, propiedades y eventos, entre otros elementos, como
se muestra ms adelante en este tema.
Una declaracin de clase o estructura es como un plano que se utiliza para crear instancias u objetos en tiempo
de ejecucin. Si define una clase o estructura llamada Person , Person es el nombre del tipo. Si declara e
inicializa una variable p de tipo Person , se dice que p es un objeto o instancia de Person . Se pueden crear
varias instancias del mismo tipo Person , y cada instancia tiene diferentes valores en sus propiedades y campos.
Una clase es un tipo de referencia. Cuando se crea un objeto de la clase, la variable a la que se asigna el objeto
contiene solo una referencia a esa memoria. Cuando la referencia de objeto se asigna a una nueva variable, la
nueva variable hace referencia al objeto original. Los cambios realizados en una variable se reflejan en la otra
variable porque ambas hacen referencia a los mismos datos.
Una estructura es un tipo de valor. Cuando se crea una estructura, la variable a la que se asigna la estructura
contiene los datos reales de ella. Cuando la estructura se asigna a una nueva variable, se copia. Por lo tanto, la
nueva variable y la variable original contienen dos copias independientes de los mismos datos. Los cambios
realizados en una copia no afectan a la otra copia.
En general, las clases se utilizan para modelar comportamientos ms complejos, o datos que se prevn modificar
despus de haber creado un objeto de clase. Las estructuras son ms adecuadas para las estructuras de datos
pequeas que contienen principalmente datos que no se prevn modificar despus de haber creado la
estructura.
Para ms informacin, vea Clases, Objectos y Estructuras.
Ejemplo
En el ejemplo siguiente, CustomClass en el espacio de nombres ProgrammingGuide tiene tres miembros: un
constructor de instancia, una propiedad denominada Number y un mtodo denominado Multiply . El mtodo
Main de la clase Program crea una instancia (objeto) de CustomClass , y se puede acceder a la propiedad y al
mtodo del objeto mediante una notacin de puntos.
using System;
namespace ProgrammingGuide
{
// Class definition.
public class CustomClass
{
// Class members.
//
// Property.
public int Number { get; set; }
// Method.
public int Multiply(int num)
{
return num * Number;
}
// Instance Constructor.
public CustomClass()
{
Number = 0;
}
}
// Another class definition that contains Main, the program entry point.
class Program
{
static void Main(string[] args)
{
// Create an object of type CustomClass.
CustomClass custClass = new CustomClass();
Encapsulacin
A veces se hace referencia a la encapsulacin como el primer pilar o principio de la programacin orientada a
objetos. Segn el principio de encapsulacin, una clase o una estructura pueden especificar hasta qu punto se
puede acceder a sus miembros para codificar fuera de la clase o la estructura. No se prev el uso de los mtodos
y las variables fuera de la clase, o el ensamblado puede ocultarse para limitar el potencial de los errores de
codificacin o de los ataques malintencionados.
Para ms informacin sobre las clases, vea Clases y Objetos.
Miembros
Todos los mtodos, campos, constantes, propiedades y eventos deben declararse dentro de un tipo; se les
denomina miembros del tipo. En C#, no hay mtodos ni variables globales como en otros lenguajes. Incluso un
punto de entrada del programa, el mtodo Main , debe declararse dentro de una clase o estructura. La lista
siguiente incluye los diversos tipos de miembros que se pueden declarar en una clase o estructura.
Campos
Constantes
Propiedades
Mtodos
Constructores
Eventos
Finalizadores
Indizadores
Operadores
Tipos anidados
Accesibilidad
Algunos mtodos y propiedades estn diseados para ser invocables y accesibles desde el cdigo fuera de la
clase o la estructura, lo que se conoce como cdigo de cliente. Otros mtodos y propiedades pueden estar
indicados exclusivamente para utilizarse en la propia clase o estructura. Es importante limitar la accesibilidad del
cdigo, a fin de que solo el cdigo de cliente previsto pueda acceder a l. Puede usar los modificadores de
acceso public, protected, internal, protected internal y private para especificar hasta qu punto los tipos y sus
miembros son accesibles para el cdigo de cliente. La accesibilidad predeterminada es private . Para ms
informacin, vea Modificadores de acceso.
Herencia
Las clases (pero no las estructuras) admiten el concepto de herencia. Una clase que deriva de otra clase (la clase
base) contiene automticamente todos los miembros pblicos, protegidos e internos de la clase base, salvo sus
constructores y finalizadores. Para ms informacin, vea Herencia y Polimorfismo.
Las clases pueden declararse como abstract, lo que significa que uno o varios de sus mtodos no tienen ninguna
implementacin. Aunque no se pueden crear instancias de clases abstractas directamente, pueden servir como
clases base para otras clases que proporcionan la implementacin que falta. Las clases tambin pueden
declararse como sealed para evitar que otras clases hereden de ellas. Para ms informacin, vea Clases y
miembros de clase abstractos y sellados.
Interfaces
Las clases y las estructuras pueden heredar varias interfaces. Heredar de una interfaz significa que el tipo
implementa todos los mtodos definidos en la interfaz. Para ms informacin, vea Interfaces.
Tipos genricos
Las clases y estructuras pueden definirse con uno o varios parmetros de tipo. El cdigo de cliente proporciona
el tipo cuando crea una instancia del tipo. Por ejemplo, la clase List<T> del espacio de nombres
System.Collections.Generic se define con un parmetro de tipo. El cdigo de cliente crea una instancia de
List<string> o List<int> para especificar el tipo que contendr la lista. Para ms informacin, vea Genricos.
Tipos estticos
Las clases (pero no las estructuras) pueden declararse como static. Una clase esttica puede contener solo
miembros estticos y no se puede crear una instancia de ellos con la palabra clave new. Una copia de la clase se
carga en memoria cuando se carga el programa, y sus miembros son accesibles a travs del nombre de clase.
Las clases y estructuras pueden contener miembros estticos. Para ms informacin, vea Clases estticas y sus
miembros.
Tipos anidados
Una clase o estructura se puede anidar dentro de otra clase o estructura. Para obtener ms informacin, consulte
Tipos anidados.
Tipos parciales
Puede definir parte de una clase, estructura o mtodo en un archivo de cdigo y otra parte en un archivo de
cdigo independiente. Para ms informacin, vea Clases y mtodos parciales.
Inicializadores de objeto
Puede crear instancias de objetos de clase o estructura y de colecciones de objetos e iniciarlizarlos, sin llamar de
forma explcita a su constructor. Para ms informacin, vea Inicializadores de objeto y de coleccin.
Tipos annimos
En situaciones donde no es conveniente o necesario crear una clase con nombre, por ejemplo al rellenar una
lista con estructuras de datos que no tiene que conservar o pasar a otro mtodo, utilice los tipos annimos. Para
ms informacin, vea Tipos annimos.
mtodos de extensin.
Puede "extender" una clase sin crear una clase derivada mediante la creacin de un tipo independiente cuyos
mtodos pueden llamarse como si pertenecieran al tipo original. Para ms informacin, vea Mtodos de
extensin.
Variables locales con asignacin implcita de tipos
Dentro de un mtodo de clase o estructura, puede utilizar tipos implcitos para indicar al compilador que
determine el tipo correcto en tiempo de compilacin. Para ms informacin, vea Variables locales con asignacin
implcita de tipos.
Vea tambin
Gua de programacin de C#
Clases (Gua de programacin de C#)
03/10/2017 5 min to read Edit Online
Una class es una construccin que le permite crear sus propios tipos personalizados agrupando las variables de
otros tipos, mtodos y eventos. Una clase es como un plano. Define los datos y el comportamiento de un tipo. Si la
clase no se declara como esttica, el cdigo de cliente puede usarla mediante la creacin de objetos o instancias
que se asignan a una variable. La variable permanece en memoria hasta que todas las referencias a ella estn
fuera del mbito. En ese momento, CLR la marca como apta para la recoleccin de elementos no utilizados. Si la
clase se declara como esttica, solo habr una copia en la memoria y el cdigo de cliente solo podr tener acceso a
ella a travs de la propia clase, y no a travs de una variable de instancia. Para obtener ms informacin, vea
Clases estticas y sus miembros.
A diferencia de los structs, las clases admiten la herencia, una caracterstica fundamental de la programacin
orientada a objetos. Para obtener ms informacin, vea Herencia.
Declarar clases
Las clases se declaran mediante la palabra clave class, como se muestra en el siguiente ejemplo:
La palabra clave class va precedida del nivel de acceso. Como en este caso se usa public, cualquier usuario puede
crear objetos de esta clase. El nombre de la clase sigue a la palabra clave class . El resto de la definicin es el
cuerpo de la clase, donde se definen los datos y el comportamiento. Los campos, las propiedades, los mtodos y
los eventos de una clase se denominan de forma colectiva miembros de clase.
Crear objetos
Aunque a veces se usan indistintamente, una clase y un objeto son cosas diferentes. Una clase define un tipo de
objeto, pero no es un objeto en s. Un objeto es una entidad concreta basada en una clase y, a veces, se conoce
como una instancia de una clase.
Los objetos se pueden crear usando la palabra clave new, seguida del nombre de la clase en la que se basar el
objeto, como en este ejemplo:
Cuando se crea una instancia de una clase, se vuelve a pasar al programador una referencia al objeto. En el
ejemplo anterior, object1 es una referencia a un objeto que se basa en Customer . Esta referencia apunta al objeto
nuevo, pero no contiene los datos del objeto. De hecho, puede crear una referencia de objeto sin tener que crear
ningn objeto:
Customer object2;
No se recomienda crear referencias de objeto como esta, que no hace referencia a ningn objeto, ya que, si se
intenta obtener acceso a un objeto a travs de este tipo de referencia, se producir un error en tiempo de
ejecucin. Pero dicha referencia puede haberse creado para hacer referencia a un objeto, ya sea creando un nuevo
objeto o asignndola a un objeto existente, como en el siguiente ejemplo:
Este cdigo crea dos referencias de objeto que hacen referencia al mismo objeto. Por lo tanto, los cambios
efectuados en el objeto mediante object3 se reflejarn en los usos posteriores de object4 . Dado que los objetos
basados en clases se tratan por referencia, las clases se denominan "tipos de referencia".
Herencia de clases
La herencia se consigue mediante una derivacin, en la que se declara una clase mediante una clase base, desde la
que hereda los datos y el comportamiento. Una clase base se especifica anexando dos puntos y el nombre de la
clase base seguido del nombre de la clase derivada, como en el siguiente ejemplo:
Cuando una clase declara una clase base, hereda todos los miembros de la clase base excepto los constructores.
A diferencia de C++, una clase de C# solo puede heredar directamente de una clase base. En cambio, dado que
una clase base puede heredar de otra clase, una clase podra heredar indirectamente varias clases base. Adems,
una clase puede implementar directamente ms de una interfaz. Para obtener ms informacin, vea Interfaces.
Una clase puede declararse abstracta. Una clase abstracta contiene mtodos abstractos que tienen una definicin
de firma, pero no tienen ninguna implementacin. No se pueden crear instancias de las clases abstractas. Solo se
pueden usar a travs de las clases derivadas que implementan los mtodos abstractos. Por el contrario, la clase
sealed no permite que otras clases se deriven de ella. Para ms informacin, vea Clases y miembros de clase
abstractos y sellados.
Las definiciones de clase se pueden dividir entre distintos archivos de cdigo fuente. Para obtener ms
informacin, consulte Clases y mtodos parciales.
Descripcin
En el ejemplo siguiente se define una clase pblica que contiene un solo campo, un mtodo y un mtodo especial
denominado "constructor". Para obtener ms informacin, vea Constructores. Luego, se crea una instancia de la
clase con la palabra clave new .
Ejemplo
public class Person
{
// Field
public string name;
// Method
public void SetName(string newName)
{
name = newName;
}
}
class TestPerson
{
static void Main()
{
// Call the constructor that has no parameters.
Person person1 = new Person();
Console.WriteLine(person1.name);
person1.SetName("John Smith");
Console.WriteLine(person1.name);
Vea tambin
Gua de programacin de C#
Object-Oriented Programming (Programacin orientada a objetos)
Polimorfismo
Miembros
Mtodos
Constructors (Constructores [Gua de programacin de C#])
Finalizadores
Objects
Objetos (Gua de programacin de C#)
03/10/2017 5 min to read Edit Online
Una definicin de clase o estructura es como un plano que especifica qu puede hacer el tipo. Un objeto es
bsicamente un bloque de memoria que se ha asignado y configurado de acuerdo con el plano. Un programa
puede crear muchos objetos de la misma clase. Los objetos tambin se denominan instancias y pueden
almacenarse en una variable con nombre, o en una matriz o coleccin. El cdigo de cliente es el cdigo que usa
estas variables para llamar a los mtodos y acceder a las propiedades pblicas del objeto. En un lenguaje orientado
a objetos, como C#, un programa tpico consta de varios objetos que interactan dinmicamente.
NOTA
Los tipos estticos se comportan de forma diferente a lo que se describe aqu. Para obtener ms informacin, consulte Clases
estticas y sus miembros.
class Program
{
static void Main()
{
Person person1 = new Person("Leopold", 6);
Console.WriteLine("person1 Name = {0} Age = {1}", person1.Name, person1.Age);
}
}
/*
Output:
person1 Name = Leopold Age = 6
person2 Name = Molly Age = 16
person1 Name = Molly Age = 16
*/
Dado que las estructuras son tipos de valor, una variable de un objeto de estructura contiene una copia de todo el
objeto. Tambin se pueden crear instancias de estructuras usando el operador new , pero esto no resulta necesario,
como se muestra en el ejemplo siguiente:
public struct Person
{
public string Name;
public int Age;
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
La memoria para p1 y p2 se asigna en la pila de subprocesos. Esta memoria se reclama junto con el tipo o
mtodo en el que se declara. Este es uno de los motivos por los que se copian las estructuras en la asignacin. Por
el contrario, la memoria que se asigna a una instancia de clase la reclama automticamente (recoleccin de
elementos no utilizados) Common Language Runtime cuando todas las referencias al objeto se han salido del
mbito. No es posible destruir de forma determinante un objeto de clase como en C++. Para obtener ms
informacin sobre la recoleccin de elementos no utilizados en .NET Framework, consulte Recoleccin de
elementos no utilizados.
NOTA
La asignacin y desasignacin de memoria en el montn administrado estn muy optimizadas en Common Language
Runtime. En la mayora de los casos, no existe ninguna diferencia significativa en el costo de rendimiento entre asignar una
instancia de clase en el montn y asignar una instancia de estructura en la pila.
if (p2.Equals(p1))
Console.WriteLine("p2 and p1 have the same values.");
La implementacin System.ValueType de Equals usa la reflexin porque debe poder determinar cules son los
campos en cualquier estructura. Al crear sus propias estructuras, invalide el mtodo Equals para proporcionar un
algoritmo de igualdad eficaz especfico de su tipo.
Para determinar si los valores de los campos de dos instancias de clase son iguales, puede usar el mtodo
Equals o el operador ==. En cambio, selos solo si la clase los ha invalidado o sobrecargado para proporcionar
una definicin personalizada de lo que significa "igualdad" para los objetos de ese tipo. La clase tambin puede
implementar la interfaz IEquatable<T> o la interfaz IEqualityComparer<T>. Ambas interfaces proporcionan
mtodos que pueden servir para comprobar la igualdad de valores. Al disear sus propias clases que invaliden
Equals , asegrese de seguir las instrucciones descritas en Cmo: Definir la igualdad de valores para un tipo y
Object.Equals(Object).
Secciones relacionadas
Para obtener ms informacin:
Clases
Estructuras
Constructores
Finalizadores
Eventos
Vea tambin
Gua de programacin de C#
object
Herencia
class
struct
new (Operador, Referencia de C#)
Sistema de tipos comunes
Structs (Gua de programacin de C#)
03/10/2017 1 min to read Edit Online
Los structs comparten la mayora de la sintaxis con las clases, aunque estn ms limitados que estas:
Dentro de una declaracin de struct, los campos no se pueden inicializar a menos que se declaren como
constantes o estticos.
Un struct no puede declarar un constructor predeterminado (un constructor sin parmetros) ni un
finalizador.
Los structs se copian en la asignacin. Cuando se asigna un struct a una variable nueva, se copian todos los
datos y las modificaciones que se realicen en la nueva copia no cambiarn los datos de la copia original. Es
importante que lo recuerde al trabajar con colecciones de tipos de valor como Dictionary<string,
myStruct>.
Los structs son tipos de valor y las clases son tipos de referencia.
A diferencia de las clases, se pueden crear instancias de structs sin usar un operador new .
Los structs pueden declarar constructores que tengan parmetros.
As, un struct no puede heredar de otra clase o de otro struct, como tampoco puede ser la base de una clase.
Todos los structs heredan directamente de System.ValueType , que hereda de System.Object .
Un struct puede implementar interfaces.
Un struct se puede usar como un tipo que acepta valores NULL y se le puede asignar un valor NULL.
Secciones relacionadas
Para obtener ms informacin:
Utilizar estructuras
Constructores
Tipos que aceptan valores NULL
Cmo: Saber las diferencias entre pasar a un mtodo un struct y una referencia a clase
Cmo: Implementar conversiones definidas por el usuario entre structs
Vea tambin
Gua de programacin de C#
Clases y estructuras
Clases
Utilizar estructuras (Gua de programacin de C#)
03/10/2017 3 min to read Edit Online
El tipo struct resulta adecuado para representar objetos pequeos como Point , Rectangle y Color . Aunque es
igual de vlido representar un punto como un elemento class con Propiedades autoimplementadas, seguramente
un struct sea ms eficaz en algunos escenarios. Por ejemplo, si declara una matriz de 1000 objetos Point , se
asignar ms memoria para hacer referencia a cada objeto y, en este caso, un struct sera menos costoso. Como
.NET Framework contiene un objeto denominado Point, denominaremos el struct de este ejemplo "CoOrds".
Definir un constructor (sin parmetros) predeterminado para un struct es un error, como tambin lo es inicializar
un campo de instancia en el cuerpo de un struct. Los miembros del struct solo se pueden inicializar mediante un
constructor con parmetros, o bien teniendo acceso individualmente a cada miembro una vez declarado el struct.
Los miembros privados o inaccesibles por cualquier otro motivo solo se pueden inicializar en un constructor.
Cuando se crea un objeto de struct mediante el operador new , el objeto se crea y se llama al constructor
apropiado. A diferencia de las clases, se pueden crear instancias de structs sin usar el operador new . En tal caso,
no hay ninguna llamada de constructor, con lo cual la asignacin es ms eficaz. Pero los campos seguirn sin
asignar y el objeto no se podr usar hasta que todos los campos se inicialicen.
Cuando un struct contiene un tipo de referencia como miembro, se debe invocar explcitamente el constructor
predeterminado de ese miembro, ya que, de lo contrario, el miembro seguir sin asignar y el struct no se podr
usar (esto genera el error del compilador CS0171).
En los structs no existe el concepto de herencia que s hay en las clases. As, un struct no puede heredar de otra
clase o de otro struct, como tampoco puede ser la base de una clase. Pero los structs s heredan de la clase base
Object. Un struct puede implementar interfaces y lo hace exactamente igual que las clases.
No se puede declarar una clase mediante la palabra clave struct . En C#, las clases y los structs son distintos
semnticamente. Un struct es un tipo de valor, mientras que una clase es un tipo de referencia. Para obtener ms
informacin, vea Tipos de valor.
A menos que necesite una semntica de tipo de referencia, es probable que el sistema controle una clase pequea
ms eficazmente si se declara como un struct.
Ejemplo 1
Descripcin
En este ejemplo se muestra la inicializacin de struct mediante constructores predeterminados y constructores
con parmetros.
Cdigo
public struct CoOrds
{
public int x, y;
// Display results:
Console.Write("CoOrds 1: ");
Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);
Console.Write("CoOrds 2: ");
Console.WriteLine("x = {0}, y = {1}", coords2.x, coords2.y);
Ejemplo 2
Descripcin
En este ejemplo se muestra una caracterstica nica de los structs. Se crea un objeto CoOrds sin usar el operador
new . Si reemplaza la palabra struct por la palabra class , el programa no se compilar.
Cdigo
// Initialize:
coords1.x = 10;
coords1.y = 20;
// Display results:
Console.Write("CoOrds 1: ");
Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);
Vea tambin
Gua de programacin de C#
Clases y estructuras
Structs
Herencia (Gua de programacin de C#)
03/10/2017 7 min to read Edit Online
La herencia, junto con la encapsulacin y el polimorfismo, es una de las tres caractersticas principales de la
programacin orientada a objetos. La herencia permite crear clases nuevas que reutilizan, extienden y modifican
el comportamiento que se define en otras clases. La clase cuyos miembros se heredan se denomina clase base y
la clase que hereda esos miembros se denomina clase derivada. Una clase derivada solo puede tener una clase
base directa, pero la herencia es transitiva. Si ClaseC se deriva de ClaseB y ClaseB se deriva de ClaseA, ClaseC
hereda los miembros declarados en ClaseB y ClaseA.
NOTA
Los structs no admiten la herencia, pero pueden implementar interfaces. Para obtener ms informacin, vea Interfaces.
Conceptualmente, una clase derivada es una especializacin de la clase base. Por ejemplo, si tiene una clase base
Animal , podra tener una clase derivada denominada Mammal y otra clase derivada denominada Reptile .
Mammal es Animal y Reptile tambin es Animal , pero cada clase derivada representa especializaciones
diferentes de la clase base.
Cuando se define una clase para que derive de otra clase, la clase derivada obtiene implcitamente todos los
miembros de la clase base, salvo sus constructores y sus finalizadores. La clase derivada puede reutilizar el cdigo
de la clase base sin tener que volver a implementarlo. Puede agregar ms miembros en la clase derivada. De esta
manera, la clase derivada ampla la funcionalidad de la clase base.
En la ilustracin siguiente se muestra una clase WorkItem que representa un elemento de trabajo de un proceso
empresarial. Como con todas las clases, se deriva de System.Object y hereda todos sus mtodos. WorkItem
agrega cinco miembros propios. Entre estos se incluye un constructor, dado que los constructores no se heredan.
La clase ChangeRequest hereda de WorkItem y representa un tipo concreto de elemento de trabajo. ChangeRequest
agrega dos miembros ms a los miembros que hereda de WorkItem y de Object. Debe agregar su propio
constructor y adems agrega originalItemID . La propiedad originalItemID permite que la instancia
ChangeRequest se asocie con el WorkItem original al que se aplica la solicitud de cambio.
Herencia de clases
En el ejemplo siguiente se muestra cmo se expresan en C# las relaciones de clase de la ilustracin anterior. En el
ejemplo tambin se muestra cmo WorkItem reemplaza el mtodo virtual Object.ToString y cmo la clase
ChangeRequest hereda la implementacin WorkItem del mtodo.
// WorkItem implicitly inherits from the Object class.
public class WorkItem
{
// Static field currentID stores the job ID of the last WorkItem that
// has been created.
private static int currentID;
//Properties.
protected int ID { get; set; }
protected string Title { get; set; }
protected string Description { get; set; }
protected TimeSpan jobLength { get; set; }
// Method Update enables you to update the title and job length of an
// existing WorkItem object.
public void Update(string title, TimeSpan joblen)
{
this.Title = title;
this.jobLength = joblen;
}
class Program
{
static void Main()
{
// Create an instance of WorkItem by using the constructor in the
// base class that takes three arguments.
WorkItem item = new WorkItem("Fix Bugs",
"Fix all bugs in my code branch",
new TimeSpan(3, 4, 0, 0));
Interfaces
Una interfaz es un tipo de referencia similar a una clase base abstracta formada nicamente por miembros
abstractos. Cuando una clase implementa una interfaz, debe proporcionar una implementacin para todos los
miembros de la interfaz. Una clase puede implementar varias interfaces, aunque solo puede derivar de una nica
clase base directa.
Las interfaces se usan para definir funciones especficas para clases que no tienen necesariamente una relacin
"es un/una". Por ejemplo, la interfaz System.IEquatable<T> se puede implementar mediante cualquier clase o
struct que deba permitir que el cdigo de cliente determine si dos objetos del tipo son equivalentes (pero el tipo
define la equivalencia). IEquatable<T> no implica el mismo tipo de relacin "es un/una" que existe entre una clase
base y una clase derivada (por ejemplo, Mammal es Animal ). Para ms informacin, vea Interfaces.
Vea tambin
Gua de programacin de C#
Clases y structs
class
struct
Polimorfismo (Gua de programacin de C#)
03/10/2017 8 min to read Edit Online
using System;
using System.Collections.Generic;
// Virtual method
public virtual void Draw()
{
Console.WriteLine("Performing base class drawing tasks");
}
}
class Program
{
static void Main(string[] args)
{
// Polymorphism at work #1: a Rectangle, Triangle and Circle
// can all be used whereever a Shape is expected. No cast is
// required because an implicit conversion exists from a derived
// class to its base class.
var shapes = new List<Shape>
{
new Rectangle(),
new Triangle(),
new Circle()
};
/* Output:
Drawing a rectangle
Performing base class drawing tasks
Drawing a triangle
Performing base class drawing tasks
Drawing a circle
Performing base class drawing tasks
*/
En C#, cada tipo es polimrfico porque todos los tipos, incluidos los definidos por el usuario, heredan de Object.
Introduccin al polimorfismo
Miembros virtuales
Cuando una clase derivada hereda de una clase base, obtiene todos los mtodos, campos, propiedades y eventos
de la clase base. El diseador de la clase derivada tiene las siguientes opciones:
Invalidar los miembros virtuales de la clase base.
Heredar el mtodo de la clase base ms prximo sin invalidarlo.
Definir una nueva implementacin no virtual de esos miembros que oculte las implementaciones de la clase
base.
Una clase derivada puede invalidar un miembro de la clase base si este se declara como virtual o abstracto. El
miembro derivado debe usar la palabra clave override para indicar explcitamente que el propsito del mtodo es
participar en una invocacin virtual. El siguiente fragmento de cdigo muestra un ejemplo:
Los campos no pueden ser virtuales; solo los mtodos, propiedades, eventos e indizadores pueden ser virtuales.
Cuando una clase derivada invalida un miembro virtual, se llama a ese miembro aunque se acceda a una instancia
de esa clase como una instancia de la clase base. El siguiente fragmento de cdigo muestra un ejemplo:
BaseClass A = (BaseClass)B;
A.DoWork(); // Also calls the new method.
Los mtodos y propiedades virtuales permiten a las clases derivadas extender una clase base sin necesidad de usar
la implementacin de clase base de un mtodo. Para obtener ms informacin, consulte Control de versiones con
las palabras clave Override y New. Una interfaz proporciona otra manera de definir un mtodo o conjunto de
mtodos cuya implementacin se deja a las clases derivadas. Para obtener ms informacin, vea Interfaces.
Ocultar miembros de clase base con nuevos miembros
Si quiere que el miembro derivado tenga el mismo nombre que un miembro de una clase base, pero no quiere
que participe en la invocacin virtual, puede usar la palabra clave new. La palabra clave new se coloca antes que el
tipo devuelto del miembro de la clase que se est reemplazando. El siguiente fragmento de cdigo muestra un
ejemplo:
public class BaseClass
{
public void DoWork() { WorkField++; }
public int WorkField;
public int WorkProperty
{
get { return 0; }
}
}
An se puede acceder a los miembros de la clase base ocultos desde el cdigo de cliente convirtiendo la instancia
de la clase derivada en una instancia de la clase base. Por ejemplo:
BaseClass A = (BaseClass)B;
A.DoWork(); // Calls the old method.
public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}
Una clase derivada puede detener la herencia virtual al declarar una invalidacin como sealed. Para ello, es
necesario colocar la palabra clave sealed antes de la palabra clave override en la declaracin del miembro de la
clase. El siguiente fragmento de cdigo muestra un ejemplo:
public class C : B
{
public sealed override void DoWork() { }
}
En el ejemplo anterior, el mtodo DoWork ya no es virtual para ninguna clase que derive de C. Sigue siendo virtual
para instancias de C, aunque se conviertan al tipo B o A. Los mtodos sellados pueden reemplazarse por las clases
derivadas al usar la palabra clave new , como se muestra en el ejemplo siguiente:
public class D : C
{
public new void DoWork() { }
}
En este caso, si se llama a DoWork en D usando una variable de tipo D, se llama al nuevo DoWork . Si se usa una
variable de tipo C, B o A para acceder a una instancia de D, la llamada a DoWork seguir las reglas de herencia
virtual y enrutar dichas llamadas a la implementacin de DoWork en la clase C.
Acceder a miembros virtuales de clases base desde clases derivadas
Una clase derivada que ha reemplazado o invalidado un mtodo o propiedad puede seguir accediendo al mtodo
o propiedad en la clase base usando la siguiente palabra clave base. El siguiente fragmento de cdigo muestra un
ejemplo:
NOTA
Se recomienda que las mquinas virtuales usen base para llamar a la implementacin de la clase base de ese miembro en
su propia implementacin. Dejar que se produzca el comportamiento de la clase base permite a la clase derivada
concentrarse en implementar el comportamiento especfico de la clase derivada. Si no se llama a la implementacin de la
clase base, depende de la clase derivada hacer que su comportamiento sea compatible con el de la clase base.
En esta seccin
Control de versiones con las palabras clave Override y New
Saber cundo utilizar las palabras clave Override y New
Cmo: Invalidar el mtodo ToString
Vea tambin
Gua de programacin de C#
Gua de programacin de C#
Herencia
Clases y miembros de clase abstractos y sellados
Mtodos
Eventos
Propiedades
Indexers (Indexadores)
Tipos
Control de versiones con las palabras clave Override
y New (Gua de programacin de C#)
03/10/2017 5 min to read Edit Online
El lenguaje C# est diseado para que las versiones entre clases base y derivadas de diferentes bibliotecas puedan
evolucionar y mantener la compatibilidad con versiones anteriores. Esto significa, por ejemplo, que la introduccin
de un nuevo miembro en una clase base con el mismo nombre que un miembro de una clase derivada es
totalmente compatible con C# y no lleva a un comportamiento inesperado. Adems, implica que una clase debe
declarar explcitamente si un mtodo est pensado para reemplazar un mtodo heredado o si se trata de un nuevo
mtodo que oculta un mtodo heredado de nombre similar.
En C#, las clases derivadas pueden contener mtodos con el mismo nombre que los mtodos de clase base.
El mtodo de clase base debe definirse como virtual.
Si el mtodo de la clase derivada no va precedido por las palabras clave new u override, el compilador
emite una advertencia y el mtodo se comporta como si la palabra clave new estuviese presente.
Si el mtodo de la clase derivada va precedido de la palabra clave new , el mtodo se define como
independiente del mtodo de la clase base.
Si el mtodo de la clase derivada va precedido de la palabra clave override , los objetos de la clase derivada
llamarn a ese mtodo y no al mtodo de la clase base.
El mtodo de clase base puede llamarse desde dentro de la clase derivada mediante la palabra clave base .
Las palabras clave override , virtual y new tambin pueden aplicarse a propiedades, indexadores y
eventos.
De forma predeterminada, los mtodos de C# no son virtuales. Si se declara un mtodo como virtual, toda clase
que hereda el mtodo puede implementar su propia versin Para que un mtodo sea virtual, se usa el modificador
virtual en la declaracin del mtodo de la clase base. La clase derivada puede luego reemplazar el mtodo base
virtual mediante la palabra clave override u ocultar el mtodo virtual en la clase base mediante la palabra clave
new . Si no se especifican las palabras clave override o new , el compilador emite una advertencia y el mtodo de
la clase derivada oculta el mtodo de la clase base.
Para demostrar esto en la prctica, supongamos por un momento que la compaa A ha creado una clase
denominada GraphicsClass , que su programa usa. La siguiente es GraphicsClass :
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
}
Su compaa usa esta clase y usted la usa para derivar su propia clase, agregando un nuevo mtodo:
class GraphicsClass
{
public virtual void DrawLine() { }
public virtual void DrawPoint() { }
public virtual void DrawRectangle() { }
}
Si quiere que su mtodo reemplace al nuevo mtodo de clase base, use la palabra clave override :
La palabra clave override se asegura de que los objetos derivados de YourDerivedGraphicsClass usen la versin
de la clase derivada de DrawRectangle . Los objetos derivados de YourDerivedGraphicsClass todava pueden
acceder a la versin de clase base DrawRectangle mediante la palabra clave base:
base.DrawRectangle();
Si no quiere que el mtodo reemplace al nuevo mtodo de clase base, se aplican las consideraciones siguientes.
Para evitar la confusin entre los dos mtodos, puede cambiarle el nombre a su mtodo. Esto puede ser un
proceso lento y propenso a errores y no resultar prctico en algunos casos. Pero si el proyecto es relativamente
pequeo, puede usar opciones de refactorizacin de Visual Studio para cambiar el nombre del mtodo. Para
obtener ms informacin, vea Refactoring Classes and Types (Class Designer) (Refactorizacin de clases y tipos
[Diseador de clases]).
Tambin puede evitar la advertencia mediante la palabra clave new en la definicin de clase derivada:
Con la palabra clave new se indica al compilador que su definicin oculta la definicin contenida en la clase base.
ste es el comportamiento predeterminado.
Cuando se llama a DoWork en una instancia de Derived , el compilador de C# intentar en primer lugar que la
llamada sea compatible con las versiones de DoWork declaradas originalmente en Derived . Los mtodos de
reemplazo no se consideran como declarados en una clase, son nuevas implementaciones de un mtodo que se
declara en una clase base. Solo si el compilador de C# no puede hacer coincidir la llamada al mtodo con un
mtodo original en Derived , intentar hacer coincidir la llamada con un mtodo reemplazado con el mismo
nombre y parmetros compatibles. Por ejemplo:
int val = 5;
Derived d = new Derived();
d.DoWork(val); // Calls DoWork(double).
Dado que la variable val se puede convertir implcitamente en un valor doble, el compilador de C# llama a
DoWork(double) en lugar de a DoWork(int) . Hay dos maneras de evitarlo. En primer lugar, evite declarar nuevos
mtodos con el mismo nombre que los mtodos virtuales. En segundo lugar, puede indicar al compilador de C#
que llame al mtodo virtual haciendo que busque la lista de mtodos de clase base mediante la conversin de la
instancia de Derived a Base . Como el mtodo es virtual, se llamar a la implementacin de DoWork(int) en
Derived . Por ejemplo:
Para obtener otros ejemplos de new y override , vea Knowing When to Use Override and New Keywords (Saber
cundo usar las palabras clave override y new [Gua de programacin de C#]).
Vea tambin
Gua de programacin de C#
Clases y estructuras
Methods (Mtodos [Gua de programacin de C#])
Herencia
Saber cundo utilizar las palabras clave Override y
New (Gua de programacin de C#)
03/10/2017 11 min to read Edit Online
En C#, un mtodo de una clase derivada puede tener el mismo nombre que un mtodo de la clase base. Se puede
especificar cmo interactan los mtodos mediante las palabras clave new y override. El modificador override
extiende el mtodo de clase base y el modificador new lo oculta. En los ejemplos de este tema se ilustra la
diferencia.
En una aplicacin de consola, declare las dos clases siguientes, BaseClass y DerivedClass . DerivedClass hereda
de BaseClass .
class BaseClass
{
public void Method1()
{
Console.WriteLine("Base - Method1");
}
}
bc.Method1();
dc.Method1();
dc.Method2();
bcdc.Method1();
}
// Output:
// Base - Method1
// Base - Method1
// Derived - Method2
// Base - Method1
}
Despus, agregue el mtodo Method2 siguiente a BaseClass . La firma de este mtodo coincide con la firma del
mtodo Method2 de DerivedClass .
Dado que BaseClass ahora tiene un mtodo Method2 , se puede agregar una segunda instruccin de llamada para
las variables de BaseClass bc y bcdc , como se muestra en el cdigo siguiente.
bc.Method1();
bc.Method2();
dc.Method1();
dc.Method2();
bcdc.Method1();
bcdc.Method2();
Al compilar el proyecto, ver que la adicin del mtodo Method2 de BaseClass genera una advertencia. La
advertencia indica que el mtodo Method2 de DerivedClass oculta el mtodo Method2 de BaseClass . Se
recomienda usar la palabra clave new en la definicin de Method2 si se pretende provocar ese resultado. Como
alternativa, se puede cambiar el nombre de uno de los mtodos Method2 para resolver la advertencia, pero eso no
siempre resulta prctico.
Antes de agregar new , ejecute el programa para ver el resultado producido por las instrucciones adicionales que
realizan la llamada. Se muestran los resultados siguientes.
// Output:
// Base - Method1
// Base - Method2
// Base - Method1
// Derived - Method2
// Base - Method1
// Base - Method2
La palabra clave new conserva las relaciones que generan ese resultado, pero se suprime la advertencia. Las
variables de tipo BaseClass siguen teniendo acceso a los miembros de BaseClass y la variable de tipo
DerivedClass sigue teniendo acceso a los miembros de DerivedClass en primer lugar y, despus, tiene en cuenta
los miembros heredados de BaseClass .
Para suprimir la advertencia, agregue el modificador new a la definicin de Method2 en DerivedClass , como se
muestra en el cdigo siguiente. Se puede agregar el modificador antes o despus de public .
Vuelva a ejecutar el programa para comprobar que el resultado no ha cambiado. Compruebe tambin que ya no
aparece la advertencia. Mediante el uso de new , afirma que es consciente de que el miembro que modifica oculta
un miembro heredado de la clase base. Para ms informacin sobre la ocultacin de nombres a travs de la
herencia, vea new (Modificador, Referencia de C#).
Para contrastar este comportamiento con los efectos de usar override , agregue el mtodo siguiente a
DerivedClass . Se puede agregar el modificador override antes o despus de public .
Vuelva a ejecutar el proyecto. Observe especialmente las dos ltimas lneas del resultado siguiente.
// Output:
// Base - Method1
// Base - Method2
// Derived - Method1
// Derived - Method2
// Derived - Method1
// Base - Method2
El uso del modificador override permite que bcdc tenga acceso al mtodo Method1 que se define en
DerivedClass . Normalmente, es el comportamiento deseado en jerarquas de herencia. La intencin es que los
objetos que tienen valores que se crean a partir de la clase derivada usen los mtodos que se definen en la clase
derivada. Ese comportamiento se consigue mediante el uso de override para extender el mtodo de clase base.
El cdigo siguiente contiene el ejemplo completo.
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
// Define the base class, Car. The class defines two methods,
// DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived
// class also defines a ShowDetails method. The example tests which version of
// ShowDetails is selected, the base class method or the derived class method.
class Car
{
public void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
ShowDetails();
}
El ejemplo comprueba la versin de ShowDetails que se llama. El siguiente mtodo, TestCars1 , declara una
instancia de cada clase y, despus, llama a DescribeCar en cada instancia.
public static void TestCars1()
{
System.Console.WriteLine("\nTestCars1");
System.Console.WriteLine("----------");
// Notice the output from this test case. The new modifier is
// used in the definition of ShowDetails in the ConvertibleCar
// class.
TestCars1 genera el siguiente resultado. Observe especialmente los resultados de car2 , que probablemente no
son los que se esperaban. El tipo de objeto es ConvertibleCar , pero DescribeCar no tiene acceso a la versin de
ShowDetails que se define en la clase ConvertibleCar porque ese mtodo se declara con el modificador new , no
con el modificador override . Como resultado, un objeto ConvertibleCar muestra la misma descripcin que un
objeto Car . Compare los resultados de car3 , que es un objeto Minivan . En este caso, el mtodo ShowDetails
que se declara en la clase Minivan invalida el mtodo ShowDetails que se declara en la clase Car , y en la
descripcin que se muestra se describe una furgoneta.
// TestCars1
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
TestCars2 crea una lista de objetos que tienen el tipo Car . Se crean instancias de los valores de los objetos desde
las clases Car , ConvertibleCar y Minivan . DescribeCar se llama en cada elemento de la lista. En el cdigo
siguiente se muestra la definicin de TestCars2 .
// TestCars2
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
Los mtodos TestCars3 y TestCars4 completan el ejemplo. Estos mtodos llaman directamente a ShowDetails ,
primero desde los objetos declarados con el tipo ConvertibleCar y Minivan ( TestCars3 ), y despus desde los
objetos declarados con el tipo Car ( TestCars4 ). En el cdigo siguiente se definen estos dos mtodos.
Los mtodos generan el siguiente resultado, que se corresponde a los resultados del primer ejemplo de este tema.
// TestCars3
// ----------
// A roof that opens up.
// Carries seven people.
// TestCars4
// ----------
// Standard transportation.
// Carries seven people.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideAndNew2
namespace OverrideAndNew2
{
class Program
{
static void Main(string[] args)
{
// Declare objects of the derived classes and test which version
// of ShowDetails is run, base or derived.
TestCars1();
// Notice the output from this test case. The new modifier is
// used in the definition of ShowDetails in the ConvertibleCar
// class.
ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
System.Console.WriteLine("----------");
// Define the base class, Car. The class defines two virtual methods,
// DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived
// class also defines a ShowDetails method. The example tests which version of
// ShowDetails is used, the base class method or the derived class method.
class Car
{
public virtual void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
ShowDetails();
}
Vea tambin
Gua de programacin de C#
Clases y estructuras
Control de versiones con las palabras clave Override y New
base
abstract
Cmo: Invalidar el mtodo ToString (Gua de
programacin de C#)
03/10/2017 1 min to read Edit Online
Cada clase o struct de C# hereda implcitamente la clase Object. Por consiguiente, cada objeto de C# obtiene el
mtodo ToString, que devuelve una representacin de cadena de ese objeto. Por ejemplo, todas las variables de
tipo int tienen un mtodo ToString , que las habilita para devolver su contenido como cadena:
int x = 42;
string strx = x.ToString();
Console.WriteLine(strx);
// Output:
// 42
Cuando cree una clase o struct personalizados, debe reemplazar el mtodo ToString para proporcionar
informacin sobre el tipo al cdigo de cliente.
Para obtener informacin sobre cmo usar cadenas de formato y otros tipos de formato personalizado con el
mtodo ToString , vea Aplicar formato a tipos.
IMPORTANTE
Cuando decida qu informacin va a proporcionar a travs de este mtodo, considere si la clase o struct se va a usar alguna
vez en cdigo que no sea de confianza. Asegrese de que no proporciona informacin que pueda ser aprovechada por
cdigo malintencionado.
class Person
{
public string Name { get; set; }
public int Age { get; set; }
Se puede probar el mtodo ToString tal y como se muestra en el siguiente ejemplo de cdigo:
Person person = new Person { Name = "John", Age = 12 };
Console.WriteLine(person);
// Output:
// Person: John 12
Vea tambin
IFormattable
Gua de programacin de C#
Clases y estructuras
Cadenas
string
new
override
virtual
Aplicacin de formato a tipos
Clases y miembros de clase abstractos y sellados
(Gua de programacin de C#)
03/10/2017 2 min to read Edit Online
La palabra clave abstract permite crear clases y miembros class que estn incompletos y se deben implementar
en una clase derivada.
La palabra clave sealed permite impedir la herencia de una clase o de ciertos miembros de clase marcados
previamente como virtual.
No se pueden crear instancias de una clase abstracta. El propsito de una clase abstracta es proporcionar una
definicin comn de una clase base que mltiples clases derivadas pueden compartir. Por ejemplo, una biblioteca
de clases puede definir una clase abstracta que se utiliza como parmetro para muchas de sus funciones y
solicitar a los programadores que utilizan esa biblioteca que proporcionen su propia implementacin de la clase
mediante la creacin de una clase derivada.
Las clases abstractas tambin pueden definir mtodos abstractos. Esto se consigue agregando la palabra clave
abstract antes del tipo de valor que devuelve el mtodo. Por ejemplo:
Los mtodos abstractos no tienen ninguna implementacin, de modo que la definicin de mtodo va seguida por
un punto y coma en lugar de un bloque de mtodo normal. Las clases derivadas de la clase abstracta deben
implementar todos los mtodos abstractos. Cuando una clase abstracta hereda un mtodo virtual de una clase
base, la clase abstracta puede reemplazar el mtodo virtual con un mtodo abstracto. Por ejemplo:
// compile with: /target:library
public class D
{
public virtual void DoWork(int i)
{
// Original implementation.
}
}
public class F : E
{
public override void DoWork(int i)
{
// New implementation.
}
}
Si un mtodo virtual se declara como abstract , sigue siendo virtual para cualquier clase que herede de la clase
abstracta. Una clase que hereda un mtodo abstracto no puede tener acceso a la implementacin original del
mtodo: en el ejemplo anterior, DoWork en la clase F no puede llamar a DoWork en la clase D. De esta manera, una
clase abstracta puede exigir a las clases derivadas que proporcionen nuevas implementaciones de mtodo para
los mtodos virtuales.
Una clase sellada no se puede utilizar como clase base. Por esta razn, tampoco puede ser una clase abstracta. Las
clases selladas evitan la derivacin. Puesto que nunca se pueden utilizar como clase base, algunas optimizaciones
en tiempo de ejecucin pueden hacer que sea un poco ms rpido llamar a miembros de clase sellada.
Un mtodo, indizador, propiedad o evento de una clase derivada que reemplaza a un miembro virtual de la clase
base puede declarar ese miembro como sellado. Esto niega el aspecto virtual del miembro para cualquier clase
derivada adicional. Esto se logra colocando la palabra clave sealed antes de la palabra clave override en la
declaracin del miembro de clase. Por ejemplo:
public class D : C
{
public sealed override void DoWork() { }
}
Vea tambin
Gua de programacin de C#
Clases y structs
Herencia
Mtodos
Campos
Cmo: Definir propiedades abstractas
Cmo: Definir propiedades abstractas (Gua de
programacin de C#)
03/10/2017 2 min to read Edit Online
En el ejemplo siguiente se muestra cmo definir las propiedades abstract. Una declaracin de propiedad abstracta
no proporciona una implementacin de los descriptores de acceso de propiedad, declara que la clase admite
propiedades, pero deja la implementacin del descriptor de acceso a las clases derivadas. En el ejemplo siguiente
se muestra cmo implementar las propiedades abstractas heredadas de una clase base.
Este ejemplo consta de tres archivos, cada uno de los cuales se compila individualmente y se hace referencia a su
ensamblado resultante mediante la siguiente compilacin:
abstractshape.cs: la clase Shape que contiene una propiedad Area abstracta.
shapes.cs: las subclases de la clase Shape .
shapetest.cs: un programa de prueba para mostrar las reas de algunos objetos derivados de Shape .
Para compilar el ejemplo, use el siguiente comando:
csc abstractshape.cs shapes.cs shapetest.cs
Ejemplo
Este archivo declara la clase Shape que contiene la propiedad Area del tipo double .
// compile with: csc /target:library abstractshape.cs
public abstract class Shape
{
private string name;
public Shape(string s)
{
// calling the set accessor of the Id property.
Id = s;
}
public string Id
{
get
{
return name;
}
set
{
name = value;
}
}
Al declarar una propiedad abstracta (como Area en este ejemplo), simplemente indica qu descriptores de
acceso de propiedad estn disponibles, pero no los implementa. En este ejemplo, solo est disponible un
descriptor de acceso get, por lo que la propiedad es de solo lectura.
Ejemplo
En el siguiente cdigo se muestran tres subclases de Shape y cmo invalidan la propiedad Area para
proporcionar su propia implementacin.
// compile with: csc /target:library /reference:abstractshape.dll shapes.cs
public class Square : Shape
{
private int side;
Ejemplo
En el siguiente cdigo se muestra un programa de prueba que crea un nmero de objetos derivados de Shape e
imprime sus reas.
System.Console.WriteLine("Shapes Collection");
foreach (Shape s in shapes)
{
System.Console.WriteLine(s);
}
}
}
/* Output:
Shapes Collection
Square #1 Area = 25.00
Circle #1 Area = 28.27
Rectangle #1 Area = 20.00
*/
Vea tambin
Gua de programacin de C#
Clases y structs
Clases y miembros de clase abstractos y sellados
Propiedades
Crear y utilizar ensamblados mediante la lnea de comandos
Clases estticas y sus miembros (Gua de
programacin de C#)
03/10/2017 6 min to read Edit Online
Una clase esttica es bsicamente lo mismo que una clase no esttica, con la diferencia de que no se pueden crear
instancias de una clase esttica. En otras palabras, no puede usar la palabra clave new para crear una variable del
tipo de clase. Dado que no hay ninguna variable de instancia, para tener acceso a los miembros de una clase
esttica, debe usar el nombre de la clase. Por ejemplo, si tiene una clase esttica denominada UtilityClass que
tiene un mtodo pblico denominado MethodA , llame al mtodo tal como se muestra en el ejemplo siguiente:
UtilityClass.MethodA();
Es posible usar una clase esttica como un contenedor adecuado para conjuntos de mtodos que solo funcionan
en parmetros de entrada y que no tienen que obtener ni establecer campos de instancias internas. Por ejemplo,
en la biblioteca de clases .NET Framework, la clase esttica System.Math contiene mtodos que realizan
operaciones matemticas, sin ningn requisito para almacenar o recuperar datos que sean nicos de una
instancia concreta de la clase Math. Es decir, para aplicar los miembros de la clase, debe especificar el nombre de
clase y el nombre de mtodo, como se muestra en el ejemplo siguiente.
// Output:
// 3.14
// -4
// 3
Como sucede con todos los tipos de clase, Common Language Runtime (CLR) de .NET Framework carga la
informacin de tipo para una clase esttica cuando se carga el programa que hace referencia a la clase. El
programa no puede especificar exactamente cundo se carga la clase, pero existe la garanta de que se cargar, de
que sus campos se inicializarn y de que se llamar a su constructor esttico antes de que se haga referencia a la
clase por primera vez en el programa. Solo se llama una vez a un constructor esttico, y una clase esttica
permanece en memoria durante la vigencia del dominio de aplicacin en el que reside el programa.
NOTA
Para crear una clase no esttica que solo permita la creacin de una instancia de s misma, vea Implementing Singleton in
C# (Implementar un singleton en C#).
Ejemplo
A continuacin se muestra un ejemplo de una clase esttica que contiene dos mtodos que convierten la
temperatura de grados Celsius a grados Fahrenheit y viceversa:
return fahrenheit;
}
return celsius;
}
}
class TestTemperatureConverter
{
static void Main()
{
Console.WriteLine("Please select the convertor direction");
Console.WriteLine("1. From Celsius to Fahrenheit.");
Console.WriteLine("2. From Fahrenheit to Celsius.");
Console.Write(":");
switch (selection)
{
case "1":
Console.Write("Please enter the Celsius temperature: ");
F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine());
Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
break;
case "2":
Console.Write("Please enter the Fahrenheit temperature: ");
C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine());
Console.WriteLine("Temperature in Celsius: {0:F2}", C);
Console.WriteLine("Temperature in Celsius: {0:F2}", C);
break;
default:
Console.WriteLine("Please select a convertor.");
break;
}
Miembros estticos
Una clase no esttica puede contener mtodos, campos, propiedades o eventos estticos. El miembro esttico es
invocable en una clase, incluso si no se ha creado ninguna instancia de la clase. Siempre se tiene acceso al
miembro esttico con el nombre de clase, no con el nombre de instancia. Solo existe una copia de un miembro
esttico, independientemente del nmero de instancias de la clase que se creen. Los mtodos y las propiedades
estticos no pueden tener acceso a campos y eventos no estticos en su tipo contenedor, y tampoco pueden tener
acceso a una variable de instancia de un objeto a menos que se pase explcitamente en un parmetro de mtodo.
Es ms habitual declarar una clase no esttica con algunos miembros estticos que declarar toda una clase como
esttica. Dos usos habituales de los campos estticos son llevar la cuenta del nmero de objetos de los que se han
creado instancias y almacenar un valor que se debe compartir entre todas las instancias.
Los mtodos estticos se pueden sobrecargar pero no invalidar, ya que pertenecen a la clase y no a una instancia
de la clase.
Aunque un campo no se puede declarar como static const , el campo const es bsicamente esttico en su
comportamiento. Pertenece al tipo, no a las instancias del tipo. Por lo tanto, se puede tener acceso a campos const
mediante la misma notacin ClassName.MemberName que se usa para los campos estticos. No se requiere ninguna
instancia de objeto.
C# no admite variables locales estticas (variables que se declaran en el mbito del mtodo).
Para declarar miembros de clases estticas, use la palabra clave static antes del tipo de valor devuelto del
miembro, como se muestra en el ejemplo siguiente:
public class Automobile
{
public static int NumberOfWheels = 4;
public static int SizeOfGasTank
{
get
{
return 15;
}
}
public static void Drive() { }
public static event EventType RunOutOfGas;
Los miembros estticos se inicializan antes de que se obtenga acceso por primera vez al miembro esttico y antes
de que se llame al constructor esttico, en caso de haberlo. Para tener acceso a un miembro de clase esttica, use
el nombre de la clase en lugar de un nombre de variable para especificar la ubicacin del miembro, como se
muestra en el ejemplo siguiente:
Automobile.Drive();
int i = Automobile.NumberOfWheels;
Si la clase contiene campos estticos, proporcione un constructor esttico que los inicialice al cargar la clase.
Una llamada a un mtodo esttico genera una instruccin de llamada en Lenguaje Intermedio de Microsoft
(MSIL), mientras que una llamada a un mtodo de instancia genera una instruccin callvirt , que tambin
comprueba si hay referencias a un objeto NULL, pero la mayora de las veces la diferencia de rendimiento entre
las dos no es significativo.
Vea tambin
Gua de programacin de C#
static
Clases
class
Constructores estticos
Constructores de instancias
Miembros (Gua de programacin de C#)
03/10/2017 2 min to read Edit Online
Las clases y structs tienen miembros que representan sus datos y comportamiento. Los miembros de una clase
incluyen todos los miembros declarados en la clase, junto con todos los miembros (excepto constructores y
finalizadores) declarados en todas las clases de su jerarqua de herencia. Los miembros privados de clases base se
heredan en las clases derivadas, pero estas no pueden tener acceso a ellos.
En la tabla siguiente se enumeran los tipos de miembros que puede contener una clase o struct:
MIEMBRO DESCRIPCIN
Mtodos Los mtodos definen las acciones que una clase puede realizar.
Los mtodos pueden aceptar parmetros que proporcionan
datos de entrada y devolver datos de salida a travs de
parmetros. Los mtodos tambin pueden devolver un valor
directamente, sin usar ningn parmetro.
Tipos anidados Los tipos anidados son tipos declarados dentro de otro tipo.
Los tipos anidados se usan a menudo para describir objetos
utilizados nicamente por los tipos que los contienen.
Vea tambin
Gua de programacin de C#
Clases
Mtodos
Constructors (Constructores [Gua de programacin de C#])
Finalizadores
Propiedades
Campos
Indexers (Indexadores)
Eventos
Tipos anidados
Operadores
Operadores sobrecargables
Modificadores de acceso (Gua de programacin de
C#)
03/10/2017 4 min to read Edit Online
Todos los tipos y miembros de tipo tienen un nivel de accesibilidad que controla si se pueden usar desde otro
cdigo del ensamblado u otros ensamblados. Puede usar los siguientes modificadores de acceso para especificar
la accesibilidad de un tipo o miembro cuando lo declare:
public
Puede obtener acceso al tipo o miembro cualquier otro cdigo del mismo ensamblado o de otro ensamblado que
haga referencia a ste.
private
Solamente el cdigo de la misma clase o estructura puede acceder al tipo o miembro.
protected
Solamente el cdigo de la misma clase o estructura, o de una clase derivada de esa clase, puede acceder al tipo o
miembro.
internal
Puede obtener acceso al tipo o miembro cualquier cdigo del mismo ensamblado, pero no de un ensamblado
distinto.
protected internal
Cualquier cdigo del ensamblado en el que se ha declarado, o desde cualquier clase derivada de otro ensamblado,
puede acceder al tipo o miembro. El acceso desde otro ensamblado debe producirse en una declaracin de clase
que derive de la clase en la que se haya declarado el elemento interno protegido y se debe realizar mediante una
instancia del tipo de clase derivada.
En los ejemplos siguientes se muestra cmo especificar modificadores de acceso en un tipo y miembro:
No todos los tipos o miembros pueden usar todos los modificadores de acceso en todos los contextos; en algunos
casos la accesibilidad de un miembro de tipo est restringida por la accesibilidad de su tipo contenedor. En las
secciones siguientes se proporcionan ms detalles sobre la accesibilidad.
// public class:
public class Tricycle
{
// protected method:
protected void Pedal() { }
// private field:
private int wheels = 3;
NOTA
El nivel de accesibilidad protected internal significa protected O internal, no protected E internal. Es decir, se puede acceder a
un miembro protegido interno desde cualquier clase del mismo ensamblado, incluidas las clases derivadas. Para limitar la
accesibilidad a las clases derivadas del mismo ensamblado, declare la propia clase como internal y sus miembros como
protected.
Otros tipos
Las interfaces declaradas directamente en un espacio de nombres se pueden declarar como public o internal y, al
igual que las clases y las estructuras, su valor predeterminado es el acceso interno. Los miembros de interfaz son
siempre pblicos porque el propsito de una interfaz es permitir que otros tipos accedan a una clase o estructura.
A los miembros de interfaz no se les puede aplicar ningn modificador de acceso.
Los miembros de enumeracin siempre son pblicos y no se les puede aplicar ningn modificador de acceso.
Los delegados se comportan como las clases y las estructuras. De forma predeterminada, tienen acceso interno
cuando se declaran directamente en un espacio de nombres y acceso privado cuando estn anidados.
Vea tambin
Gua de programacin de C#
Clases y structs
Interfaces
private
public
internal
protected
class
struct
interface
Campos (Gua de programacin de C#)
03/10/2017 4 min to read Edit Online
Un campo es una variable de cualquier tipo que se declara directamente en una clase o struct. Los campos son
miembros de su tipo contenedor.
Una clase o struct puede tener campos de instancia o campos estticos, o ambos. Los campos de instancia son
especficos de una instancia de un tipo. Si tiene una clase T, con un campo de instancia F, puede crear dos objetos
de tipo T y modificar el valor de F en cada objeto sin afectar el valor del otro objeto. Por el contrario, un campo
esttico pertenece a la propia clase y se comparte entre todas las instancias de esa clase. Los cambios realizados
desde la instancia A sern visibles inmediatamente para las instancias B y C, si tienen acceso al campo.
Por lo general, solo se deben usar campos para las variables que tienen accesibilidad privada o protegida. Los
datos que la clase expone al cdigo de cliente deben proporcionarse a travs de mtodos, propiedades e
indizadores. Mediante estas construcciones para el acceso indirecto a los campos internos, se puede proteger de
los valores de entrada no vlidos. Un campo privado que almacena los datos expuestos por una propiedad pblica
se denomina memoria auxiliar o campo de respaldo.
Los campos almacenan habitualmente los datos que deben ser accesibles para ms de un mtodo de clase y que
deben almacenarse durante ms tiempo de lo que dura un nico mtodo. Por ejemplo, es posible que una clase
que representa una fecha de calendario tenga tres campos enteros: uno para el mes, otro para el da y otro para el
ao. Las variables que no se usan fuera del mbito de un nico mtodo se deben declarar como variables locales
dentro del mtodo del propio cuerpo.
Los campos se declaran en el bloque de clase especificando el nivel de acceso del campo, seguido por el tipo del
campo, seguido por el nombre del campo. Por ejemplo:
public class CalendarEntry
{
// private field
private DateTime date;
}
}
Para obtener acceso a un campo en un objeto, agregue un punto despus del nombre de objeto, seguido del
nombre del campo, como en objectname.fieldname . Por ejemplo:
Se puede proporcionar un valor inicial a un campo mediante el operador de asignacin cuando se declara el
campo. Para asignar automticamente el campo day a "Monday" , por ejemplo, se declarara day como en el
ejemplo siguiente:
Los campos se inicializan inmediatamente antes de que se llame al constructor para la instancia del objeto. Si el
constructor asigna el valor de un campo, sobrescribir cualquier valor dado durante la declaracin del campo. Para
obtener ms informacin, vea Using Constructors (Uso de constructores).
NOTA
Un inicializador de campo no puede hacer referencia a otros campos de instancia.
Los campos se pueden marcar como public, private, protected, internal o protected internal . Estos modificadores
de acceso definen cmo los usuarios de la clase pueden obtener acceso a los campos. Para obtener ms
informacin, vea Modificadores de acceso.
Opcionalmente, un campo se puede declarar como static. Esto hace que el campo est disponible para los
llamadores en cualquier momento, aunque no exista ninguna instancia de la clase. Para obtener ms informacin,
vea Clases estticas y sus miembros.
Se puede declarar un campo como readonly. Solamente se puede asignar un valor a un campo de solo lectura
durante la inicializacin o en un constructor. Un campo static``readonly es muy similar a una constante, salvo
que el compilador de C# no tiene acceso al valor de un campo esttico de solo lectura en tiempo de compilacin,
solo en tiempo de ejecucin. Para obtener ms informacin, vea Constants (Constantes).
Vea tambin
Gua de programacin de C#
Clases y structs
Uso de constructores
Herencia
Modificadores de acceso
Clases y miembros de clase abstractos y sellados
Constantes (Gua de programacin de C#)
03/10/2017 2 min to read Edit Online
Las constantes son valores inmutables que se conocen en tiempo de compilacin y que no cambian durante la vida
del programa. Las constantes se declaran con el modificador const. Solo los tipos integrados de C# (excluido
System.Object) pueden declararse como const . Para obtener una lista de los tipos integrados, vea Tabla de tipos
integrados. Los tipos definidos por el usuario, incluidas las clases, las estructuras y las matrices, no pueden ser
const . Use el modificador readonly para crear una clase, una estructura o una matriz que se inicialice una vez en
tiempo de ejecucin (por ejemplo, en un constructor) y que posteriormente no se pueda cambiar.
C# no admite mtodos, propiedades ni eventos const .
El tipo enum permite definir constantes con nombre para los tipos integrados enteros (por ejemplo, int , uint ,
long , etc.). Para ms informacin, vea enum.
class Calendar1
{
public const int months = 12;
}
En este ejemplo la constante months siempre es 12 y ni siquiera la propia clase la puede cambiar. De hecho,
cuando el compilador detecta un identificador de constante en el cdigo fuente de C# (por ejemplo, months ),
sustituye directamente el valor literal en el cdigo de lenguaje intermedio (IL) que genera. Dado que no hay
ninguna direccin de variable asociada a una constante en tiempo de ejecucin, no se pueden pasar los campos
const por referencia ni pueden aparecer como un valor L en una expresin.
NOTA
Tenga cuidado al hacer referencia a valores de constante definidos en otro cdigo como archivos DLL. Si una nueva versin
del archivo DLL define un nuevo valor para la constante, el programa conservar el valor literal anterior hasta que se vuelva a
compilar con la versin nueva.
Se pueden declarar varias constantes del mismo tipo a la vez, por ejemplo:
class Calendar2
{
const int months = 12, weeks = 52, days = 365;
}
La expresin que se usa para inicializar una constante puede hacer referencia a otra constante si no crea una
referencia circular. Por ejemplo:
class Calendar3
{
const int months = 12;
const int weeks = 52;
const int days = 365;
Las constantes se pueden marcar como public, private, protected, internal o protected internal . Estos
modificadores de acceso definen cmo los usuarios de la clase pueden acceder a la constante. Para ms
informacin, vea Modificadores de acceso.
A las constantes se accede como si fueran campos estticos porque el valor de la constante es el mismo para todas
las instancias del tipo. No use la palabra clave static para declararlas. Las expresiones que no estn en la clase
que define la constante deben usar el nombre de la clase, un punto y el nombre de la constante para acceder a ella.
Por ejemplo:
Vea tambin
Gua de programacin de C#
Clases y structs
Propiedades
Tipos
readonly
Immutability in C# Part One: Kinds of Immutability (Inmutabilidad en C# (primera parte): tipos de inmutabilidad)
Cmo: Definir constantes en C#
03/10/2017 1 min to read Edit Online
Las constantes son campos cuyos valores se establecen en tiempo de compilacin y nunca se pueden cambiar. Use
constantes para proporcionar nombres descriptivos en lugar de literales numricos ("nmeros mgicos") para
valores especiales.
NOTA
En C#, la directiva del preprocesador #define no puede usarse para definir constantes en la manera que se usa normalmente
en C y C++.
Para definir valores constantes de tipos enteros ( int , byte y as sucesivamente) use un tipo enumerado. Para
ms informacin, vea enum.
Para definir constantes no enteras, un enfoque es agruparlas en una nica clase esttica denominada Constants .
Esto necesitar que todas las referencias a las constantes vayan precedidas por el nombre de clase, como se
muestra en el ejemplo siguiente.
Ejemplo
static class Constants
{
public const double Pi = 3.14159;
public const int SpeedOfLight = 300000; // km per sec.
}
class Program
{
static void Main()
{
double radius = 5.3;
double area = Constants.Pi * (radius * radius);
int secsFromSun = 149476000 / Constants.SpeedOfLight; // in km
}
}
El uso del calificador de nombre de clase ayuda a garantizar que usted y otros usuarios que usan la constante
comprenden que es una constante y que no puede modificarse.
Vea tambin
Clases y structs
Propiedades (Gua de programacin de C#)
03/10/2017 5 min to read Edit Online
Una propiedad es un miembro que proporciona un mecanismo flexible para leer, escribir o calcular el valor de
un campo privado. Las propiedades se pueden usar como si fueran miembros de datos pblicos, pero en
realidad son mtodos especiales denominados descriptores de acceso. Esto permite acceder fcilmente a los
datos a la vez que proporciona la seguridad y la flexibilidad de los mtodos.
class TimePeriod
{
private double seconds;
class Program
{
static void Main()
{
TimePeriod t = new TimePeriod();
// The property assignment causes the 'set' accessor to be called.
t.Hours = 24;
A partir de C# 7, los descriptores de acceso get y set se pueden implementar como miembros con forma de
expresin. En este caso, las palabras clave get y set deben estar presentes. En el ejemplo siguiente se muestra
el uso de definiciones de cuerpos de expresin para ambos descriptores de acceso. Observe que no se usa la
palabra clave return con el descriptor de acceso get .
using System;
class Program
{
static void Main(string[] args)
{
var item = new SaleItem("Shoes", 19.95m);
Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");
}
}
// The example displays output like the following:
// Shoes: sells for $19.95
class Program
{
static void Main(string[] args)
{
var item = new SaleItem{ Name = "Shoes", Price = 19.95m };
Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");
}
}
// The example displays output like the following:
// Shoes: sells for $19.95
Secciones relacionadas
Utilizar propiedades
Propiedades de interfaz
Comparacin entre propiedades e indizadores
Restringir la accesibilidad del descriptor de acceso
Propiedades autoimplementadas
Vea tambin
Gua de programacin de C#
Utilizar propiedades
Indizadores
get (palabra clave)
set (palabra clave)
Utilizar propiedades (Gua de programacin de C#)
03/10/2017 9 min to read Edit Online
Las propiedades combinan aspectos de los campos y los mtodos. Para el usuario de un objeto, una propiedad
que parece un campo, el acceso a la propiedad necesita la misma sintaxis. Para el implementador de una clase, una
propiedad es uno o dos bloques de cdigo que representa un descriptor de acceso get o un descriptor de acceso
set. El bloque de cdigo del descriptor de acceso get se ejecuta cuando se lee la propiedad; el bloque de cdigo
del descriptor de acceso set se ejecuta cuando se asigna un nuevo valor a la propiedad. Una propiedad sin un
descriptor de acceso set se considera de solo lectura. Una propiedad sin un descriptor de acceso get se
considera de solo escritura. Una propiedad que tiene ambos descriptores de acceso es de lectura y escritura.
A diferencia de los campos, las propiedades no se clasifican como variables. Por lo tanto, no puede pasar una
propiedad como un parmetro ref u out.
Las propiedades tienen muchos usos: pueden validar datos antes de permitir un cambio; pueden exponer
claramente datos en una clase donde esos datos se recuperan realmente de otros orgenes, como una base de
datos; pueden realizar una accin cuando los datos se cambian, como generar un evento, o cambiar el valor de
otros campos.
Las propiedades se declaran en el bloque de clase especificando el nivel de acceso del campo, seguido del tipo de
la propiedad, seguido del nombre de la propiedad y seguido de un bloque de cdigo que declara un descriptor de
acceso get o un descriptor de acceso set . Por ejemplo:
En este ejemplo, Month se declara como una propiedad, de manera que el descriptor de acceso set pueda estar
seguro de que el valor Month se establece entre 1 y 12. La propiedad Month usa un campo privado para realizar
un seguimiento del valor actual. A menudo, a la ubicacin real de los datos de una propiedad se le conoce como la
"memoria auxiliar" de la propiedad. Esto es comn para las propiedades que usan campos privados como una
memoria auxiliar. El campo se marca como privado para asegurarse de que solo puede cambiarse llamando a la
propiedad. Para obtener ms informacin sobre las restricciones de acceso pblico y privado, vea Modificadores
de acceso.
Las propiedades implementadas automticamente proporcionan una sintaxis simplificada para las declaraciones
de propiedad simples. Para obtener ms informacin, vea Propiedades implementadas automticamente.
El descriptor de acceso get
El cuerpo del descriptor de acceso get se parece al de un mtodo. Debe devolver un valor del tipo de propiedad.
La ejecucin del descriptor de acceso get es equivalente a la lectura del valor del campo. Por ejemplo, cuando se
devuelve la variable privada del descriptor de acceso get y se habilitan las optimizaciones, la llamada al mtodo
de descriptor de acceso get se inserta mediante el compilador, de manera que no existe ninguna sobrecarga de
llamada al mtodo. En cambio, un mtodo de descriptor de acceso get virtual no puede insertarse porque el
compilador no conoce en tiempo de compilacin a qu mtodo puede llamarse realmente en tiempo de ejecucin.
A continuacin se muestra un descriptor de acceso get que devuelve el valor de un campo privado name :
class Person
{
private string name; // the name field
public string Name // the Name property
{
get
{
return name;
}
}
}
Cuando hace referencia a la propiedad, excepto como el destino de una asignacin, el descriptor de acceso get se
invoca para leer el valor de la propiedad. Por ejemplo:
El descriptor de acceso get debe finalizar en una instruccin return o throw, y el control no puede salir del cuerpo
del descriptor de acceso.
Cambiar el estado del objeto mediante el descriptor de acceso get es un estilo de programacin incorrecto. Por
ejemplo, el siguiente descriptor de acceso produce el efecto secundario de cambiar el estado del objeto cada vez
que se tiene acceso al campo number .
El descriptor de acceso get puede usarse para devolver el valor de campo o para calcularlo y devolverlo. Por
ejemplo:
class Employee
{
private string name;
public string Name
{
get
{
return name != null ? name : "NA";
}
}
}
En el segmento de cdigo anterior, si no asigna un valor a la propiedad Name , devolver el valor NA.
class Person
{
private string name; // the name field
public string Name // the Name property
{
get
{
return name;
}
set
{
name = value;
}
}
}
Cuando asigna un valor a la propiedad, el descriptor de acceso set se invoca mediante un argumento que
proporciona el valor nuevo. Por ejemplo:
Es un error usar el nombre de parmetro implcito, value , para una declaracin de variable local en el descriptor
de acceso set .
Comentarios
Las propiedades pueden marcarse como public , private , protected , internal o protected internal . Estos
modificadores de acceso definen cmo los usuarios de la clase pueden obtener acceso a la propiedad. Los
descriptores de acceso get y set para la misma propiedad pueden tener diferentes modificadores de acceso.
Por ejemplo, get puede ser public para permitir el acceso de solo lectura desde el exterior del tipo, y set
puede ser private o protected . Para ms informacin, vea Modificadores de acceso.
Una propiedad puede declararse como una propiedad esttica mediante la palabra clave static . Esto hace que la
propiedad est disponible para los autores de la llamada en cualquier momento, aunque no exista ninguna
instancia de la clase. Para ms informacin, vea Clases estticas y sus miembros.
Una propiedad puede marcarse como una propiedad virtual mediante la palabra clave virtual. Esto permite que las
clases derivadas invaliden el comportamiento de la propiedad mediante la palabra clave override. Para obtener
ms informacin sobre estas opciones, vea Herencia.
Una propiedad que invalida una propiedad virtual tambin puede sellarse, que especifica que para las clases
derivadas ya no es virtual. Por ltimo, una propiedad puede declararse abstracta. Esto significa que no existe
ninguna implementacin en la clase, y las clases derivadas deben escribir su propia implementacin. Para obtener
ms informacin sobre estas opciones, vea Abstract and Sealed Classes and Class Members (Clases y miembros
de clase abstractos y sellados [Gua de programacin de C#]).
NOTA
Es un error usar un modificador virtual, abstract u override en un descriptor de acceso de una propiedad static.
Ejemplo
En este ejemplo se muestran las propiedades de solo lectura, estticas y de instancia. Acepta el nombre del
empleado desde el teclado, incrementa NumberOfEmployees en 1 y muestra el nombre del empleado y el nmero.
public class Employee
{
public static int NumberOfEmployees;
private static int counter;
private string name;
// A Constructor:
public Employee()
{
// Calculate the employee's number:
counter = ++counter + NumberOfEmployees;
}
}
class TestEmployee
{
static void Main()
{
Employee.NumberOfEmployees = 107;
Employee e1 = new Employee();
e1.Name = "Claude Vige";
Ejemplo
En este ejemplo se muestra cmo tener acceso a una propiedad en una clase base que est oculta mediante otra
propiedad que tiene el mismo nombre en una clase derivada.
public class Employee
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
class TestHiding
{
static void Main()
{
Manager m1 = new Manager();
La conversin (Employee) se usa para tener acceso a la propiedad oculta de la clase base:
((Employee)m1).Name = "Mary";
Para obtener ms informacin sobre cmo ocultar miembros, vea el Modificador new.
Ejemplo
En este ejemplo, dos clases, Cube y Square , implementan una clase abstracta, Shape , e invalidan su propiedad
Area abstracta. Tenga en cuenta el uso del modificador override en las propiedades. El programa acepta el lado
como una entrada y calcula las reas del cuadrado y el cubo. Tambin acepta el rea como una entrada y calcula el
lado correspondiente para el cuadrado y el cubo.
public Cube(double s)
{
side = s;
}
class TestShapes
{
static void Main()
{
// Input the side:
System.Console.Write("Enter the side: ");
double side = double.Parse(System.Console.ReadLine());
Vea tambin
Gua de programacin de C#
Propiedades
Propiedades de interfaz
Propiedades autoimplementadas
Propiedades de interfaces (Gua de programacin de
C#)
03/10/2017 2 min to read Edit Online
Las propiedades se pueden declarar en una interfaz. A continuacin tiene un ejemplo de un descriptor de acceso
de indexador de interfaz:
El descriptor de acceso de una propiedad de interfaz no tiene un cuerpo. Por tanto, el propsito de los descriptores
de acceso es indicar si la propiedad es de lectura y escritura, de solo lectura o de solo escritura.
Ejemplo
En este ejemplo, la interfaz IEmployee tiene una propiedad de lectura y escritura, Name , y una propiedad de solo
lectura, Counter . La clase Employee implementa la interfaz IEmployee y usa estas dos propiedades. El programa
lee el nombre de un nuevo empleado y el nmero actual de empleados y muestra el nombre del empleado y el
nmero de empleados calculado.
Puede usar el nombre completo de la propiedad, que hace referencia a la interfaz en la que se declara el miembro.
Por ejemplo:
string IEmployee.Name
{
get { return "Employee Name"; }
set { }
}
Se denomina implementacin de interfaz explcita. Por ejemplo, si la clase Employee implementa dos interfaces
ICitizen y IEmployee , y ambas interfaces tienen la propiedad Name , la implementacin del miembro de interfaz
explcita ser necesaria. Es decir, la siguiente declaracin de propiedad:
string IEmployee.Name
{
get { return "Employee Name"; }
set { }
}
int Counter
{
get;
}
}
class TestEmployee
{
static void Main()
{
System.Console.Write("Enter number of employees: ");
Employee.numberOfEmployees = int.Parse(System.Console.ReadLine());
Vea tambin
Gua de programacin de C#
Propiedades
Utilizar propiedades
Comparacin entre propiedades e indizadores
Indexers (Indexadores)
Interfaces
Restringir la accesibilidad del descriptor de acceso
(Gua de programacin de C#)
03/10/2017 4 min to read Edit Online
Las partes get y set de una propiedad o un indexador se denominan descriptores de acceso. De forma
predeterminada, estos descriptores de acceso tienen la misma visibilidad o nivel de acceso: los de la propiedad o el
indexador al que pertenecen. Para obtener ms informacin, vea Niveles de accesibilidad. En cambio, a veces
resulta til restringir el acceso a uno de estos descriptores de acceso. Normalmente, esto implica restringir la
accesibilidad del descriptor de acceso set , mientras que se mantiene el descriptor de acceso get accesible
pblicamente. Por ejemplo:
En este ejemplo, una propiedad denominada Name define un descriptor de acceso get y set . El descriptor de
acceso get recibe el nivel de accesibilidad de la propiedad, public en este caso, mientras que el descriptor de
acceso set se restringe explcitamente al aplicar el modificador de acceso protected al propio descriptor de
acceso.
Implementar interfaces
Al usar un descriptor de acceso para implementar una interfaz, este no puede tener un modificador de acceso. En
cambio, si implementa la interfaz con un descriptor de acceso, como get , el otro descriptor de acceso puede tener
un modificador de acceso, como en el ejemplo siguiente:
Ejemplo
En el ejemplo siguiente, se incluyen tres clases: BaseClass , DerivedClass y MainClass . Hay dos propiedades en
BaseClass , Name y Id en ambas clases. En el ejemplo, se muestra cmo la propiedad Id en DerivedClass se
puede ocultar con la propiedad Id en BaseClass al usar un modificador de acceso restrictivo como protected o
private. Por tanto, cuando asigna valores a esta propiedad, se llama en su lugar a la propiedad en la clase
BaseClass . Si se reemplaza el modificador de acceso por public, la propiedad ser accesible.
En el ejemplo, tambin se muestra que un modificador de acceso restrictivo, como private o protected , en el
descriptor de acceso set de la propiedad Name en DerivedClass impide el acceso al descriptor de acceso y
genera un error al asignrselo.
public string Id
{
get { return id; }
set { }
}
}
class MainClass
{
static void Main()
{
BaseClass b1 = new BaseClass();
DerivedClass d1 = new DerivedClass();
b1.Name = "Mary";
d1.Name = "John";
b1.Id = "Mary123";
d1.Id = "John123"; // The BaseClass.Id property is called.
Comentarios
Tenga en cuenta que, si reemplaza la declaracin new private string Id por new public string Id , obtendr el
resultado:
Name and ID in the base class: Name-BaseClass, ID-BaseClass
Vea tambin
Gua de programacin de C#
Propiedades
Indexers (Indexadores)
Modificadores de acceso
Cmo: Declarar y usar propiedades de lectura y
escritura (Gua de programacin de C#)
03/10/2017 2 min to read Edit Online
Las propiedades proporcionan la comodidad de los miembros de datos pblicos sin los riesgos que provienen del
acceso sin comprobar, sin controlar y sin proteger a los datos de un objeto. Esto se consigue mediante los
descriptores de acceso: mtodos especiales que asignan y recuperan valores del miembro de datos subyacente. El
descriptor de acceso set permite que los miembros de datos se asignen, y el descriptor de acceso get recupera los
valores de los miembros de datos.
En este ejemplo se muestra una clase Person que tiene dos propiedades: Name (string) y Age (int). Ambas
propiedades proporcionan descriptores de acceso get y set , de manera que se consideran propiedades de
lectura y escritura.
Ejemplo
class Person
{
private string name = "N/A";
private int age = 0;
set
{
age = value;
}
}
class TestPerson
{
static void Main()
{
{
// Create a new Person object:
Person person = new Person();
// Print out the name and the age associated with the person:
Console.WriteLine("Person details - {0}", person);
Programacin slida
En el ejemplo anterior, las propiedades Name y Age son pblicas e incluyen un descriptor de acceso get y set .
Esto permite que cualquier objeto lea y escriba estas propiedades. En cambio, a veces esto es conveniente para
excluir uno de los descriptores de acceso. Omitir el descriptor de acceso set , por ejemplo, hace que la propiedad
sea de solo lectura:
De manera alternativa, puede exponer un descriptor de acceso pblicamente pero hacer que el otro sea privado o
est protegido. Para obtener ms informacin, vea Accesibilidad del descriptor de acceso asimtrico.
Una vez que se declaren las propiedades, pueden usarse como si fueran campos de la clase. Esto permite una
sintaxis muy natural cuando ambos obtienen y establecen el valor de una propiedad, como se muestra en las
instrucciones siguientes:
person.Name = "Joe";
person.Age = 99;
Tenga en cuenta que en un mtodo set de la propiedad est disponible una variable value especial. Esta variable
contiene el valor que el usuario ha especificado, por ejemplo:
name = value;
Tenga en cuenta la sintaxis pura para incrementar la propiedad Age en un objeto Person :
person.Age += 1;
Si los mtodos set y get independientes se han usado para modelar las propiedades, el cdigo equivalente
puede tener este aspecto:
person.SetAge(person.GetAge() + 1);
Tenga en cuenta que ToString no se usa explcitamente en el programa. Se invoca de manera predeterminada
mediante las llamadas a WriteLine .
Vea tambin
Gua de programacin de C#
Propiedades
Clases y structs
Propiedades autoimplementadas (Gua de
programacin de C#)
03/10/2017 1 min to read Edit Online
En C# 3.0 y versiones posteriores, las propiedades implementadas automticamente hacen que la declaracin de
propiedades sea ms concisa cuando no es necesaria ninguna lgica adicional en los descriptores de acceso de la
propiedad. Tambin permite que el cdigo de cliente cree objetos. Cuando se declara una propiedad tal como se
muestra en el ejemplo siguiente, el compilador crea un campo de respaldo privado y annimo al que solo se
puede acceder con los descriptores de acceso de propiedad get y set .
Ejemplo
En el ejemplo siguiente se muestra una clase simple que tiene algunas propiedades implementadas
automticamente:
// Constructor
public Customer(double purchases, string name, int ID)
{
TotalPurchases = purchases;
Name = name;
CustomerID = ID;
}
// Methods
public string GetContactInfo() {return "ContactInfo";}
public string GetTransactionHistory() {return "History";}
class Program
{
static void Main()
{
// Intialize a new object.
Customer cust1 = new Customer ( 4987.63, "Northwind",90108 );
//Modify a property
cust1.TotalPurchases += 499.99;
}
}
Vea tambin
Propiedades
Modificadores
Cmo: Implementar una clase ligera con propiedades
autoimplementadas (Gua de programacin de C#)
03/10/2017 2 min to read Edit Online
En este ejemplo se muestra cmo crear una clase ligera inmutable que solo sirve para encapsular un conjunto de
propiedades autoimplementadas. Use este tipo de construccin en lugar de un struct cuando deba utilizar una
semntica de tipo de referencia.
Puede crear una propiedad inmutable de dos maneras. Puede declarar el descriptor de acceso set como private. La
propiedad solo se puede establecer dentro del tipo, pero es inmutable a los consumidores. En su lugar puede
declarar solo el descriptor de acceso get, que hace que la propiedad sea inmutable en cualquier lugar excepto en el
constructor del tipo.
Cuando se declara un descriptor de acceso set privado, no se puede usar un inicializador de objeto para inicializar
la propiedad. Se debe utilizar un constructor o un mtodo factory.
Ejemplo
En el siguiente ejemplo se muestran dos maneras de implementar una clase inmutable que tenga propiedades
autoimplementadas. Cada forma declara una de las propiedades con un set privado y una de las propiedades
solamente con un get . La primera clase usa un constructor solo para inicializar las propiedades y la segunda clase
utiliza un mtodo factory esttico que llama a un constructor.
// Public constructor.
public Contact(string contactName, string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
}
// Private constructor.
private Contact2(string contactName, string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
/* Output:
Terry Adams, 123 Main St.
Fadi Fakhouri, 345 Cypress Ave.
Hanying Feng, 678 1st Ave
Cesar Garcia, 12 108th St.
Debra Garcia, 89 E. 42nd St.
*/
El compilador crea campos de respaldo para cada propiedad autoimplementada. No se puede acceder a los
campos directamente desde el cdigo fuente.
Vea tambin
Propiedades
struct
Inicializadores de objeto y coleccin
Mtodos (Gua de programacin de C#)
03/10/2017 11 min to read Edit Online
Un mtodo es un bloque de cdigo que contiene una serie de instrucciones. Un programa hace que se ejecuten
las instrucciones al llamar al mtodo y especificando los argumentos de mtodo necesarios. En C#, todas las
instrucciones ejecutadas se realizan en el contexto de un mtodo. El mtodo Main es el punto de entrada para
cada aplicacin de C# y se llama mediante Common Language Runtime (CLR) cuando se inicia el programa.
NOTA
En este tema se analizan los mtodos denominados. Para obtener informacin sobre las funciones annimas, vea
Funciones annimas (Gua de programacin de C#).
Firmas de mtodo
Los mtodos se declaran en una clase o struct especificando el nivel de acceso, como public o private ,
modificadores opcionales como abstract o sealed , el valor de retorno, el nombre del mtodo y cualquier
parmetro de mtodo. Todas estas partes forman la firma del mtodo.
NOTA
Un tipo de valor devuelto de un mtodo no forma parte de la firma del mtodo con el objetivo de sobrecargar el mtodo.
Sin embargo, forma parte de la firma del mtodo al determinar la compatibilidad entre un delegado y el mtodo que
seala.
Los parmetros de mtodo se encierran entre parntesis y se separan por comas. Los parntesis vacos indican
que el mtodo no requiere parmetros. Esta clase contiene tres mtodos:
Acceso a mtodos
Llamar a un mtodo en un objeto es como acceder a un campo. Despus del nombre del objeto, agregue un
punto, el nombre del mtodo y parntesis. Los argumentos se enumeran entre parntesis y estn separados por
comas. Los mtodos de la clase Motorcycle se pueden llamar como en el ejemplo siguiente:
class TestMotorcycle : Motorcycle
{
moto.StartEngine();
moto.AddGas(15);
moto.Drive(5, 20);
double speed = moto.GetTopSpeed();
Console.WriteLine("My top speed is {0}", speed);
}
}
int Square(int i)
{
// Store input argument in a local variable.
int input = i;
return input * input;
}
Ahora, si se pasa un objeto basado en este tipo a un mtodo, tambin se pasa una referencia al objeto. En el
ejemplo siguiente se pasa un objeto de tipo SampleRefType al mtodo ModifyObject .
Fundamentalmente, el ejemplo hace lo mismo que el ejemplo anterior en el que se pasa un argumento por valor
a un mtodo. Pero, debido a que se utiliza un tipo de referencia, el resultado es diferente. La modificacin que se
lleva a cabo en ModifyObject al campo value del parmetro, obj , tambin cambia el campo value del
argumento, rt , en el mtodo TestRefType . El mtodo TestRefType muestra 33 como salida.
Para obtener ms informacin sobre cmo pasar tipos de referencia por valor y por referencia, vea Pasar
parmetros Reference-Type (Gua de programacin de C#) y Tipos de referencia (Referencia de C#).
Valores devueltos
Los mtodos pueden devolver un valor al autor de llamada. Si el tipo de valor devuelto, el tipo enumerado antes
del nombre de mtodo, no es void , el mtodo puede devolver el valor mediante la utilizacin de la palabra clave
return . Una instruccin con la palabra clave return seguida de un valor que coincide con el tipo de valor
devuelto devolver este valor al autor de llamada del mtodo.
El valor puede devolverse al autor de la llamada mediante valor o, a partir de C# 7, mediante referencia. Los
valores se devuelven al autor de la llamada mediante referencia si la palabra clave ref se usa en la firma del
mtodo y sigue cada palabra clave return . Por ejemplo, la siguiente firma del mtodo y la instruccin return
indican que el mtodo devuelve nombres de variable estDistance mediante referencia al autor de la llamada.
La palabra clave return tambin detiene la ejecucin del mtodo. Si el tipo de valor devuelto es void , una
instruccin return sin un valor tambin es til para detener la ejecucin del mtodo. Sin la palabra clave
return , el mtodo dejar de ejecutarse cuando alcance el final del bloque de cdigo. Los mtodos con un tipo
de valor devuelto no nulo son necesarios para usar la palabra clave return para devolver un valor. Por ejemplo,
estos dos mtodos utilizan la palabra clave return para devolver enteros:
class SimpleMath
{
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
Para utilizar un valor devuelto de un mtodo, el mtodo de llamada puede usar la llamada de mtodo en
cualquier lugar; un valor del mismo tipo sera suficiente. Tambin puede asignar el valor devuelto a una variable.
Por ejemplo, los dos siguientes ejemplos de cdigo logran el mismo objetivo:
Usar una variable local, en este caso, result , para almacenar un valor es opcional. La legibilidad del cdigo
puede ser til, o puede ser necesaria si debe almacenar el valor original del argumento para todo el mbito del
mtodo.
Para usar un valor devuelto mediante referencia de un mtodo, debe declarar una variable local de tipo ref si
pretende modificar su valor. Por ejemplo, si el mtodo Planet.GetEstimatedDistance devuelve un valor Double
mediante referencia, puede definirlo como una variable local de tipo ref con cdigo como el siguiente:
Devolver una matriz multidimensional de un mtodo, M , que modifica el contenido de la matriz no es necesario
si la funcin de llamada ha pasado la matriz a M . Puede devolver la matriz resultante de M para obtener un
estilo correcto o un flujo funcional de valores, pero no es necesario porque C# pasa todos los tipos de referencia
mediante valor, y el valor de una referencia de matriz es el puntero de la matriz. En el mtodo M , los cambios en
el contenido de la matriz los puede observar cualquier cdigo que tenga una referencia a la matriz, como se
muestra en el ejemplo siguiente.
static void Main(string[] args)
{
int[,] matrix = new int[2, 2];
FillMatrix(matrix);
// matrix is now full of -1
}
Mtodos asincrnicos
Mediante la caracterstica asincrnica, puede invocar mtodos asincrnicos sin usar definiciones de llamada
explcitas ni dividir manualmente el cdigo en varios mtodos o expresiones lambda.
Si marca un mtodo con el modificador async , puede usar el operador await en el mtodo. Cuando el control
alcanza una expresin await en el mtodo asincrnico, el control se devuelve al autor de llamada y se progreso
del mtodo se suspende hasta que se completa la tarea esperada. Cuando se completa la tarea, la ejecucin
puede reanudarse en el mtodo.
NOTA
Un mtodo asincrnico vuelve al autor de llamada cuando encuentra el primer objeto esperado que an no se ha
completado o cuando llega al final del mtodo asincrnico, lo que ocurra primero.
Un mtodo asincrnico puede tener un tipo de valor devuelto de Task<TResult>, Task, o nulo. El tipo de valor
devuelto nulo se utiliza principalmente para definir controladores de eventos, donde se requiere un tipo de valor
devuelto nulo. No se puede esperar un mtodo asincrnico que devuelve nulo, y el autor de llamada de un
mtodo con tipo de devolucin nulo no puede capturar ninguna excepcin producida por este.
En el ejemplo siguiente, DelayAsync es un mtodo asincrnico con un tipo de valor devuelto de Task<TResult>.
DelayAsync tiene una instruccin return que devuelve un entero. Por lo tanto, la declaracin del mtodo de
DelayAsync debe tener un tipo de valor devuelto de Task<int> . Dado que el tipo de valor devuelto es Task<int>
, la evaluacin de la expresin await en DoSomethingAsync genera un entero, como se demuestra en la siguiente
instruccin: int result = await delayTask .
El mtodo startButton_Click es un ejemplo de un mtodo asincrnico con un tipo de valor devuelto nulo. Dado
que DoSomethingAsync es un mtodo asincrnico, la tarea de la llamada a DoSomethingAsync debe esperar, como
se muestra en la siguiente instruccin: await DoSomethingAsync(); . El mtodo startButton_Click debe definirse
con el modificador async porque el mtodo tiene una expresin await .
// using System.Diagnostics;
// using System.Threading.Tasks;
// Output:
// Result: 5
Un mtodo aisncrnico no puede declarar ningn parmetro ref u out , pero puede llamar a los mtodos que
tienen estos parmetros.
Para obtener ms informacin sobre los mtodos asincrnicos, vea Programacin asincrnica con Async y Await,
Flujo de control en programas asincrnicos y Tipos de valor devuelto de Async.
public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);
Si el mtodo devuelve void o si es un mtodo asincrnico, el cuerpo del mtodo debe ser una expresin de
instruccin (igual que con las expresiones lambda). Para las propiedades y los indexadores, solo deben leerse, y
no usa la palabra clave de descriptor de acceso get .
Iteradores
Un iterador realiza una iteracin personalizada en una coleccin, como una lista o matriz. Un iterador utiliza la
instruccin yield return para devolver cada elemento de uno en uno. Cuando se alcanza la instruccin yield
return , se recuerda la ubicacin actual en el cdigo. La ejecucin se reinicia desde esa ubicacin la prxima vez
que se llama el iterador.
Llame a un iterador a partir del cdigo de cliente mediante una instruccin foreach .
El tipo de valor devuelto de un iterador puede ser IEnumerable, IEnumerable<T>, IEnumeratoro IEnumerator<T>.
Para obtener ms informacin, consulta Iteradores.
Vea tambin
Gua de programacin de C#
Clases y structs
Modificadores de acceso
Clases estticas y sus miembros
Herencia
Clases y miembros de clase abstractos y sellados
params
return
out
ref
Pasar parmetros
Funciones locales (Gua de programacin de C#)
03/10/2017 6 min to read Edit Online
A partir de C# 7, C# admite funciones locales. Las funciones locales son mtodos privados de un tipo que estn
anidados en otro miembro. Solo se pueden llamar desde su miembro contenedor. Las funciones locales se pueden
declarar en y llamar desde:
Mtodos, especialmente los mtodos de iterador y asincrnicos
Constructores
Descriptores de acceso de propiedad
Descriptores de acceso de un evento
Mtodos annimos
Expresiones lambda
Finalizadores
Otras funciones locales
En cambio, las funciones locales no se pueden declarar dentro de un miembro con forma de expresin.
NOTA
En algunos casos, puede usar una expresin lambda para implementar funcionalidad compatible tambin con una funcin
local. Para ver una comparacin, consulte Funciones locales frente a expresiones lambda.
Las funciones locales aclaran la intencin del cdigo. Cualquiera que lea el cdigo puede ver que solo el mtodo
que lo contiene puede llamar al mtodo. Para los proyectos de equipo, tambin hacen que sea imposible que otro
desarrollador llame errneamente al mtodo directamente desde cualquier otro punto de la clase o struct.
using System;
using System.IO;
class Example
{
static void Main()
{
string contents = GetText(@"C:\temp", "example.txt");
Console.WriteLine("Contents of the file:\n" + contents);
}
return filepath;
}
}
}
class Example
{
static void Main()
{
IEnumerable<int> ienum = OddSequence(50, 110);
Console.WriteLine("Retrieved enumerator...");
En su lugar, puede producir una excepcin al realizar la validacin y antes de recuperar el iterador al devolver el
iterador de una funcin local, como se muestra en el ejemplo siguiente.
using System;
using System.Collections.Generic;
class Example
{
static void Main()
{
IEnumerable<int> ienum = OddSequence(50, 110);
Console.WriteLine("Retrieved enumerator...");
return GetOddSequenceEnumerator();
IEnumerable<int> GetOddSequenceEnumerator()
{
for (int i = start; i <= end; i++)
{
if (i % 2 == 1)
yield return i;
}
}
}
}
// The example displays the following output:
// Unhandled Exception: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid
values.
// Parameter name: end must be less than or equal to 100.
// at Sequence.<GetNumericRange>d__1.MoveNext() in Program.cs:line 23
// at Example.Main() in Program.cs:line 43
Las funciones locales se pueden usar de forma similar, para controlar las excepciones fuera de la operacin
asincrnica. Normalmente, las excepciones producidas en el mtodo asincrnico requieren que examine las
excepciones internas de una excepcin AggregateException. Las funciones locales permiten que el cdigo genere
un error inmediato y permiten que la excepcin se produzca y observe de forma sincrnica.
En el ejemplo siguiente, se usa un mtodo asincrnico denominado GetMultipleAsync para pausar durante un
nmero especificado de segundos y se devuelve un valor que es un mltiplo aleatorio de ese nmero de segundos.
El retraso mximo es de 5 segundos; se produce una excepcin ArgumentOutOfRangeException si el valor es
mayor que 5. Como se muestra en el ejemplo siguiente, la excepcin que produce cuando se pasa un valor de 6 al
mtodo GetMultipleAsync se encapsula en una excepcin AggregateException despus de que el mtodo
GetMultipleAsync empiece a ejecutarse.
using System;
using System.Threading.Tasks;
class Example
{
static void Main()
{
int result = GetMultipleAsync(6).Result;
Console.WriteLine($"The returned value is {result:N0}");
}
Igual que hemos hecho con el iterador de mtodo, podemos refactorizar el cdigo de este ejemplo para realizar la
validacin antes de llamar al mtodo asincrnico. Como se muestra en el resultado del ejemplo siguiente, la
excepcin ArgumentOutOfRangeException no se encapsula en una excepcin <x:System.AggregateException>.
using System;
using System.Threading.Tasks;
class Example
{
static void Main()
{
int result = GetMultiple(6).Result;
Console.WriteLine($"The returned value is {result:N0}");
}
return GetValueAsync();
Vea tambin
Mtodos
Valores devueltos y variables locales de tipo ref
03/10/2017 7 min to read Edit Online
A partir de C# 7, C# admite los valores devueltos de referencia (valores devueltos de tipo ref). Un valor devuelto de
referencia permite que un mtodo devuelva una referencia a un objeto, en lugar de un valor, al autor de una
llamada. El autor de la llamada puede tratar el objeto devuelto como si se hubiera devuelto por valor o por
referencia. Un valor devuelto por referencia que el autor de la llamada trata como una referencia en lugar de un
valor es una variable local de tipo ref.
Adems, el nombre del objeto devuelto por cada instruccin return en el cuerpo del mtodo debe ir precedido de
la palabra clave ref. Por ejemplo, la siguiente instruccin return devuelve un objeto Person denominado p por
referencia:
return ref p;
Tenga en cuenta que la palabra clave ref se usa antes de la declaracin de variable local y antes de la llamada al
mtodo. Si no se incluyen ambas palabras clave ref en la asignacin y declaracin de variable, se produce el error
del compilador CS8172, "No se puede inicializar una variable por referencia con un valor".
Los cambios posteriores en el objeto Person devuelto por el mtodo se reflejan en el objeto contacts .
Si p no est definido como una variable local de tipo ref mediante la palabra clave ref , los cambios que realiza
en p el autor de la llamada no se reflejan en el objeto contacts .
using System;
class NumberStore
{
int[] numbers = { 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023 };
En el ejemplo siguiente, se llama al mtodo NumberStore.FindNumber para recuperar el primer valor que es mayor o
igual que 16. Despus, el autor de la llamada duplica el valor devuelto por el mtodo. Como se muestra en el
resultado del ejemplo, este cambio se refleja en el valor de los elementos de matriz de la instancia NumberStore .
using System;
Sin que se admitan los valores devueltos de referencia, este tipo de operacin se realiza normalmente devolviendo
el ndice del elemento de matriz junto con su valor. Despus, el autor de la llamada puede usar este ndice para
modificar el valor en una llamada al mtodo independiente. En cambio, el autor de la llamada tambin puede
modificar el ndice para tener acceso a otros valores de matriz y, posiblemente, modificarlos.
Vea tambin
ref (palabra clave)
Pasar parmetros (Gua de programacin de C#)
03/10/2017 1 min to read Edit Online
En C#, los argumentos se pueden pasar a parmetros por valor o por referencia. El paso de parmetros por
referencia permite a los miembros de funciones, mtodos, propiedades, indexadores, operadores y constructores
cambiar el valor de los parmetros y hacer que ese cambio persista en el entorno de la llamada. Para pasar un
parmetro por referencia, use una de las palabras clave ref o out . En los ejemplos de este tema, para simplificar,
solo se usa la palabra clave ref . Para obtener ms informacin sobre la diferencia entre ref y out , vea ref, out
y Pasar matrices mediante Ref y Out.
En el ejemplo siguiente se muestra la diferencia entre los parmetros de valor y de referencia.
class Program
{
static void Main(string[] args)
{
int arg;
// Passing by value.
// The value of arg in Main is not changed.
arg = 4;
squareVal(arg);
Console.WriteLine(arg);
// Output: 4
// Passing by reference.
// The value of arg in Main is changed.
arg = 4;
squareRef(ref arg);
Console.WriteLine(arg);
// Output: 16
}
// Passing by reference
static void squareRef(ref int refParameter)
{
refParameter *= refParameter;
}
}
Una variable tipo de valor contiene sus datos directamente, en oposicin a la variable tipo de referencia, que
contiene una referencia a sus datos. Pasar una variable tipo de valor a un mtodo en funcin del valor significa
pasar una copia de la variable al mtodo. Ningn cambio realizado en el parmetro dentro del mtodo afecta a los
datos originales almacenados en la variable de argumentos. Si desea que el mtodo al que se llama cambie el valor
del parmetro, debe pasarlo en funcin de la referencia, con la palabra clave ref o out. Para simplificar, en el
ejemplo siguiente se usa ref .
class PassingValByVal
{
static void SquareIt(int x)
// The parameter x is passed by value.
// Changes to x will not affect the original value of x.
{
x *= x;
System.Console.WriteLine("The value inside the method: {0}", x);
}
static void Main()
{
int n = 5;
System.Console.WriteLine("The value before calling the method: {0}", n);
La variable n es un tipo de valor. Contiene sus datos, el valor 5 . Cuando se invoca SquareIt , el contenido de n
se copia en el parmetro x , que se multiplica dentro del mtodo. En Main , sin embargo, el valor de n es el
mismo despus de llamar al mtodo SquareIt que el que era antes. El cambio que tiene lugar dentro del mtodo
solo afecta a la variable local x .
class PassingValByRef
{
static void SquareIt(ref int x)
// The parameter x is passed by reference.
// Changes to x will affect the original value of x.
{
x *= x;
System.Console.WriteLine("The value inside the method: {0}", x);
}
static void Main()
{
int n = 5;
System.Console.WriteLine("The value before calling the method: {0}", n);
En este ejemplo, no es el valor de n el que se pasa, sino una referencia a n . El parmetro x no es un entero; se
trata de una referencia a int , en este caso, una referencia a n . Por tanto, cuando x se multiplica dentro del
mtodo, lo que realmente se multiplica es a lo que x hace referencia, n .
Al llamar al mtodo SwapByRef , use la palabra clave ref en la llamada, como se muestra en el ejemplo siguiente.
static void Main()
{
int i = 2, j = 3;
System.Console.WriteLine("i = {0} j = {1}" , i, j);
Vea tambin
Gua de programacin de C#
Pasar parmetros
Pasar parmetros Reference-Type
Pasar parmetros Reference-Type (Gua de
programacin de C#)
03/10/2017 4 min to read Edit Online
Una variable de un tipo de referencia no contiene sus datos directamente, contiene una referencia a sus datos. Al
pasar un parmetro de tipo de referencia por valor, es posible cambiar los datos a los que apunta el tipo de
referencia, como el valor de un miembro de clase. En cambio, no se puede cambiar el valor de la propia referencia;
es decir, no puede usar la misma referencia para asignar memoria para una nueva clase y hacer que persista fuera
del bloque. Para ello, pase el parmetro mediante las palabras clave ref u out. Para simplificar, en el ejemplo
siguiente se usa ref .
class PassingRefByVal
{
static void Change(int[] pArray)
{
pArray[0] = 888; // This change affects the original element.
pArray = new int[5] {-3, -1, -2, -3, -4}; // This change is local.
System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
}
Change(arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr [0]);
}
}
/* Output:
Inside Main, before calling the method, the first element is: 1
Inside the method, the first element is: -3
Inside Main, after calling the method, the first element is: 888
*/
En el ejemplo anterior, la matriz, arr , que es un tipo de referencia, se pasa al mtodo sin el parmetro ref . En tal
caso, se pasa al mtodo una copia de la referencia, que apunta a arr . El resultado muestra que es posible que el
mtodo cambie el contenido de un elemento de matriz, en este caso de 1 a 888 . En cambio, si se asigna una
nueva porcin de memoria al usar el operador new dentro del mtodo Change , la variable pArray hace referencia
a una nueva matriz. Por tanto, cualquier cambio que hubiese despus no afectar a la matriz original, arr , que se
ha creado dentro de Main . De hecho, se crean dos matrices en este ejemplo, una dentro de Main y otra dentro del
mtodo Change .
class PassingRefByRef
{
static void Change(ref int[] pArray)
{
// Both of the following changes will affect the original variables:
pArray[0] = 888;
pArray = new int[5] {-3, -1, -2, -3, -4};
System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
}
Change(ref arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr[0]);
}
}
/* Output:
Inside Main, before calling the method, the first element is: 1
Inside the method, the first element is: -3
Inside Main, after calling the method, the first element is: -3
*/
Todos los cambios que tienen lugar dentro del mtodo afectan a la matriz original en Main . De hecho, la matriz
original se reasigna mediante el operador new . Por tanto, despus de llamar al mtodo Change , cualquier
referencia a arr apunta a la matriz de cinco elementos, que se crea en el mtodo Change .
En este ejemplo, los parmetros tienen que pasarse en funcin de la referencia para afectar a las variables en el
programa que realiza la llamada. Si quita la palabra clave ref tanto del encabezado de mtodo como de la
llamada al mtodo, no se llevar a cabo ningn cambio en el programa que realiza la llamada.
Para obtener ms informacin sobre las cadenas, vea string.
Vea tambin
Gua de programacin de C#
Pasar parmetros
Pasar matrices mediante Ref y Out
ref
Tipos de referencia
Cmo: Saber las diferencias entre pasar a un mtodo
un struct y una referencia a clase (Gua de
programacin de C#)
03/10/2017 2 min to read Edit Online
En el ejemplo siguiente se muestra cmo pasar un struct a un mtodo es diferente de pasar una instancia de clase a
un mtodo. En el ejemplo, los dos argumentos (struct e instancia de clase) se pasan mediante valor, y ambos
mtodos cambian el valor de un campo del argumento. En cambio, los resultados de los dos mtodos no son los
mismos porque lo que se pasa cuando pasa un struct difiere de lo que se pasa cuando pasa una instancia de una
clase.
Como un struct es un tipo de valor, cuando pasa un struct mediante valor a un mtodo, el mtodo recibe y funciona
en una copia del argumento struct. El mtodo no tiene acceso al struct original en el mtodo de llamada y, por lo
tanto, no puede cambiarlo de ninguna manera. El mtodo solo puede cambiar la copia.
Una instancia de clase es un tipo de referencia, no un tipo de valor. Cuando un tipo de referencia se pasa mediante
valor a un mtodo, el mtodo recibe una copia de la referencia a la instancia de clase. Es decir, el mtodo recibe una
copia de la direccin de la instancia, no una copia de la propia instancia. La instancia de clase en el mtodo de
llamada tiene una direccin, el parmetro en el mtodo que se ha llamado tiene una copia de la direccin, y ambas
direcciones hacen referencia al mismo objeto. Como el parmetro solo contiene una copia de la direccin, el
mtodo al que se ha llamado no puede cambiar la direccin de la instancia de clase en el mtodo de llamada. En
cambio, el mtodo al que se ha llamado puede usar la direccin para tener acceso a los miembros de clase que la
direccin original y la copia hacen referencia. Si el mtodo al que se ha llamado cambia un miembro de clase, la
instancia de clase original en el mtodo de llamada tambin cambia.
En el resultado del ejemplo siguiente se ilustra la diferencia. El valor del campo willIChange de la instancia de clase
se cambia mediante la llamada al mtodo ClassTaker porque el mtodo usa la direccin en el parmetro para
buscar el campo especificado de la instancia de clase. El campo willIChange del struct en el mtodo de llamada no
se cambia mediante la llamada al mtodo StructTaker porque el valor del argumento es una copia del propio
struct, no una copia de su direccin. StructTaker cambia la copia, y la copia se pierde cuando se completa la
llamada a StructTaker .
Ejemplo
class TheClass
{
public string willIChange;
}
struct TheStruct
{
public string willIChange;
}
class TestClassAndStruct
{
static void ClassTaker(TheClass c)
{
c.willIChange = "Changed";
}
ClassTaker(testClass);
StructTaker(testStruct);
Vea tambin
Gua de programacin de C#
Clases
Structs
Pasar parmetros
Variables locales con asignacin implcita de tipos
(Gua de programacin de C#)
03/10/2017 4 min to read Edit Online
Las variables locales pueden declararse sin proporcionar un tipo explcito. La palabra clave var indica al
compilador que infiera el tipo de la variable a partir de la expresin de la derecha de la instruccin de inicializacin.
El tipo inferido puede ser un tipo integrado, un tipo annimo, un tipo definido por el usuario o un tipo definido en
la biblioteca de clases .NET Framework. Para obtener ms informacin sobre cmo inicializar las matrices con var ,
vea Matrices con tipo implcito.
Los ejemplos siguientes muestran distintas formas en que se pueden declarar variables locales con var :
// i is compiled as an int
var i = 5;
// s is compiled as a string
var s = "Hello";
// a is compiled as int[]
var a = new[] { 0, 1, 2 };
Es importante comprender que la palabra clave var no significa "variant" ni indica que la variable est dbilmente
tipada o est enlazada en tiempo de ejecucin. Solo significa que el compilador determina y asigna el tipo ms
adecuado.
La palabra clave var se puede usar en los contextos siguientes:
En variables locales (variables declaradas en el mbito del mtodo), tal y como se muestra en el ejemplo
anterior.
En una instruccin de inicializacin for.
Para obtener ms informacin, vea Cmo: Usar matrices y variables locales con tipo implcito en expresiones de
consulta (Gua de programacin de C#).
class ImplicitlyTypedLocals2
{
static void Main()
{
string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
Comentarios
Las siguientes restricciones se aplican a las declaraciones de variable con tipo implcito:
var solo se puede usar cuando una variable local se declara e inicializa en la misma instruccin; la variable
no se puede inicializar en null ni en un grupo de mtodos o una funcin annima.
var no se puede usar en campos en el mbito de clase.
Las variables declaradas con var no se pueden usar en la expresin de inicializacin. En otras palabras, esta
expresin es vlida : int i = (i = 20); , pero esta expresin genera un error en tiempo de compilacin:
var i = (i = 20);
// Same as previous example except we use the entire last name as a key.
// Query variable is an IEnumerable<IGrouping<string, Student>>
var studentQuery3 =
from student in students
group student by student.Last;
Pero el uso de var supone al menos la posibilidad de que el cdigo sea ms difcil de comprender para otros
programadores. Por ese motivo, la documentacin de C# por lo general solo usa var cuando es necesario.
Vea tambin
Referencia de C#
Implicitly Typed Arrays (Matrices con tipo implcito [Gua de programacin de C#])
Cmo: Usar matrices y variables locales con tipo implcito en expresiones de consulta (Gua de programacin de
C#)
Anonymous Types (Tipos annimos [Gua de programacin de C#])
Inicializadores de objeto y de coleccin
var
Expresiones de consulta LINQ
LINQ (Language-Integrated Query) (Language Integrated Query [LINQ])
for
foreach, in
using (instruccin)
Cmo: Usar matrices y variables locales con tipo
implcito en expresiones de consulta (Gua de
programacin de C#)
03/10/2017 2 min to read Edit Online
Puede usar variables locales con tipo implcito siempre que quiera que el compilador determine el tipo de una
variable local. Debe usar variables locales con tipo implcito para almacenar tipos annimos, que a menudo se usan
en las expresiones de consulta. En los ejemplos siguientes, se muestran los usos obligatorios y opcionales de las
variables locales con tipo implcito en las consultas.
Las variables locales con tipo implcito se declaran mediante la palabra clave contextual var. Para obtener ms
informacin, vea Variables locales con asignacin implcita de tipos y Matrices con asignacin implcita de tipos.
Ejemplo
En el ejemplo siguiente, se muestra un escenario comn en el que la palabra clave var es necesaria: una expresin
de consulta que genera una secuencia de tipos annimos. En este escenario, la variable de consulta y la variable de
iteracin en la instruccin foreach deben escribirse de forma implcita mediante el uso de var porque no se tiene
acceso a un nombre de tipo para el tipo annimo. Para obtener ms informacin sobre los tipos annimos, vea
Tipos annimos.
Ejemplo
En el ejemplo siguiente, se usa la palabra clave var en una situacin similar, pero en la que el uso de var es
opcional. Dado que student.LastName es una cadena, la ejecucin de la consulta devuelve una secuencia de
cadenas. Por tanto, el tipo de queryID podra declararse como System.Collections.Generic.IEnumerable<string> en
lugar de var . La palabra clave var se usa por comodidad. En el ejemplo, la variable de iteracin en la instruccin
foreach se escribe de forma explcita como una cadena, pero se podra declarar mediante var . Dado que el tipo
de la variable de iteracin no es un tipo annimo, el uso de var es opcional, no es obligatorio. Recuerde que var
no es un tipo, sino una instruccin para que el compilador deduzca y asigne el tipo.
// Variable queryID could be declared by using
// System.Collections.Generic.IEnumerable<string>
// instead of var.
var queryID =
from student in students
where student.ID > 111
select student.LastName;
Vea tambin
Gua de programacin de C#
Mtodos de extensin
LINQ (Language-Integrated Query)
var
Expresiones de consulta LINQ
Mtodos de extensin (Gua de programacin de C#)
03/10/2017 8 min to read Edit Online
Los mtodos de extensin permiten "agregar" mtodos a los tipos existentes sin crear un nuevo tipo derivado,
recompilar o modificar de otra manera el tipo original. Los mtodos de extensin son una clase especial de
mtodo esttico, pero se les llama como si fueran mtodos de instancia en el tipo extendido. En el caso del cdigo
de cliente escrito en C#, F# y Visual Basic, no existe ninguna diferencia aparente entre llamar a un mtodo de
extensin y llamar a los mtodos realmente definidos en un tipo.
Los mtodos de extensin ms comunes son los operadores de consulta LINQ estndar, que agregan funciones de
consulta a los tipos System.Collections.IEnumerable y System.Collections.Generic.IEnumerable<T> existentes. Para
usar los operadores de consulta estndar, inclyalos primero en el mbito con una directiva using System.Linq . A
partir de ese momento, cualquier tipo que implemente IEnumerable<T> parecer tener mtodos de instancia
como GroupBy, OrderBy, Average, etc. Puede ver estos mtodos adicionales en la finalizacin de instrucciones de
IntelliSense al escribir "punto" despus de una instancia de un tipo IEnumerable<T>, como List<T> o Array.
En el ejemplo siguiente se muestra cmo llamar al mtodo OrderBy de operador de consulta estndar en una
matriz de enteros. La expresin entre parntesis es una expresin lambda. Muchos operadores de consulta
estndar toman expresiones lambda como parmetros, pero no es un requisito para los mtodos de extensin.
Para obtener ms informacin, vea Lambda Expressions (Expresiones lambda).
class ExtensionMethods2
{
Los mtodos de extensin se definen como mtodos estticos, pero se les llama usando la sintaxis de mtodo de
instancia. El primer parmetro especifica en qu tipo funciona el mtodo, y el parmetro est precedido del
modificador this. Los mtodos de extensin nicamente se encuentran dentro del mbito cuando el espacio de
nombres se importa explcitamente en el cdigo fuente con una directiva using .
En el ejemplo siguiente se muestra un mtodo de extensin definido para la clase System.String. Observe que se
define dentro de una clase esttica no anidada y no genrica:
namespace ExtensionMethods
{
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
}
El mtodo de extensin WordCount se puede incluir en el mbito con esta directiva using :
using ExtensionMethods;
En el cdigo, el mtodo de extensin se invoca con la sintaxis de mtodo de instancia. Sin embargo, el lenguaje
intermedio (IL) generado por el compilador convierte el cdigo en una llamada en el mtodo esttico. Por lo tanto,
el principio de encapsulacin no se infringe realmente. De hecho, los mtodos de extensin no pueden tener
acceso a las variables privadas en el tipo que extienden.
Para obtener ms informacin, vea How to: Implement and Call a Custom Extension Method (Cmo: Implementar
e invocar un mtodo de extensin personalizado).
En general, probablemente se llamar a mtodos de extensin con mucha ms frecuencia de la que se
implementarn mtodos propios. Dado que los mtodos de extensin se llaman con la sintaxis de mtodo de
instancia, no se requieren conocimientos especiales para usarlos desde el cdigo de cliente. Para habilitar los
mtodos de extensin para un tipo determinado, basta con agregar una directiva using para el espacio de
nombres en el que se definen los mtodos. Por ejemplo, para usar los operadores de consulta estndar, agregue
esta directiva using al cdigo:
using System.Linq;
(Puede que haya que agregar tambin una referencia a System.Core.dll). Observar que los operadores de
consulta estndar aparecen ahora en IntelliSense como mtodos adicionales disponibles para la mayora de los
tipos IEnumerable<T>.
NOTA
Aunque los operadores de consulta estndar no aparezcan en IntelliSense para String, siguen estando disponibles.
Ejemplo
En el ejemplo siguiente se muestran las reglas que el compilador de C# sigue para determinar si se va a enlazar
una llamada a mtodo a un mtodo de instancia del tipo o a un mtodo de extensin. La clase esttica Extensions
contiene mtodos de extensin definidos para cualquier tipo que implemente IMyInterface . Las clases A , B y C
implementan la interfaz.
Nunca se llama al mtodo de extensin MethodB , porque su nombre y signatura coinciden exactamente con los
mtodos ya implementados por las clases.
Si el compilador no encuentra un mtodo de instancia con una signatura coincidente, se enlazar a un mtodo de
extensin coincidente, si existe.
class A : IMyInterface
{
public void MethodB() { Console.WriteLine("A.MethodB()"); }
}
class B : IMyInterface
{
public void MethodB() { Console.WriteLine("B.MethodB()"); }
public void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); }
}
class C : IMyInterface
{
public void MethodB() { Console.WriteLine("C.MethodB()"); }
public void MethodA(object obj)
{
Console.WriteLine("C.MethodA(object obj)");
}
}
class ExtMethodDemo
{
static void Main(string[] args)
{
// Declare an instance of class A, class B, and class C.
A a = new A();
B b = new B();
C c = new C();
Instrucciones generales
En general, recomendamos que se implementen mtodos de extensin con moderacin y nicamente cuando sea
necesario. Siempre que sea posible, el cdigo de cliente que debe extender un tipo existente debera hacerlo
creando un nuevo tipo derivado del existente. Para obtener ms informacin, vea Herencia.
Al usar un mtodo de extensin para ampliar un tipo cuyo cdigo fuente no se puede cambiar, se corre el riesgo
de que un cambio en la implementacin del tipo interrumpa el mtodo de extensin.
Si se implementan mtodos de extensin para un tipo determinado, recuerde los puntos siguientes:
Nunca se llamar a un mtodo de extensin si tiene la misma signatura que un mtodo definido en el tipo.
Los mtodos de extensin se incluyen en el mbito en el nivel de espacio de nombres. Por ejemplo, si se
tienen varias clases estticas que contienen mtodos de extensin en un nico espacio de nombres
denominado Extensions , la directiva using Extensions; los incluir a todos en el mbito.
Para una biblioteca de clases ya implementada, no deben usarse mtodos de extensin para evitar incrementar el
nmero de versin de un ensamblado. Si desea agregar una funcionalidad significativa a una biblioteca de la que
es propietario del cdigo fuente, deben seguirse las instrucciones de .NET Framework estndar para el control de
versiones de ensamblado. Para obtener ms informacin, vea Versiones de los ensamblados.
Vea tambin
Gua de programacin de C#
Ejemplos de programacin en paralelo (incluyen numerosos mtodos de extensin de ejemplo)
Expresiones lambda
Informacin general sobre operadores de consulta estndar
Conversion rules for Instance parameters and their impact (Reglas de conversin para los parmetros de instancia
y su impacto)
Extension methods Interoperability between languages (Interoperabilidad de los mtodos de extensin entre
lenguajes)
Extension methods and Curried Delegates (Mtodos de extensin y delegados currificados)
Extension method Binding and Error reporting (Enlazar mtodos de extensin y notificacin de errores)
Cmo: Implementar e invocar un mtodo de
extensin personalizado (Gua de programacin de
C#)
03/10/2017 2 min to read Edit Online
En este tema se muestra cmo implementar sus propios mtodos de extensin para cualquier tipo de la biblioteca
de clases .NET Framework o para cualquier otro tipo .NET que desee extender. El cdigo de cliente puede usar los
mtodos de extensin agregando una referencia a la DLL que los contiene y agregando una directiva using que
especifique el espacio de nombres en el que se definen los mtodos de extensin.
Ejemplo
En el ejemplo siguiente se implementa un mtodo de extensin denominado WordCount en la clase
CustomExtensions.StringExtension . El mtodo opera en la clase String, que se especifica como el primer parmetro
de mtodo. El espacio de nombres CustomExtensions se importa en el espacio de nombres de la aplicacin y se
llama al mtodo dentro del mtodo Main .
using System.Linq;
using System.Text;
using System;
namespace CustomExtensions
{
//Extension methods must be defined in a static class
public static class StringExtension
{
// This is the extension method.
// The first parameter takes the "this" modifier
// and specifies the type for which the method is defined.
public static int WordCount(this String str)
{
return str.Split(new char[] {' ', '.','?'}, StringSplitOptions.RemoveEmptyEntries).Length;
}
}
}
namespace Extension_Methods_Simple
{
//Import the extension method namespace.
using CustomExtensions;
class Program
{
static void Main(string[] args)
{
string s = "The quick brown fox jumped over the lazy dog.";
// Call the method as if it were an
// instance method on the type. Note that the first
// parameter is not specified by the calling code.
int i = s.WordCount();
System.Console.WriteLine("Word count of s is {0}", i);
}
}
}
Compilar el cdigo
Para ejecutar este cdigo, cpielo y pguelo en un proyecto de aplicacin de la consola de Visual C# creado en
Visual Studio. De forma predeterminada, este proyecto tiene como destino la versin 3.5 de .NET Framework y
tiene una referencia a System.Core.dll y una directiva using para System.Linq. Si faltan uno o varios de estos
requisitos del proyecto, se pueden agregar manualmente.
Vea tambin
Gua de programacin de C#
Mtodos de extensin
LINQ (Language-Integrated Query)
Clases estticas y sus miembros
protected
internal
public
this
namespace
Cmo: Crear un mtodo nuevo para una
enumeracin (Gua de programacin de C#)
03/10/2017 1 min to read Edit Online
Puede usar mtodos de extensin para agregar funcionalidad a un tipo de enumeracin concreto.
Ejemplo
En el ejemplo siguiente, la enumeracin Grades representa las posibles calificaciones con letras que un alumno
puede recibir en una clase. Un mtodo de extensin denominado Passing se agrega al tipo Grades para que cada
instancia de ese tipo "sepa" ahora si representa una calificacin de aprobado o no.
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace EnumExtension
{
// Define an extension method in a non-nested static class.
public static class Extensions
{
public static Grades minPassing = Grades.D;
public static bool Passing(this Grades grade)
{
return grade >= minPassing;
}
}
Extensions.minPassing = Grades.C;
Console.WriteLine("\r\nRaising the bar!\r\n");
Console.WriteLine("First {0} a passing grade.", g1.Passing() ? "is" : "is not");
Console.WriteLine("Second {0} a passing grade.", g2.Passing() ? "is" : "is not");
}
}
}
/* Output:
First is a passing grade.
Second is not a passing grade.
Tenga en cuenta que la clase Extensions tambin contiene una variable esttica que se actualiza dinmicamente y
que el valor devuelto del mtodo de extensin refleja el valor actual de esa variable. Esto demuestra que, en
segundo plano, los mtodos de extensin se invocan directamente en la clase esttica en donde se definen.
Compilar el cdigo
Para ejecutar este cdigo, cpielo y pguelo en un proyecto de aplicacin de la consola de Visual C# creado en
Visual Studio. De forma predeterminada, este proyecto tiene como destino la versin 3.5 de .NET Framework y tiene
una referencia a System.Core.dll y una directiva using para System.Linq. Si faltan uno o varios de estos requisitos
del proyecto, se pueden agregar manualmente.
Vea tambin
Gua de programacin de C#
Mtodos de extensin
Argumentos opcionales y con nombre (Gua de
programacin de C#)
03/10/2017 8 min to read Edit Online
C# 4 introduce argumentos opcionales y con nombre. Los argumentos con nombre permiten especificar un
argumento para un parmetro concreto asociando el argumento al nombre del parmetro y no a la posicin del
parmetro en la lista de parmetros. Los argumentos opcionales permiten omitir argumentos para algunos
parmetros. Ambas tcnicas se pueden usar con mtodos, indexadores, constructores y delegados.
Cuando se usan argumentos opcionales y con nombre, los argumentos se evalan por el orden en que aparecen en
la lista de argumentos, no en la lista de parmetros.
Los parmetros opcionales y con nombre, cuando se usan conjuntamente, solo permiten especificar argumentos
para algunos parmetros de una lista de parmetros opcionales. Esta funcionalidad facilita enormemente las
llamadas a interfaces COM, como las API de automatizacin de Microsoft Office.
Si no recuerda el orden de los parmetros pero conoce sus nombres, puede enviar los argumentos en cualquier
orden, primero el peso o primero la estatura.
CalculateBMI(weight: 123, height: 64);
Los argumentos con nombre tambin mejoran la legibilidad del cdigo al identificar lo que cada argumento
representa.
Un argumento con nombre puede seguir a los argumentos posicionales, tal y como se muestra aqu.
CalculateBMI(123, height: 64);
Pero un argumento posicional no puede seguir a un argumento con nombre. La instruccin siguiente genera un
error del compilador.
//CalculateBMI(weight: 123, 64);
Ejemplo
El cdigo siguiente implementa los ejemplos de esta seccin.
class NamedExample
{
static void Main(string[] args)
{
// The method can be called in the normal way, by using positional arguments.
PrintOrderDetails("Gift Shop", 31, "Red Mug");
Argumentos opcionales
La definicin de un mtodo, constructor, indexador o delegado puede especificar que sus parmetros son
necesarios o que son opcionales. Todas las llamadas deben proporcionar argumentos para todos los parmetros
necesarios, pero pueden omitir los argumentos para los parmetros opcionales.
Cada parmetro opcional tiene un valor predeterminado como parte de su definicin. Si no se enva ningn
argumento para ese parmetro, se usa el valor predeterminado. Un valor predeterminado debe ser uno de los
siguientes tipos de expresiones:
una expresin constante;
una expresin con el formato new ValType() , donde ValType es un tipo de valor, como enum o struct;
una expresin con el formato default(ValType), donde ValType es un tipo de valor.
Los parmetros opcionales se definen al final de la lista de parmetros despus de los parmetros necesarios. Si el
autor de la llamada proporciona un argumento para algn parmetro de una sucesin de parmetros opcionales,
debe proporcionar argumentos para todos los parmetros opcionales anteriores. No se admiten espacios
separados por comas en la lista de argumentos. Por ejemplo, en el cdigo siguiente, el mtodo de instancia
ExampleMethod se define con un parmetro necesario y dos opcionales.
Pero si conoce el nombre del tercer parmetro, puede usar un argumento con nombre para realizar la tarea.
anExample.ExampleMethod(3, optionalint: 4);
IntelliSense usa corchetes para indicar parmetros opcionales, tal y como se muestra en la ilustracin siguiente.
NOTA
Tambin puede declarar parmetros opcionales con la clase OptionalAttribute de .NET. Los parmetros OptionalAttribute
no requieren un valor predeterminado.
Ejemplo
En el ejemplo siguiente, el constructor de ExampleClass tiene un solo parmetro, que es opcional. El mtodo de
instancia ExampleMethod tiene un parmetro necesario, required , y dos parmetros opcionales, optionalstr y
optionalint . El cdigo de Main muestra las distintas formas en que se pueden invocar el constructor y el mtodo.
namespace OptionalNamespace
{
class OptionalExample
{
static void Main(string[] args)
{
// Instance anExample does not send an argument for the constructor's
// optional parameter.
ExampleClass anExample = new ExampleClass();
anExample.ExampleMethod(1, "One", 1);
anExample.ExampleMethod(2, "Two");
anExample.ExampleMethod(3);
class ExampleClass
{
private string _name;
Interfaces COM
Los argumentos opcionales y con nombre, adems de compatibilidad con objetos dinmicos y otros avances,
mejoran considerablemente la interoperabilidad con las API de COM, como las API de automatizacin de Office.
Por ejemplo, el mtodo AutoFormat de la interfaz Range de Microsoft Office Excel tiene siete parmetros, todos
ellos opcionales. Estos parmetros se muestran en la siguiente ilustracin.
Parmetros de AutoFormat
En C# 3.0 y versiones anteriores, se requiere un argumento para cada parmetro, tal y como se muestra en el
ejemplo siguiente.
// In C# 3.0 and earlier versions, you need to supply an argument for
// every parameter. The following call specifies a value for the first
// parameter, and sends a placeholder value for the other six. The
// default values are used for those parameters.
var excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Workbooks.Add();
excelApp.Visible = true;
var myFormat =
Microsoft.Office.Interop.Excel.XlRangeAutoFormat.xlRangeAutoFormatAccounting1;
Pero la llamada a AutoFormat se puede simplificar considerablemente mediante argumentos opcionales y con
nombre, que se introducen en C# 4.0. Los parmetros opcionales y con nombre permiten omitir el argumento de
un parmetro opcional si no se quiere cambiar el valor predeterminado del parmetro. En la siguiente llamada,
solo se especifica un valor para uno de los siete parmetros.
// The following code shows the same call to AutoFormat in C# 4.0. Only
// the argument for which you want to provide a specific value is listed.
excelApp.Range["A1", "B4"].AutoFormat( Format: myFormat );
Para obtener ms informacin y ejemplos, vea How to: Use Named and Optional Arguments in Office
Programming [Cmo: Usar argumentos opcionales y con nombre en la programacin de Office (Gua de
programacin de C#)] y How to: Access Office Interop Objects by Using Visual C# Features [Cmo: Tener acceso a
objetos de interoperabilidad de Office mediante las caractersticas de Visual C# (Gua de programacin de C#)].
Overload Resolution
El uso de argumentos opcionales y con nombre afecta a la resolucin de sobrecarga de las maneras siguientes:
Un mtodo, indexador o constructor es un candidato para la ejecucin si cada uno de sus parmetros es
opcional o corresponde, por nombre o por posicin, a un solo argumento de la instruccin de llamada y el
argumento se puede convertir al tipo del parmetro.
Si se encuentra ms de un candidato, se aplican las reglas de resolucin de sobrecarga de las conversiones
preferidas a los argumentos que se especifican explcitamente. Los argumentos omitidos en parmetros
opcionales se ignoran.
Si dos candidatos se consideran igualmente correctos, la preferencia pasa a un candidato que no tenga
parmetros opcionales cuyos argumentos se hayan omitido en la llamada. Se trata de una consecuencia de
una preferencia general en la resolucin de sobrecarga para los candidatos con menos parmetros.
Vea tambin
How to: Use Named and Optional Arguments in Office Programming [Cmo: Usar argumentos opcionales y con
nombre en la programacin de Office (Gua de programacin de C#)]
Uso de tipo dinmico
Using Constructors [Uso de constructores (Gua de programacin de C#)]
Utilizar indizadores
Cmo: Usar argumentos opcionales y con nombre en
la programacin de Office (Gua de programacin de
C#)
03/10/2017 5 min to read Edit Online
Los argumentos con nombre y los argumentos opcionales, introducidos en C# 4, mejoran la comodidad, la
flexibilidad y la legibilidad en la programacin de C#. Adems, estas caractersticas facilitan enormemente el acceso
a interfaces COM, como las API de automatizacin de Microsoft Office.
En el ejemplo siguiente, el mtodo ConvertToTable tiene diecisis parmetros que representan las caractersticas
de una tabla, como el nmero de columnas y filas, el formato, los bordes, las fuentes y los colores. Los diecisis
parmetros son opcionales, ya que la mayora de las veces no interesa especificar valores concretos para todos
ellos. Pero si no hay argumentos opcionales y con nombre, es necesario proporcionar un valor o un valor de
marcador de posicin para cada parmetro. Con los argumentos opcionales y con nombre, puede especificar
valores solamente para los parmetros necesarios para el proyecto.
Debe tener Microsoft Office Word instalado en el equipo para completar estos procedimientos.
NOTA
Es posible que tu equipo muestre nombres o ubicaciones diferentes para algunos de los elementos de la interfaz de usuario
de Visual Studio en las siguientes instrucciones. La edicin de Visual Studio que se tenga y la configuracin que se utilice
determinan estos elementos. Para obtener ms informacin, vea Personalizar el IDE.
2. Agregue el cdigo siguiente al final del mtodo para definir dnde se muestra texto en el documento y qu
texto se muestra.
DisplayInWord();
2. Presione CTRL+F5 para ejecutar el proyecto. Aparecer un documento de Word con el texto especificado.
Para convertir el texto en tabla
1. Use el mtodo ConvertToTable para incluir el texto en una tabla. El mtodo tiene 16 parmetros opcionales.
IntelliSense coloca los parmetros opcionales entre corchetes, tal como se muestra en la ilustracin
siguiente.
Parmetros de ConvertToTable
Los argumentos opcionales y con nombre permiten especificar valores solo para los parmetros que quiere
cambiar. Agregue el cdigo siguiente al final del mtodo DisplayInWord para crear una tabla simple. El
argumento especifica que las comas de la cadena de texto de range separan las celdas de la tabla.
// Convert to a simple table. The table will have a single row with
// three columns.
range.ConvertToTable(Separator: ",");
En versiones anteriores de C#, la llamada a ConvertToTable requiere un argumento de referencia para cada
parmetro, tal como se muestra en el cdigo siguiente.
2. Para especificar un formato predefinido para la tabla, reemplace la ltima lnea de DisplayInWord por la
instruccin siguiente y escriba CTRL+F5. El formato puede ser cualquiera de las constantes WdTableFormat.
Ejemplo
En el cdigo siguiente se incluye el ejemplo completo.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Word = Microsoft.Office.Interop.Word;
namespace OfficeHowTo
{
class WordProgram
{
static void Main(string[] args)
{
DisplayInWord();
}
// Next, use the ConvertToTable method to put the text into a table.
// The method has 16 optional parameters. You only have to specify
// values for those you want to change.
// Convert to a simple table. The table will have a single row with
// three columns.
range.ConvertToTable(Separator: ",");
Vea tambin
Argumentos opcionales y con nombre
Constructores (Gua de programacin de C#)
03/10/2017 2 min to read Edit Online
Cada vez que se crea una clase o struct, se llama a su constructor. Una clase o struct puede tener varios
constructores que toman argumentos diferentes. Los constructores permiten al programador establecer valores
predeterminados, limitar la creacin de instancias y escribir cdigo flexible y fcil de leer. Para obtener ms
informacin y ejemplos, vea Usar constructores y Constructores de instancias.
Constructores predeterminados
Si no proporciona un constructor para la clase, C# crear uno de manera predeterminada que cree instancias del
objeto y establezca las variables miembro en los valores predeterminados que se indican en Tabla de valores
predeterminados. Si no proporciona un constructor para su struct, C# se basa en un constructor predeterminado
implcito para inicializar automticamente cada campo de un tipo de valor en su valor predeterminado como se
muestra en la Tabla de valores predeterminados. Para obtener ms informacin y ejemplos, vea Constructores
de instancias.
Si un constructor puede implementarse como una instruccin nica, puede usar una definicin del cuerpo de
expresin. En el ejemplo siguiente se define una clase Location cuyo constructor tiene un nico parmetro de
cadena denominado name. La definicin del cuerpo de expresin asigna el argumento al campo locationName .
static Adult()
{
minimumAge = 18;
}
Tambin puede definir un constructor esttico con una definicin de cuerpo de expresin, como se muestra en el
ejemplo siguiente.
En esta seccin
Utilizar constructores
Constructores de instancias
Constructores privados
Constructores estticos
Cmo: Escribir un constructor Copy
Vea tambin
Gua de programacin de C#
Clases y estructuras
Finalizadores
static
Why Do Initializers Run In The Opposite Order As Constructors? Part One (Por qu los inicializadores se
ejecutan en orden contrario a los constructores? Parte uno)
Utilizar constructores (Gua de programacin de C#)
03/10/2017 4 min to read Edit Online
Cuando se crea una class o un struct, se llama a su constructor. Los constructores tienen el mismo nombre que la
class o el struct y suelen inicializar los miembros de datos del nuevo objeto.
En el ejemplo siguiente, una clase denominada Taxi se define mediante un constructor simple. Luego, se crea
una instancia de la clase con el operador new. El constructor Taxi se invoca con el operador new
inmediatamente despus de asignar memoria para el nuevo objeto.
class TestTaxi
{
static void Main()
{
Taxi t = new Taxi();
Console.WriteLine(t.isInitialized);
}
}
Un constructor que no toma ningn parmetro se denomina constructor predeterminado. Los constructores
predeterminados se invocan cada vez que se crea una instancia de un objeto mediante el operador new y no se
especifica ningn argumento en new . Para obtener ms informacin, vea Instance Constructors (Constructores de
instancias [Gua de programacin de C#]).
A menos que la clase sea static, las clases sin constructores tienen un constructor pblico predeterminado por el
compilador de C# con el fin de habilitar la creacin de instancias de clase. Para obtener ms informacin, consulte
Clases estticas y sus miembros.
Puede impedir que se cree una instancia de una clase convirtiendo el constructor en privado, de la manera
siguiente:
class NLog
{
// Private Constructor:
private NLog() { }
Para obtener ms informacin, vea Private Constructors (Constructores privados [Gua de programacin de C#]).
Los constructores de tipos struct son similares a los constructores de clases, pero structs no puede contener un
constructor predeterminado explcito porque el compilador proporciona uno automticamente. Este constructor
inicializa cada campo del struct en los valores predeterminados. Para obtener ms informacin, vea Default
Values Table (Tabla de valores predeterminados [Referencia de C#]). Pero este constructor predeterminado solo
se invoca si las instancias de struct se crean con new . Por ejemplo, este cdigo usa el constructor
predeterminado para Int32, por lo que se tiene la certeza de que el entero se inicializa:
Si bien, el siguiente cdigo genera un error del compilador porque no usa new y porque intenta usar un objeto
que no se ha inicializado:
int i;
Console.WriteLine(i);
Tambin puede inicializar o asignar los objetos basados en structs (incluidos todos los tipos numricos
integrados) y luego usarlos como en el ejemplo siguiente:
Un constructor puede usar la palabra clave base para llamar al constructor de una clase base. Por ejemplo:
public class Manager : Employee
{
public Manager(int annualSalary)
: base(annualSalary)
{
//Add further instructions here.
}
}
En este ejemplo, se llama al constructor de la clase base antes de ejecutar el bloque del constructor. La palabra
clave base puede usarse con o sin parmetros. Los parmetros del constructor se pueden usar como parmetros
en base o como parte de una expresin. Para obtener ms informacin, vea base.
En una clase derivada, si un constructor de clase base no se llama explcitamente con la palabra clave base , se
llama implcitamente al constructor predeterminado, si hay alguno. Esto significa que las siguientes declaraciones
del constructor son en efecto iguales:
Si una clase base no proporciona un constructor predeterminado, la clase derivada debe realizar una llamada
explcita a un constructor base mediante base .
Un constructor puede invocar otro constructor en el mismo objeto mediante la palabra clave this. Igual que base ,
this puede usarse con o sin parmetros. Adems, los parmetros del constructor estn disponibles como
parmetros en this o como parte de una expresin. Por ejemplo, el segundo constructor del ejemplo anterior se
puede reescribir con this :
Los constructores se pueden marcar como public, private, protected, internal o protected internal . Estos
modificadores de acceso definen cmo los usuarios de la clase pueden construir la clase. Para obtener ms
informacin, consulte Modificadores de acceso.
Un constructor puede declararse esttico mediante la palabra clave static. Los constructores estticos se llaman
automticamente, inmediatamente antes de acceder a los campos estticos y, por lo general, se usan para
inicializar miembros de clase esttica. Para obtener ms informacin, vea Static Constructors (Constructores
estticos [Gua de programacin de C#]).
Vea tambin
Gua de programacin de C#
Clases y estructuras
Constructors (Constructores [Gua de programacin de C#])
Finalizadores
Constructores de instancias (Gua de programacin
de C#)
03/10/2017 4 min to read Edit Online
Los constructores de instancias se usan para crear e inicializar las variables miembro de instancia cuando se usa
la expresin new para crear un objeto de una clase. Para inicializar una clase esttica, o variables estticas en una
clase no esttica, se debe definir un constructor esttico. Para obtener ms informacin, vea Static Constructors
(Constructores estticos [Gua de programacin de C#]).
En el siguiente ejemplo se muestra un constructor de instancias:
class CoOrds
{
public int x, y;
// constructor
public CoOrds()
{
x = 0;
y = 0;
}
}
NOTA
Para mayor claridad, esta clase contiene campos pblicos. El uso de campos pblicos no es una prctica de programacin
recomendada porque permite que cualquier mtodo de cualquier parte de un programa obtenga acceso sin restricciones ni
comprobaciones a los mecanismos internos de un objeto. Los miembros de datos generalmente deberan ser privados y
solo se debera tener acceso a ellos a travs de las propiedades y mtodos de la clase.
Se llama a este constructor de instancias cada vez que se crea un objeto basado en la clase CoOrds . Un
constructor como este, que no toma ningn argumento, se denomina constructor predeterminado. Pero a
menudo resulta til proporcionar constructores adicionales. Por ejemplo, se puede agregar un constructor a la
clase CoOrds que permita especificar los valores iniciales de los miembros de datos:
Esto permite crear objetos CoOrd con valores iniciales predeterminados o especficos, como este:
Si una clase no tiene un constructor, se genera automticamente un constructor predeterminado y los valores
predeterminados se usan para inicializar los campos del objeto. Por ejemplo, un int se inicializa en 0. Para ms
informacin sobre los valores predeterminados, vea Tabla de valores predeterminados (Referencia de C#). Por
tanto, dado que el constructor predeterminado de la clase CoOrds inicializa todos los miembros de datos en cero,
se puede quitar por completo sin cambiar el funcionamiento de la clase. Ms adelante en este tema se
proporciona un ejemplo completo del uso de varios constructores en el Ejemplo 1 y en el Ejemplo 2 se
proporciona un ejemplo de un constructor generado automticamente.
Los constructores de instancias tambin se pueden usar para llamar a los constructores de instancias de las clases
base. El constructor de clase puede invocar el constructor de la clase base a travs del inicializador, como sigue:
En este ejemplo, la clase Circle pasa valores que representan el radio y el alto al constructor proporcionado por
Shape desde el que se deriva Circle . Un ejemplo completo del uso de Shape y Circle aparece en este tema en
el Ejemplo 3.
Ejemplo 1
En el ejemplo siguiente se muestra una clase con dos constructores de clase, uno sin argumentos y uno con dos
argumentos.
class CoOrds
{
public int x, y;
// Default constructor:
public CoOrds()
{
x = 0;
y = 0;
}
class MainClass
{
static void Main()
{
CoOrds p1 = new CoOrds();
CoOrds p2 = new CoOrds(5, 3);
Ejemplo 2
En este ejemplo, la clase Person no tiene ningn constructor, en cuyo caso, se proporciona automticamente un
constructor predeterminado y los campos se inicializan en sus valores predeterminados.
public class Person
{
public int age;
public string name;
}
class TestPerson
{
static void Main()
{
Person person = new Person();
Observe que el valor predeterminado de age es 0 y el valor predeterminado de name es null . Para ms
informacin sobre los valores predeterminados, vea Tabla de valores predeterminados (Referencia de C#).
Ejemplo 3
En el ejemplo siguiente se muestra cmo usar el inicializador de la clase base. La clase Circle se deriva de la
clase general Shape y la clase Cylinder se deriva de la clase Circle . En cada clase derivada, el constructor usa
su inicializador de clase base.
abstract class Shape
{
public const double pi = Math.PI;
protected double x, y;
class TestShapes
{
static void Main()
{
double radius = 2.5;
double height = 3.0;
Para obtener ms ejemplos sobre cmo invocar los constructores de clase base, vea virtual, override y base.
Vea tambin
Gua de programacin de C#
Clases y estructuras
Constructors (Constructores [Gua de programacin de C#])
Finalizadores
static
Constructores privados (Gua de programacin de
C#)
03/10/2017 1 min to read Edit Online
Un constructor privado es un constructor de instancia especial. Se usa generalmente en clases que contienen solo
miembros estticos. Si una clase tiene uno o ms constructores privados y ningn constructor pblico, el resto de
clases (excepto las anidadas) no podrn crear instancias de esta clase. Por ejemplo:
class NLog
{
// Private Constructor:
private NLog() { }
Ejemplo
El siguiente es un ejemplo de clase que usa un constructor privado.
public class Counter
{
private Counter() { }
public static int currentCount;
public static int IncrementCount()
{
return ++currentCount;
}
}
class TestCounter
{
static void Main()
{
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
// Counter aCounter = new Counter(); // Error
Counter.currentCount = 100;
Counter.IncrementCount();
Console.WriteLine("New count: {0}", Counter.currentCount);
Observe que si quita el comentario de la siguiente instruccin del ejemplo, se producir un error porque el
constructor es inaccesible debido a su nivel de proteccin:
Vea tambin
Gua de programacin de C#
Clases y estructuras
Constructors (Constructores [Gua de programacin de C#])
Finalizadores
private
public
Constructores estticos (Gua de programacin de
C#)
03/10/2017 3 min to read Edit Online
Un constructor esttico se usa para inicializar cualquier dato esttico o realizar una accin determinada que solo
debe realizarse una vez. Es llamado automticamente antes de crear la primera instancia o de hacer referencia a
cualquier miembro esttico.
class SimpleClass
{
// Static variable that must be initialized at run time.
static readonly long baseline;
Ejemplo
En este ejemplo, la clase Bus tiene un constructor esttico. Cuando se crea la primera instancia de Bus ( bus1 ),
se invoca el constructor esttico para inicializar la clase. En el resultado del ejemplo, se comprueba que el
constructor esttico se ejecuta solo una vez, incluso si se crean dos instancias de Bus , y que se ejecuta antes de
que se ejecute el constructor de instancia.
// Instance constructor.
public Bus(int routeNum)
{
RouteNumber = routeNum;
Console.WriteLine("Bus #{0} is created.", RouteNumber);
}
// Instance method.
public void Drive()
{
TimeSpan elapsedTime = DateTime.Now - globalStartTime;
class TestBus
{
static void Main()
{
// The creation of this instance activates the static constructor.
Bus bus1 = new Bus(71);
C# no proporciona un constructor de copias para los objetos, pero puede escribir uno personalmente.
Ejemplo
En el ejemplo siguiente, Person class define un constructor de copias que toma, como argumento, una instancia de
Person . Los valores de las propiedades de los argumentos se asignan a las propiedades de la nueva instancia de
Person . El cdigo contiene un constructor de copias alternativo que enva las propiedades Name y Age de la
instancia que quiere copiar al constructor de instancia de la clase.
class Person
{
// Copy constructor.
public Person(Person previousPerson)
{
Name = previousPerson.Name;
Age = previousPerson.Age;
}
// Instance constructor.
public Person(string name, int age)
{
Name = name;
Age = age;
}
class TestPerson
{
static void Main()
{
// Create a Person object by using the instance constructor.
Person person1 = new Person("George", 40);
// Show details to verify that the name and age fields are distinct.
Console.WriteLine(person1.Details());
Console.WriteLine(person2.Details());
Vea tambin
ICloneable
Gua de programacin de C#
Clases y estructuras
Constructors (Constructores [Gua de programacin de C#])
Finalizadores
Finalizadores (Gua de programacin de C#)
03/10/2017 3 min to read Edit Online
Comentarios
Los finalizadores no se pueden definir en structs. Solo se usan con clases.
Una clase solo puede tener un finalizador.
Los finalizadores no se pueden heredar ni sobrecargar.
No se puede llamar a los finalizadores. Se invocan automticamente.
Un finalizador no permite modificadores ni tiene parmetros.
Por ejemplo, el siguiente cdigo muestra una declaracin de un finalizador para la clase Car .
class Car
{
~Car() // destructor
{
// cleanup statements...
}
}
Un finalizador tambin puede implementarse como una definicin de cuerpo de expresin, como se muestra en
el ejemplo siguiente.
using System;
El finalizador llama implcitamente a Finalize en la clase base del objeto. Por lo tanto, una llamada a un
finalizador se convierte implcitamente al siguiente cdigo:
Esto significa que se realizan llamadas al mtodo Finalize de manera recursiva para todas las instancias de la
cadena de herencia, desde la ms a la menos derivada.
NOTA
Los finalizadores vacos no deben usarse. Cuando una clase contiene un finalizador, se crea una entrada en la cola
Finalize . Cuando se llama al finalizador, se invoca al recolector de elementos no utilizados para procesar la cola. Un
finalizador vaco simplemente produce una prdida de rendimiento innecesaria.
El programador no puede controlar cundo se llama al finalizador, porque esto lo determina el recolector de
elementos no utilizados. El recolector de elementos no utilizados comprueba si hay objetos que ya no estn
siendo usados por ninguna aplicacin. Si considera un objeto elegible para su finalizacin, llama al finalizador (si
existe) y reclama la memoria usada para almacenar el objeto. Tambin se llama a los finalizadores cuando se
cierra el programa.
Es posible forzar la recoleccin de elementos no utilizados llamando a Collect, pero en general debe evitarse su
uso por razones de rendimiento.
Ejemplo
En el siguiente ejemplo se crean tres clases que forman una cadena de herencia. La clase First es la clase base,
Second se deriva de First y Third se deriva de Second . Los tres tienen finalizadores. En Main , se crea una
instancia de la clase ms derivada. Cuando ejecute el programa, observe que se llama a los finalizadores de las
tres clases automticamente y en orden, desde la ms derivada hasta la menos derivada.
class First
{
~First()
{
System.Diagnostics.Trace.WriteLine("First's destructor is called.");
}
}
class TestDestructors
{
static void Main()
{
Third t = new Third();
}
}
/* Output (to VS Output Window):
Third's destructor is called.
Second's destructor is called.
First's destructor is called.
*/
Vea tambin
IDisposable
Gua de programacin de C#
Constructores
Recoleccin de elementos no utilizados
Inicializadores de objeto y de coleccin (Gua de
programacin de C#)
03/10/2017 4 min to read Edit Online
Los inicializadores de objeto permiten asignar valores a cualquier campo o propiedad accesible de un objeto en el
momento de su creacin sin tener que invocar un constructor seguido de lneas de instrucciones de asignacin. La
sintaxis de inicializador de objetos permite especificar argumentos para un constructor u omitir los argumentos (y
la sintaxis de parntesis). En el ejemplo siguiente se muestra cmo usar un inicializador de objeto con un tipo con
nombre, Cat , y cmo invocar el constructor predeterminado. Tenga en cuenta el uso de propiedades
implementadas automticamente en la clase Cat . Para obtener ms informacin, vea Auto-Implemented
Properties (Propiedades implementadas automticamente).
class Cat
{
// Auto-implemented properties.
public int Age { get; set; }
public string Name { get; set; }
}
Los tipos annimos permiten a la clusula select de una expresin de consulta LINQ transformar objetos de la
secuencia original en objetos cuyo valor y forma pueden ser distintos de los originales. Esto resulta til si desea
almacenar solo una parte de la informacin de cada objeto en una secuencia. En el ejemplo siguiente, suponga
que un objeto del producto ( p ) contiene numerosos campos y mtodos y que solo le interesa crear una
secuencia de objetos que contenga el nombre del producto y el precio por unidad.
var productInfos =
from p in products
select new { p.ProductName, p.UnitPrice };
Al ejecutarse esta consulta, la variable productInfos incluir una secuencia de objetos a la que se puede tener
acceso en una instruccin foreach , como se muestra en este ejemplo:
foreach(var p in productInfos){...}
Cada uno de los objetos del nuevo tipo annimo tiene dos propiedades pblicas que reciben los mismos nombres
que las propiedades o campos del objeto original. Tambin puede cambiar el nombre de un campo al crear un
tipo annimo; en el ejemplo siguiente se cambia el nombre del campo UnitPrice a Price .
Inicializadores de coleccin
Los inicializadores de coleccin le permiten especificar uno o varios inicializadores de elemento al inicializar un
tipo de coleccin que implementa IEnumerable y tiene Add con la firma apropiada como un mtodo de instancia
o un mtodo de extensin. Los inicializadores de elemento pueden ser un valor simple, una expresin o un
inicializador de objeto. Si se usa un inicializador de coleccin, no es necesario especificar varias llamadas al
mtodo Add de la clase en el cdigo fuente; el compilador agrega las llamadas.
En los ejemplos siguientes se muestran dos inicializadores de coleccin simples:
El inicializador de coleccin siguiente usa inicializadores de objeto para inicializar los objetos de la clase Cat
definida en un ejemplo anterior. Observe que los inicializadores de objeto individuales se escriben entre llaves y
se separan por comas.
Puede especificar null como elemento de un inicializador de coleccin si el mtodo Add de la coleccin lo
permite.
Ejemplo
// The following code consolidates examples from the topic.
class ObjInitializers
{
class Cat
{
// Auto-implemented properties.
public int Age { get; set; }
public string Name { get; set; }
}
// Display results.
System.Console.WriteLine(cat.Name);
Vea tambin
Gua de programacin de C#
Expresiones de consulta LINQ
Tipos annimos
Cmo: Inicializar objetos usando un inicializador de
objeto (Gua de programacin de C#)
03/10/2017 2 min to read Edit Online
Puede usar inicializadores de objeto para inicializar objetos de tipo de una forma declarativa sin tener que invocar
explcitamente un constructor para el tipo.
En los siguientes ejemplos se muestra cmo usar los inicializadores de objeto con objetos con nombre. El
compilador procesa los inicializadores de objeto primero obteniendo acceso al constructor de instancia
predeterminado y despus procesando las inicializaciones de miembro. Por lo tanto, si el constructor
predeterminado se declara como private en la clase, se producir un error en los inicializadores de objeto que
requieren acceso pblico.
Debe usar un inicializador de objeto si va a definir un tipo annimo. Para obtener ms informacin, vea Cmo:
Devolver subconjuntos de propiedades de elementos en una consulta.
Ejemplo
En el siguiente ejemplo se muestra cmo inicializar un nuevo tipo StudentName usando inicializadores de objeto.
System.Console.WriteLine(student1.ToString());
System.Console.WriteLine(student1.ToString());
System.Console.WriteLine(student2.ToString());
System.Console.WriteLine(student3.ToString());
System.Console.WriteLine(student4.ToString());
}
// Output:
// Craig 0
// Craig 0
// 183
// Craig 116
}
// Properties.
public string FirstName { get; set; }
public string LastName { get; set; }
public int ID { get; set; }
Ejemplo
En el siguiente ejemplo se muestra cmo inicializar una coleccin de tipos StudentName usando un inicializador de
coleccin. Tenga en cuenta que un inicializador de coleccin es una serie de inicializadores de objeto separados por
comas.
Compilar el cdigo
Para ejecutar este cdigo, copie y pegue la clase en un proyecto de aplicacin de consola de Visual C# creado en
Visual Studio.
Vea tambin
Gua de programacin de C#
Inicializadores de objeto y coleccin
Cmo: Inicializar un diccionario con un inicializador
de coleccin (Gua de programacin de C#)
03/10/2017 1 min to read Edit Online
Un mtodo Dictionary<TKey,TValue> contains a collection of key/value pairs. Its Add acepta dos parmetros, uno
para la clave y otro para el valor. Para inicializar un mtodo Dictionary<TKey,TValue>, or any collection whose Add
que acepte varios parmetros, encierre entre llaves cada uno de los conjuntos de parmetros, como se muestra en
el ejemplo siguiente.
Ejemplo
En el ejemplo de cdigo siguiente, Dictionary<TKey,TValue> is initialized with instances of type StudentName .
class StudentName
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int ID { get; set; }
}
class CollInit
{
Dictionary<int, StudentName> students = new Dictionary<int, StudentName>()
{
{ 111, new StudentName {FirstName="Sachin", LastName="Karnik", ID=211}},
{ 112, new StudentName {FirstName="Dina", LastName="Salimzianova", ID=317}},
{ 113, new StudentName {FirstName="Andy", LastName="Ruth", ID=198}}
};
}
Observe los dos pares de llaves en cada elemento de la coleccin. Las llaves internas contienen el inicializador de
objeto para StudentName y las llaves externas contienen el inicializador para el par clave-valor que se agregar a
students Dictionary<TKey,TValue>. Por ltimo, el inicializador completo de la coleccin para el diccionario se
encierra entre llaves.
Compilar el cdigo
Para ejecutar este cdigo, copie y pegue la clase en un proyecto de aplicacin de consola de Visual C# creado en
Visual Studio. De manera predeterminada, el proyecto tiene como destino la versin 3.5 de .NET Framework y
contiene una referencia a System.Core.dll y una directiva using para System.Linq. Si faltan uno o varios de estos
requisitos del proyecto, puede agregarlos manualmente.
Vea tambin
Gua de programacin de C#
Inicializadores de objeto y coleccin
Cmo: Obtener acceso a una clase de coleccin
mediante Foreach (Gua de programacin de C#)
03/10/2017 3 min to read Edit Online
En el ejemplo de cdigo siguiente se muestra cmo se escribe una clase Collection no genrica que se puede usar
con la instruccin foreach. En el ejemplo se define una clase de tokenizador de cadenas.
NOTA
En este ejemplo se representa el procedimiento recomendado solo cuando no se puede usar una clase Collection genrica.
Para obtener un ejemplo de cmo se implementa una clase de coleccin genrica con seguridad de tipos que admita
IEnumerable<T>, vea Iteradores.
En el ejemplo, el siguiente segmento de cdigo usa la clase Tokens para dividir la frase "This is a sample sentence."
en tokens usando " " y "-" como separadores. Despus, el cdigo muestra esos tokens mediante una instruccin
foreach .
Ejemplo
Internamente, la clase Tokens usa una matriz para almacenar los tokens. Como las matrices implementan
IEnumerator y IEnumerable, el ejemplo de cdigo podra haber usado los mtodos de enumeracin de la matriz
(GetEnumerator, MoveNext, Reset y Current) en lugar de definirlos en la clase Tokens . Las definiciones de los
mtodos se incluyen en el ejemplo para clarificar cmo estn definidos y qu hace cada uno.
using System.Collections;
// Declare the Tokens class. The class implements the IEnumerable interface.
public class Tokens : IEnumerable
{
private string[] elements;
public TokenEnumerator(Tokens t)
{
this.t = t;
}
En C#, no es necesario para una clase de coleccin implementar IEnumerable y IEnumerator para que sean
compatibles con foreach . Si la clase tiene los miembros GetEnumerator, MoveNext, Reset y Current necesarios,
funcionar con foreach . Omitir las interfaces tiene la ventaja de que permite definir un tipo de valor devuelto de
Current que es ms especfico que Object. Esto proporciona seguridad de tipos.
Por ejemplo, cambie las siguientes lneas del ejemplo anterior.
Dado que Current devuelve una cadena, el compilador puede detectar cundo se usa un tipo incompatible en una
instruccin foreach , como se muestra en el cdigo siguiente.
El inconveniente de omitir IEnumerable y IEnumerator es que la clase de coleccin ya no puede interactuar con las
instrucciones foreach (o equivalentes) de otros lenguajes compatibles con Common Language Runtime.
Vea tambin
System.Collections.Generic
Referencia de C#
Gua de programacin de C#
Arrays (Matrices)
Colecciones
Tipos anidados (Gua de programacin de C#)
03/10/2017 1 min to read Edit Online
Un tipo definido en una clase o struct se denomina tipo anidado. Por ejemplo:
class Container
{
class Nested
{
Nested() { }
}
}
Con independencia de si el tipo externo es una clase o struct, los tipos anidados se establecen de manera
predeterminada en private, solo son accesibles desde su tipo contenedor. En el ejemplo anterior, la clase Nested
es inaccesible a los tipos externos.
Tambin puede especificar un modificador de acceso para definir la accesibilidad de un tipo anidado, de la manera
siguiente:
Los tipos anidados de una clase pueden ser public, protected, internal, protected internal o private.
En cambio, al definir una clase anidada protected o protected internal dentro de una clase sellada genera
una advertencia del compilador CS0628, "Nuevo miembro protegido declarado en la clase sealed".
Los tipos anidados de un struct pueden ser public, internal o private.
En el ejemplo siguiente se convierte la clase Nested en public:
class Container
{
public class Nested
{
Nested() { }
}
}
El tipo anidado o interno puede tener acceso al tipo contenedor o externo. Para tener acceso al tipo contenedor,
pselo como un argumento al constructor del tipo anidado. Por ejemplo:
public Nested()
{
}
public Nested(Container parent)
{
this.parent = parent;
}
}
}
Un tipo anidado tiene acceso a todos los miembros que estn accesibles para el tipo contenedor. Puede tener
acceso a los miembros privados y protegidos del tipo contenedor, incluidos los miembros protegidos heredados.
En la declaracin anterior, el nombre completo de la clase Nested es Container.Nested . Este es el nombre que se
utiliza para crear una instancia nueva de la clase anidada, de la siguiente manera:
Vea tambin
Gua de programacin de C#
Clases y structs
Modificadores de acceso
Constructores
Clases y mtodos parciales (Gua de programacin de
C#)
03/10/2017 7 min to read Edit Online
Es posible dividir la definicin de una clase o un struct, una interfaz o un mtodo en dos o ms archivos de cdigo
fuente. Cada archivo de cdigo fuente contiene una seccin de la definicin de tipo o mtodo, y todos los
elementos se combinan cuando se compila la aplicacin.
Clases parciales
Es recomendable dividir una definicin de clase en varias situaciones:
Cuando se trabaja con proyectos grandes, el hecho de repartir una clase entre archivos independientes
permite que varios programadores trabajen en ella al mismo tiempo.
Cuando se trabaja con cdigo fuente generado automticamente, se puede agregar cdigo a la clase sin
tener que volver a crear el archivo de cdigo fuente. Visual Studio usa este enfoque al crear formularios
Windows Forms, cdigo de contenedor de servicio Web, etc. Puede crear cdigo que use estas clases sin
necesidad de modificar el archivo creado por Visual Studio.
Para dividir una definicin de clase, use el modificador de palabra clave partial, como se muestra aqu:
La palabra clave partial indica que se pueden definir en el espacio de nombres otros elementos de la clase, la
estructura o la interfaz. Todos los elementos deben usar la palabra clave partial . Todos los elementos deben estar
disponibles en tiempo de compilacin para formar el tipo final. Todos los elementos deben tener la misma
accesibilidad, como public , private , etc.
Si algn elemento se declara abstracto, todo el tipo se considera abstracto. Si algn elemento se declara sellado,
todo el tipo se considera sellado. Si algn elemento declara un tipo base, todo el tipo hereda esa clase.
Todos los elementos que especifiquen una clase base deben coincidir, pero los elementos que omitan una clase
base heredan igualmente el tipo base. Los elementos pueden especificar diferentes interfaces base, y el tipo final
implementa todas las interfaces enumeradas por todas las declaraciones parciales. Todas las clases, structs o
miembros de interfaz declarados en una definicin parcial estn disponibles para todos los dems elementos. El
tipo final es la combinacin de todos los elementos en tiempo de compilacin.
NOTA
El modificador partial no est disponible en declaraciones de delegado o enumeracin.
En el ejemplo siguiente se muestra que los tipos anidados pueden ser parciales, incluso si el tipo en el que estn
anidados no es parcial.
class Container
{
partial class Nested
{
void Test() { }
}
partial class Nested
{
void Test2() { }
}
}
En tiempo de compilacin, se combinan los atributos de definiciones de tipo parcial. Por ejemplo, consideremos las
siguientes declaraciones:
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
A continuacin se indican los elementos que se combinan de todas las definiciones de tipo parcial:
comentarios XML
interfaces
atributos de parmetro de tipo genrico
class (atributos)
miembros
Por ejemplo, consideremos las siguientes declaraciones:
Restricciones
Debe seguir varias reglas al trabajar con definiciones de clase parcial:
Todas las definiciones de tipo parcial que van a formar parte del mismo tipo deben modificarse con
partial . Por ejemplo, las declaraciones de clase siguientes generan un error:
El modificador partial solo puede aparecer inmediatamente antes de las palabras clave class , struct o
interface .
Se permiten tipos parciales anidados en definiciones de tipo parcial, como se muestra en el ejemplo
siguiente:
Todas las definiciones de tipo parcial que van a formar parte del mismo tipo deben definirse en el mismo
ensamblado y en el mismo mdulo (archivo .exe o .dll). Las definiciones parciales no pueden abarcar varios
mdulos.
El nombre de clase y los parmetros de tipo genrico deben coincidir en todas las definiciones de tipo
parcial. Los tipos genricos pueden ser parciales. Cada declaracin parcial debe usar los mismos nombres
de parmetro en el mismo orden.
Las siguientes palabras clave son opcionales en una definicin de tipo parcial, pero si estn presentes la
definicin, no pueden entrar en conflicto con las palabras clave especificadas en otra definicin parcial para
el mismo tipo:
public
private
protected
internal
abstract
sealed
clase base
modificador new (elementos anidados)
restricciones genricas
Para obtener ms informacin, vea Restricciones de tipos de parmetros.
Ejemplo 1
Descripcin
En el ejemplo siguiente, los campos y el constructor de la clase, CoOrds , se declaran en una definicin de clase
parcial y el miembro PrintCoOrds se declara en otra definicin de clase parcial.
Cdigo
class TestCoOrds
{
static void Main()
{
CoOrds myCoOrds = new CoOrds(10, 15);
myCoOrds.PrintCoOrds();
Ejemplo 2
Descripcin
En el ejemplo siguiente se muestra que tambin se pueden desarrollar structs e interfaces parciales.
Cdigo
partial interface ITest
{
void Interface_Test();
}
partial struct S1
{
void Struct_Test() { }
}
partial struct S1
{
void Struct_Test2() { }
}
Mtodos Partial
Una clase o struct parcial puede contener un mtodo parcial. Un elemento de la clase contiene la firma del mtodo.
Se puede definir una implementacin opcional en el mismo elemento o en otro. Si no se proporciona la
implementacin, el mtodo y todas las llamadas al mtodo se quitan en tiempo de compilacin.
Los mtodos parciales permiten que el implementador de un elemento de una clase defina un mtodo, similar a un
evento. El implementador del otro elemento de la clase puede decidir si quiere implementar el mtodo o no. Si el
mtodo no se implementa, el compilador quita la firma del mtodo y todas las llamadas al mtodo. Las llamadas al
mtodo, incluidos los resultados que se produciran por la evaluacin de los argumentos de las llamadas, no tienen
efecto en tiempo de ejecucin. Por lo tanto, el cdigo de la clase parcial puede usar libremente un mtodo parcial,
incluso si no se proporciona la implementacin. No se producir ningn error en tiempo de compilacin o en
tiempo de ejecucin si se llama al mtodo pero no se implementa.
Los mtodos parciales son especialmente tiles para personalizar el cdigo generado. Permiten reservar un
nombre y firma de mtodo de modo que el cdigo generado pueda llamar al mtodo, pero el desarrollador decide
si se implementa el mtodo. De manera muy similar a como hacen las clases parciales, los mtodos parciales
permiten que el cdigo creado por un generador de cdigo y el cdigo creado por un desarrollador humano
funcionen juntos sin costos en tiempo de ejecucin.
Una declaracin de mtodo parcial consta de dos elementos: la definicin y la implementacin. Pueden encontrarse
en elementos independientes de una clase parcial o en el mismo elemento. Si no hay ninguna declaracin de
implementacin, el compilador optimiza tanto la declaracin de definicin como todas las llamadas al mtodo.
// Definition in file1.cs
partial void onNameChanged();
// Implementation in file2.cs
partial void onNameChanged()
{
// method body
}
Las declaraciones de mtodo parcial deben comenzar con la palabra clave contextual partial y el mtodo
debe devolver void.
Los mtodos parciales pueden tener parmetros ref, pero no parmetros out.
Los mtodos parciales son implcitamente private y, por tanto, no pueden ser virtual.
Los mtodos parciales no pueden ser extern, ya que la presencia del cuerpo determina si son de definicin o
de implementacin.
Los mtodos parciales pueden tener modificadores static y unsafe.
Los mtodos parciales pueden ser genricos. Las restricciones se colocan en la declaracin de mtodo
parcial de definicin y opcionalmente pueden repetirse en el de implementacin. Los nombres del
parmetro y del parmetro de tipo no tienen que ser iguales en la declaracin de implementacin y en la
declaracin de definicin.
Puede crear un delegado para un mtodo parcial que se ha definido e implementado, pero no para un
mtodo parcial que solo se ha definido.
Vea tambin
Gua de programacin de C#
Clases
Structs
Interfaces
partial (Tipos)
Tipos annimos (Gua de programacin de C#)
03/10/2017 4 min to read Edit Online
Los tipos annimos son una manera cmoda de encapsular un conjunto de propiedades de solo lectura en un
nico objeto sin tener que definir primero un tipo explcitamente. El compilador genera el nombre del tipo y no
est disponible en el nivel de cdigo fuente. El compilador deduce el tipo de cada propiedad.
Para crear tipos annimos, use el operador new con un inicializador de objeto. Para obtener ms informacin
sobre los inicializadores de objeto, vea Inicializadores de objeto y coleccin (Gua de programacin de C#).
En el ejemplo siguiente se muestra un tipo annimo que se inicializa con dos propiedades llamadas Amount y
Message .
// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount + v.Message);
Los tipos annimos suelen usarse en la clusula select de una expresin de consulta para devolver un
subconjunto de las propiedades de cada objeto en la secuencia de origen. Para obtener ms informacin sobre
consultas, vea Expresiones de consulta LINQ.
Los tipos annimos contienen una o varias propiedades pblicas de solo lectura. No es vlido ningn otro tipo de
miembros de clase, como mtodos o eventos. La expresin que se usa para inicializar una propiedad no puede ser
null , una funcin annima o un tipo de puntero.
El escenario ms habitual es inicializar un tipo annimo con propiedades de otro tipo. En el siguiente ejemplo, se
da por hecho que existe una clase con el nombre Product . La clase Product incluye las propiedades Color y
Price , junto con otras propiedades que no son de su inters. La variable products es una coleccin de objetos
Product . La declaracin de tipo annimo comienza con la palabra clave new . La declaracin inicializa un nuevo
tipo que solo usa dos propiedades de Product . Esto hace que la consulta devuelva una cantidad de datos menor.
Si no especifica los nombres de miembro en el tipo annimo, el compilador da a los miembros de tipo annimo el
mismo nombre que la propiedad que se usa para inicializarlos. Debe proporcionar un nombre para una
propiedad que se est inicializando con una expresin, como se muestra en el ejemplo anterior. En el siguiente
ejemplo, los nombres de las propiedades del tipo annimo son Color y Price .
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
Normalmente, cuando se usa un tipo annimo para inicializar una variable, la variable se declara como variable
local con tipo implcito mediante var. El nombre del tipo no se puede especificar en la declaracin de la variable
porque solo el compilador tiene acceso al nombre subyacente del tipo annimo. Para obtener ms informacin
sobre var , vea Variables locales con asignacin implcita de tipos.
Puede crear una matriz de elementos con tipo annimo combinando una variable local con tipo implcito y una
matriz con tipo implcito, como se muestra en el ejemplo siguiente.
var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};
Comentarios
Los tipos annimos son tipos class que derivan directamente de object y que no se pueden convertir a ningn
tipo excepto object. El compilador proporciona un nombre para cada tipo annimo, aunque la aplicacin no pueda
acceder a l. Desde el punto de vista de Common Language Runtime, un tipo annimo no es diferente de otros
tipos de referencia.
Si dos o ms inicializadores de objeto annimo en un ensamblado especifican una secuencia de propiedades que
estn en el mismo orden y que tienen los mismos nombres y tipos, el compilador trata el objeto como instancias
del mismo tipo. Comparten la misma informacin de tipo generada por el compilador.
No se puede declarar que un campo, una propiedad, un evento o el tipo de valor devuelto de un mtodo tengan
un tipo annimo. De forma similar, no se puede declarar que un parmetro formal de un mtodo, propiedad,
constructor o indizador tenga un tipo annimo. Para pasar un tipo annimo, o una coleccin que contiene tipos
annimos, como un argumento a un mtodo, puede declarar el parmetro como objeto de tipo. Sin embargo, al
hacerlo se invalida el propsito del tipado fuerte. Si tiene que almacenar resultados de consulta o pasarlos fuera
del lmite del mtodo, considere la posibilidad de usar un struct o una clase con nombre normal en lugar de un
tipo annimo.
Como los mtodos Equals y GetHashCode de tipos annimos se definen en trminos de los mtodos Equals y
GetHashCode de las propiedades, dos instancias del mismo tipo annimo son iguales solo si todas sus
propiedades son iguales.
Vea tambin
Gua de programacin de C#
Inicializadores de objeto y de coleccin
Introduccin a LINQ en C#
Expresiones de consulta LINQ
Cmo: Devolver subconjuntos de propiedades de
elementos en una consulta (Gua de programacin de
C#)
03/10/2017 1 min to read Edit Online
Use un tipo annimo en una expresin de consulta cuando se cumplan estas dos condiciones:
Solo quiere algunas de las propiedades de cada elemento de origen.
No es necesario almacenar los resultados de la consulta fuera del mbito del mtodo en el que se ejecuta la
consulta.
Si solo quiere devolver una propiedad o campo de cada elemento de origen, puede usar simplemente el operador
de punto en la clusula select . Por ejemplo, para devolver solo el ID de cada student , escriba la clusula
select como sigue:
select student.ID;
Ejemplo
En el ejemplo siguiente se muestra cmo usar un tipo annimo para devolver solo un subconjunto de las
propiedades de cada elemento de origen que coincida con la condicin especificada.
Tenga en cuenta que, si no se especifica ningn nombre, el tipo annimo usa los nombres del elemento de origen
para sus propiedades. Para asignar nombres nuevos a las propiedades del tipo annimo, escriba la instruccin
select como sigue:
select new { First = student.FirstName, Last = student.LastName };
Compilar el cdigo
Para ejecutar este cdigo, copie y pegue la clase en un proyecto de aplicacin de consola de Visual C# creado en
Visual Studio. De forma predeterminada, este proyecto tiene como destino la versin 3.5 de .NET Framework, y
tendr una referencia a System.Core.dll y una directiva using para System.Linq. Si faltan uno o varios de estos
requisitos del proyecto, se pueden agregar manualmente.
Vea tambin
Gua de programacin de C#
Tipos annimos
Expresiones de consulta LINQ