Professional Documents
Culture Documents
U1 - NET Avanzado
U1 - NET Avanzado
OPTATIVO IV
.NET AVANZADO
INTRODUCCIÓN
C# es un lenguaje elegante, con seguridad de tipos y orientado a objetos, que permite a los de-
sarrolladores crear una gran variedad de aplicaciones seguras y sólidas que se ejecutan en .NET
Framework. Puede usar C# para crear aplicaciones cliente de Windows, servicios web XML, com-
ponentes distribuidos, aplicaciones cliente-servidor, aplicaciones de base de datos y muchas, mu-
chas más cosas. Visual C# proporciona un editor de código avanzado, prácticos diseñadores de
interfaz de usuario, un depurador integrado y muchas otras herramientas que facilitan el desarrollo
de aplicaciones basadas en el lenguaje C# y .NET Framework.
Lenguaje C#
IdLa sintaxis de C# es muy expresiva, pero también sencilla y fácil de aprender. Cualquier persona
familiarizada con C, C++ o Java, reconocerá al instante la sintaxis de llaves de C#. Los desarrolla-
dores que conocen cualquiera de estos lenguajes puede em-pezar normalmente a trabajar en C#
de forma productiva en un espacio muy corto de tiempo. La sintaxis de C# simplifica muchas de
las complejidades de C++ y proporciona características eficaces, como tipos de valor que aceptan
valores NULL, enumeraciones, delegados, expresiones lambda y acceso directo a memoria, que
no se encuentran en Java. C# admite métodos y tipo genéricos, que proporcionan una mayor se-
guridad de tipos y rendimiento, e iteradores, que permiten a los implementadores de clases de co-
lecciones definir comportamientos de iteración personalizados que son fáciles de usar por el código
de cliente. Las expresiones Language-Integrated Query (LINQ) convierten la consulta fuertemente
tipada en una construcción de lenguaje de primera clase.
En cuanto lenguaje orientado a objetos, C# admite los conceptos de encapsula-ción, herencia y po-
limorfismo. Todas las variables y métodos, incluido el método Main, el punto de entrada de la apli-
cación, se encapsulan dentro de las definiciones de clase. Una clase puede heredar directamente
de una clase primaria, pero puede implementar cualquier número de interfaces. Los métodos que
invalidan los métodos virtuales en una clase primaria requieren la palabra clave override como una
manera de evitar redefini-ciones accidentales. En C#, un struct es como una clase sencilla; es un
tipo asignado en la pila que puede implementar interfaces pero que no admite herencia.
1
Unidad l
Además de estos principios básicos orientados a objetos, C# facilita el desarrollo de
componentes de software mediante varias construcciones de lenguaje innovadoras,
incluidas las siguientes:
Si tiene que interactuar con otro software de Windows, como objetos COM o ar-chivos DLL nativos
de Win32, se puede hacer en C# mediante un proceso denominado “Interoperabilidad”. La intero-
perabilidad permite que los programas de C# hagan casi todo lo que puede hacer una aplicación
C++ nativa. C# admite incluso el uso de punte-ros y el concepto de código “no seguro” en los casos
en los que el acceso directo a me-moria es absolutamente crítico.
Las matrices son muy útiles para crear y trabajar con un número fijo de objetos fuertemente tipados.
Las colecciones proporcionan una manera más flexible de trabajar con grupos de objetos. A dife-
rencia de las matrices, el grupo de objetos con el que trabaja puede au-mentar y reducirse de ma-
nera dinámica a medida que cambian las necesidades de la aplicación. Para algunas colecciones,
se puede asignar una clave a cualquier objeto que incluya en la colección para, de este modo,
recuperar rápidamente el objeto con la clave.
Una colección es una clase, por lo que se debe declarar una instancia de la clase para poder agre-
gar elementos a dicha colección.
Si la colección contiene elementos de un solo tipo de datos, se puede usar una de las clases del
espacio de nombres System.Collections.Generic. Una colección genérica cumple la seguridad de
tipos para que ningún otro tipo de datos se pueda agregar a ella. Cuando se recupera un elemento
de una colección genérica, no se tiene que determinar su tipo de datos ni realizar conversiones.
Matrices
Se puede almacenar varias variables del mismo tipo en una estructura de datos de matriz. Se pue-
de declarar una matriz mediante la especificación del tipo de sus ele-mentos.
type[] arrayName;
Los ejemplos de esta sección usan la clase genérica List<T>, que le permite tra-bajar con una lista
de objetos fuertemente tipados.
En el ejemplo siguiente se crea una lista de cadenas y luego se recorre en itera-ción las cadenas
mediante una instrucción foreach.
// un inicializador de colecciones.
var paises = new List<string> { “Argentina”, “Brasil”, “Inglaterra”, “Paraguay” };
Tipos de colecciones
.NET Framework proporciona muchas colecciones comunes. Cada tipo de co-lección está diseña-
do para un fin específico.
Clases System.Collections.Generic.
Clases System.Collections.Concurrent .
Clases System.Collections.
System.Collections.Generic
Se puede crear una colección genérica mediante una de las clases del espacio de nombres Sys-
tem.Collections.Generic. Una colección genérica es útil cuando todos los elementos de la colección
tienen el mismo tipo. Una colección genérica exige el esta-blecimiento de fuertes tipos al permitir
agregar solo los tipos de datos deseados.
En la tabla siguiente se enumeran algunas de las clases usadas con frecuencia del espacio de
nombres System.Collections.Generic:
Clase Descripción
Dictionary<TKey,TValue> Representa una colección de pares de clave y valor que se organizan
según la clave.
List<T> Representa una lista de objetos a los que puede tener acceso el índice. Proporciona
métodos para buscar, ordenar y modificar listas.
Queue<T> Representa una colección de objetos de primeras entradas, primeras salidas (FIFO).
SortedList<TKey,TValue> Representa una colección de pares clave-valor que se ordenan por cla-
ves según la implementación de IComparer<T> asociada.
Stack<T> Representa una colección de objetos de últimas en-tradas, primeras salidas
Delegado
Un delegado es un tipo que representa referencias a métodos con una lista de pa-rámetros deter-
minada y un tipo de valor devuelto. Cuando se crea una instancia de un delegado, puede asociar
su instancia a cualquier método mediante una signatura compa-tible y un tipo de valor devuelto. Se
puede invocar (o llamar) al método a través de la instancia del delegado.
5
Unidad l
Los delegados se utilizan para pasar métodos como argumentos a otros méto-dos. Los controla-
dores de eventos no son más que métodos que se invocan a través de delegados. Por ejemplo,
cuando se crea un método personalizado y una clase, como un control de Windows, se podrá lla-
mar al método cuando se produzca un determinado evento. En el siguiente ejemplo se muestra una
declaración de delegado:
public delegate int RealizarCalculo(int x, int y);
Cualquier método de cualquier clase o struct accesible que coincida con el tipo de delegado se
puede asignar al delegado. El método puede ser estático o de instan-cia. Esto permite cambiar las
llamadas a métodos mediante programación y agregar nuevo código a las clases existentes.
Esta capacidad de hacer referencia a un método como parámetro hace que los delegados sean
idóneos para definir métodos de devolución de llamada. Por ejemplo, una referencia a un método
que compara dos objetos podría pasarse como argumento a un algoritmo de ordenación. Dado que
el código de comparación está en un procedi-miento independiente, el algoritmo de ordenación se
puede escribir de manera más ge-neral.
Los delegados son como los punteros de función de C++, pero tienen seguridad de tipos.
Los delegados permiten pasar los métodos como parámetros.
Los delegados pueden usarse para definir métodos de devolución de llamada.
Los delegados pueden encadenarse entre sí; por ejemplo, se puede llamar a varios métodos
en un solo evento.
No es necesario que los métodos coincidan exactamente con el tipo de delega-do.
La versión 2.0 de C# presentó el concepto de Métodos anónimos, los cuales permiten pasar
bloques de código como parámetros en lugar de un método defi-nido por separado. En C# 3.0 se
presentaron las expresiones lambda como una manera más concisa de escribir bloques de códi-
go alineado. Tanto los métodos anónimos como las expresiones lambda (en ciertos contextos) se
compilan en ti-pos de delegado. Juntas, estas características se conocen ahora como funciones
anónimas.
Un delegado es un tipo que encapsula de forma segura un método, similar a un pun-tero de función
en C y C++. A diferencia de los punteros de función de C, los delegados están orientados a objetos,
proporcionan seguridad de tipos y son seguros. El tipo de un delegado se define por el nombre del
delegado. En el ejemplo siguiente, se declara un delegado denominado Del que puede encapsular
un método que toma una string como argumento y devuelve void:
public delegate void Del(string message);
Normalmente, un objeto delegado se construye al proporcionar el nombre del método que el de-
legado encapsulará o con un método anónimo. Una vez que se crea una instan-cia de delegado,
el delegado pasará al método una llamada de método realizada al dele-gado. Los parámetros
Por ejemplo:
// Crear un método para el delegado.
public static void DelegateMethod(string messa-
ge)
{
System.Console.WriteLine(message);
}
// Instanciar el delegado.
Del handler = DelegateMethod;
// Lllamada al delegado.
handler(“Hola Mundo”);
El número es: 3
Si se usa el delegado como abstracción, no es necesario que MethodWithCallback llame directa-
mente a la consola —no tiene que estar diseñado pensando en una consola—. Lo que MethodWith-
Callback hace es simplemente preparar una cadena y pasarla a otro método. Esto es especialmen-
te eficaz, puesto que un método delegado puede utilizar cualquier número de parámetros.
Cuando se crea un delegado para encapsular un método de instancia, el delegado hace referencia
tanto a la instancia como al método. Un delegado no tiene conocimiento del tipo de instancia —
aparte del método al que encapsula—, por lo que un delegado puede hacer referencia a cualquier
tipo de objeto siempre que haya un método en ese objeto que coincida con la signatura del dele-
gado. Cuando se crea un delegado para encapsular un método estático, solo hace referencia al
método. Se deben tener en cuenta las siguientes consideraciones:
public class MethodClass
{
public void Method1(string message) { }
public void Method2(string message) { }
}
Junto con el DelegateMethod estático mostrado anteriormente, ahora tenemos tres métodos que se
pueden encapsularse mediante una instancia de Del.
Un delegado puede llamar a más de un método cuando se invoca. Esto se conoce como multidi-
fusión. Para agregar un método adicional a la lista de métodos del delega-do —la lista de invoca-
ción—, simplemente es necesario agregar dos delegados mediante los operadores de adición o
asignación y suma (‘+’ o ‘+=’). Por ejemplo:
MethodClass obj = new MethodClass();
Del d1 = obj.Method1;
Del d2 = obj.Method2;
Del d3 = DelegateMethod;
7
Unidad l
Por ejemplo:
//Eliminar Method1
allMethodsDelegate -= d1;
Los delegados con más de un método en su lista de invocación derivan de MulticastDelegate, que
es una subclase de System.Delegate. El código anterior funciona en ambos casos porque las dos
clases admiten GetInvocationList.
Los delegados de multidifusión se utilizan mucho en el control de eventos. Los objetos de origen
de evento envían notificaciones de evento a los objetos de destinatario que se han registrado para
recibir ese evento. Para suscribirse a un evento, el destinatario crea un método diseñado para con-
trolar el evento; a continuación, crea a un delegado para dicho método y pasa el delegado al origen
de eventos. El origen llama al delegado cuando se produce el evento. Después, el delegado llama
al método que controla los eventos en el destinatario y entrega los datos del evento. El origen del
evento define el tipo de delegado para un evento determinado.
Expresiones lambda
Una expresión lambda es una función anónima que se puede usar para crear ti-pos delegados o de
árbol de expresión. Al utilizar expresiones lambda, puede escribir funciones locales que se pueden
pasar como argumentos o devolverse como valor de llamadas de función. Las expresiones lambda
son especialmente útiles para escribir ex-presiones de consulta LINQ.
Para crear una expresión lambda, especifique los parámetros de entrada (si exis-ten) a la izquierda
del operador lambda => y coloque el bloque de expresiones o de ins-trucciones en el otro lado. Por
8
Unidad l
ejemplo, la expresión lambda x => x * x especifica un parámetro denominado x y devuelve el valor
de x cuadrado. Puede asignar esta expre-sión a un tipo delegado, como se muestra en el ejemplo
siguiente:
delegate int del(int i);
static void Main(string[] args)
{
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
}
Para crear un tipo de árbol de expresión:
using System.Linq.Expressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Expression<del> myET = x => x * x;
}
}
}
El operador => tiene la misma prioridad que la asignación (=) y es asociativa a la derecha (vea la
sección “Asociatividad” del artículo Operadores).
Las lambdas se usan en consultas LINQ basadas en métodos como argumentos de los métodos de
operador de consulta estándar, tales como Where.
Cuando se utiliza la sintaxis de método para llamar al método Where en la cla-se Enumerable
(como se hace en LINQ to Objects y LINQ to XML), el parámetro es un tipo delegado System.Fun-
c<T,TResult>. Una expresión lambda constituye la manera más práctica de crear ese delegado.
Cuando se llama al mismo método en, por ejemplo, la clase System.Linq.Queryable (como se hace
en LINQ to SQL), el tipo de parámetro es System.Linq.Expressions.Expression<Func>, donde Func
es uno de los delegados de Func, que tiene hasta dieciséis parámetros de entrada. De nuevo, una
expresión lambda constituye una manera muy concisa de construir ese árbol de expresión. Las
lambdas permiten que las llamadas a Where tengan un aspecto similar, aunque, de hecho, el tipo
de objeto creado a partir de la lambda sea diferente.
En el ejemplo anterior, observe que la signatura de delegado tiene un parámetro de entrada con
tipo implícito inty devuelve un int. La expresión lambda se puede convertir en un delegado de ese
tipo porque también tiene un parámetro de entrada (x) y un valor devuelto que el compilador puede
convertir implícitamente al tipo int. (La inferencia de tipos se analiza con más detalle en las seccio-
nes siguientes). Cuando el delegado se invoca mediante un parámetro de entrada de 5, devuelve
un resultado de 25.
Las lambdas no se permiten en el lado izquierdo del operador is o as.
Todas las restricciones que se aplican a los métodos anónimos también se aplican a las expresio-
nes lambda.
Lambdas de expresión
Una expresión lambda con una expresión en el lado derecho del operador => se denomina lambda
de expresión. Las lambdas de expresión se usan ampliamente en la construcción de árboles de
expresión. Una expresión lambda devuelve el resultado de evaluar la condición y tiene la siguiente
forma:
(x, y) => x == y
9
Unidad l
A veces, es difícil o imposible que el compilador deduzca los tipos de entra-da. Cuando ocurre esto,
los tipos se pueden especificar explícitamente como se muestra en el ejemplo siguiente:
(int x, string s) => s.Length > x
Para especificar cero parámetros de entrada, utilice paréntesis vacíos:
() => SomeMethod()
Observe en el ejemplo anterior que el cuerpo de una lambda de expresión puede estar compuesto
de una llamada a método. Sin embargo, si crea árboles de expresiones que se evalúan fuera de
.NET Framework, por ejemplo, en SQL Server, no debe utilizar llamadas a métodos en expresiones
lambda. Los métodos no tendrán ningún significado fuera del contexto de .NET Common Language
Runtime.
Lambdas de instrucción
Una lambda de instrucción es similar a un lambda de expresión, salvo que las instrucciones se
encierran entre llaves:
(parámetros de entrada) => {instrucción; }
El cuerpo de una lambda de instrucción puede estar compuesto de cualquier nú-mero de instruccio-
nes; sin embargo, en la práctica, generalmente no hay más de dos o tres.
delegate void TestDelegate(string s);
TestDelegate del = n => { string s = n + “ World”;
Console.WriteLine(s); };
Las lambdas de instrucción, como los métodos anónimos, no se pueden utilizar para crear árboles
de expresión.
Lambdas asincrónicas
Puede crear fácilmente expresiones e instrucciones lambda que incorporen el procesamiento asin-
crónico mediante las palabras clave async y await. Por ejemplo, en el siguiente ejemplo de formu-
larios Windows Forms se incluye un controlador de eventos que llama y espera un método asincró-
nico, ExampleMethodAsync.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Se pueden crear instancias del delegado como Func<int,bool> myFunc , don-de int es un pará-
metro de entrada y bool es el valor devuelto. El valor devuelto siem-pre se especifica en el último
parámetro de tipo. Func<int, string, bool> define un delegado con dos parámetros de entrada, int y
string, y un tipo de valor devuelto de bool. El siguiente delegado Func , cuando se invoca, devolverá
true o false para indicar si el parámetro de entrada es igual a 5:
Func<int, bool> myFunc = x => x == 5;
El compilador puede deducir el tipo del parámetro de entrada o también se puede especificar explí-
citamente. Esta expresión lambda particular cuenta aquellos enteros (n) que divididos por dos dan
como resto 1.
La siguiente línea de código produce una secuencia que contiene todos los ele-mentos de la matriz
numbers que aparecen a la izquierda del 9, ya que ese es el primer número de la secuencia que no
cumple la condición:
Al escribir lambdas, no tiene por qué especificar un tipo para los parámetros de entrada, ya que el
compilador puede deducir el tipo según el cuerpo de lambda, el tipo de delegado del parámetro y
otros factores que se describen en la especificación del lenguaje C#. Para la mayoría de los ope-
radores de consulta estándar, la primera entrada es el tipo de los elementos en la secuencia de
origen. Por consiguiente, si está realizando una consulta sobre un IEnumerable<Customer>, se
deducirá que la variable de entrada será un objeto Customer , lo cual significa que se podrá tener
acceso a sus métodos y propiedades:
11
Unidad l
customers.Where(c => c.City == “London”);
Las expresiones lambda, en sí mismas, no tienen tipo, ya que el sistema de tipos comunes no tiene
ningún concepto intrínseco de “expresión lambda”. Sin embargo, a veces resulta práctico hablar
coloquialmente del “tipo” de una expresión lambda. En estos casos, el tipo hace referencia al tipo
del delegado o el tipo de Expression en el que se convierte la expresión lambda.
class Test
{
D del;
D2 del2;
public void TestMethod(int input)
{
int j = 0;
// Salida: j = 10 b = True
Console.WriteLine(“j = {0}. b = {1}”, j, boolResult);
}
// Salida: True
Console.WriteLine(result);
Console.ReadKey();
}
}
Las reglas siguientes se aplican al ámbito de las variables en las expresiones lambda:
• Una variable capturada no se recolectará como elemento no utilizado hasta que el delegado
que hace referencia a ella sea elegible para la recolección de elementos no utilizados.
• Las variables introducidas en una expresión lambda no son visibles en el método externo.
12
Unidad l
• Una expresión lambda no puede capturar directamente un paráme-tro in, ref o outdesde un
método que la englobe.
• Una instrucción return en una expresión lambda no hace que el método que la engloba de-
vuelva un valor.
• Una expresión lambda no puede contener una instruc-ción goto , break o continue que esté
dentro de la función lambda si el des-tino de la instrucción de salto está fuera del bloque. También
es un error utilizar una instrucción de salto fuera del bloque de la función lambda si el destino está
dentro del bloque.
Indexers
Los indizadores permiten indizar las instancias de una clase o struct como matri-ces. El valor indi-
zado se puede establecer o recuperar sin especificar explícitamente un miembro de tipo o de ins-
tancia. Son similares a propiedades, excepto en que sus des-criptores de acceso usan parámetros.
En el ejemplo siguiente se define una clase genérica con métodos de descriptor de acceso get y set
sencillo para asignar y recuperar valores. La clase Program crea una instancia de esta clase para
almacenar cadenas.
using System;
class SampleCollection<T>
{
private T[] arr = new T[100];
public T this[int i]
{
get { return arr[i]; }
set { arr[i] = value; }
}
}
class Program
{
static void Main()
{
var stringCollection = new SampleCollection<string>();
stringCollection[0] = “Hola, Mundo”;
Console.WriteLine(stringCollection[0]);
}
}
// Salida:
// Hola, Mundo.
class SampleCollection<T>
{
private T[] arr = new T[100];
int nextIndex = 0;
13
Unidad l
}
class Program
{
static void Main()
{
var stringCollection = new SampleCollection<string>();
stringCollection.Add(“Hola, Mundo”);
System.Console.WriteLine(stringCollection[0]);
}
}
// Salida:
// Hola, Mundo.
Tenga en cuenta que => presenta el cuerpo de la expresión y que la palabra cla-ve get no se utiliza.
A partir de C# 7.0, los descriptores de acceso get y set se pueden implementar como miembros
con forma de expresión. En este caso, sí deben utilizarse las palabras clave get y set. Por ejemplo:
using System;
class SampleCollection<T>
{
private T[] arr = new T[100];
public T this[int i]
{
get => arr[i];
set => arr[i] = value;
}
}
class Program
{
static void Main()
{
var stringCollection = new SampleCollection<string>();
stringCollection[0] = “Hola, Mundo.”;
Console.WriteLine(stringCollection[0]);
}
}
// Salida:
// Hola, Mundo.
• Los indizadores permiten indizar objetos de manera similar a como se hace con las matrices.
• Un descriptor de acceso get devuelve un valor. Un descriptor de acce-so set asigna un valor.
• La palabra clave this se usa para definir los indizadores.
• La palabra clave value se usa para definir el valor asignado por el indizador set.
• Los indizadores no tienen que ser indizados por un valor entero; depende de us-ted
cómo definir el mecanismo de búsqueda concreto.
• Los indizadores se pueden sobrecargar.
• Los indizadores pueden tener más de un parámetro formal, por ejemplo, al tener acceso a
una matriz bidimensional.
Los indexadores son una comodidad sintáctica que le permiten crear una clase, un struct o una in-
terfaz a los que pueden acceder las aplicaciones cliente simplemente como una matriz. Los indexa-
dores se implementan con más frecuencia en tipos cuyo propósito principal consiste en encapsular
una matriz o colección interna. Por ejemplo, suponga que tiene una clase denominada TempRecord
que representa la temperatura en grados Fahrenheit que se registra en 10 momentos diferentes
durante un período de 24 horas. La clase contiene una matriz denominada “temps” de tipo float
para representar la temperatura y un DateTime que representa la fecha en que se han registrado
las tempe-raturas. Si implementa un indexador en esta clase, los clientes pueden tener acceso a
las temperaturas en una instancia de TempRecord como float temp = tr[4] en lugar de como float
14
Unidad l
temp = tr.temps[4]. La notación del indexador no solo simplifica la sin-taxis para las aplicaciones
cliente; también hace que la clase y su finalidad sean más intuitivas para que las conozcan otros
desarrolladores.
Para declarar un indexador en una clase o un struct, use la palabra clave this, como en este ejem-
plo:
Un valor de indexador no está clasificado como una variable; por tanto, no se puede pasar un valor
de indexador como un parámetro ref u out.
Para proporcionar el indexador con un nombre que puedan usar otros lenguajes, use un atributo
name en la declaración. Por ejemplo:
[System.Runtime.CompilerServices.IndexerName(“TheItem”)]
public int this [int index] // Indexer declaration
{
}
Este indexador tendrá el nombre TheItem. Si no se proporciona el atributo de nombre, Item será el
nombre predeterminado.
Ejemplo 1
En el ejemplo siguiente, se muestra cómo declarar un campo de matriz priva-da, temps, como un
indexador. El indexador permite el acceso directo a la instan-cia tempRecord[i]. La alternativa a
usar el indexador es declarar la matriz como un miembro public y tener acceso directamente a sus
miembros tempRecord.temps[i].
Tenga en cuenta que, cuando se evalúa el acceso de un indexador (por ejemplo, en una instrucción
Console.Write), se invoca al descriptor de acceso get. Por tanto, si no hay ningún descriptor de
acceso get, se produce un error en tiempo de compilación.
Código
class TempRecord
{
// Vector con valores de temperatura
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F,
61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
set
{
temps[index] = value;
}
15
Unidad l
}
}
class MainClass
{
static void Main()
{
TempRecord tempRecord = new TempRecord();
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine(“Elemento #{0} = {1}”, i, tempRecord[i]);
}
System.Console.WriteLine(“Presione una Tecla para continuar.”);
System.Console.ReadKey();
}
}
/* Salida:
Elemento #0 = 56.2
Elemento #1 = 56.7
Elemento #2 = 56.5
Elemento #3 = 58.3
Elemento #4 = 58.8
Elemento #5 = 60.1
Elemento #6 = 65.9
Elemento #7 = 62.1
Elemento #8 = 59.2
Elemento #9 = 57.5
*/
Ejemplo 2
En este ejemplo, se declara una clase que almacena los días de la semana. Se de-clara un des-
criptor de acceso get que toma una cadena, el nombre de un día, y devuel-ve el entero correspon-
diente. Por ejemplo, el domingo devolverá 0, el lunes devolverá 1, etc.
Código
class DayCollection
{
string[] days = { “Sun”, “Mon”, “Tues”, “Wed”, “Thurs”, “Fri”, “Sat” };
private int GetDay(string testDay)
{
class Program
{
static void Main(string[] args)
{
DayCollection week = new DayCollection();
System.Console.WriteLine(week[“Fri”]);
System.Console.WriteLine(week[“Made-up Day”]);
System.Console.WriteLine(“Presione una Tecla para salir.”);
System.Console.ReadKey();
}
}
// Salida: 5
Programación sólida
Hay dos formas principales en que se pueden mejorar la seguridad y confiabilidad de los
indexadores:
• Se debe establecer la accesibilidad de los descriptores de acceso get y set para que sea tan
restrictiva como sea razonable. Esto es importante para el descriptor de acceso set en particular.
BIBLIOGRAFÍA
cambiocultural.org/cultura-política/concepto-de-cultura-política
informacionporlaverdad.wordpress.com/2011/10/02/¿que-es-el-nuevo-orden-mundial.
sedici.unlp.edu.ar/bitstream/handle/10915/38737/Ponencia.pdf
www.cepal.org/es/comunicados/paises-de-la-region-adoptan-el-consenso-de-montevideo
www.eaeprogramas.es/internacionalizacion/que-son-los-mercados-emergentes
www.icps.cat/archivos/WorkingPapers
www.nexos.com.mx
www.sem-wes.org/sites/default/files/revistas/rem4_5.pdf
17