Programacion en C#

376
Programación en C# por Gorka Vicente

Transcript of Programacion en C#

Programación  en  C#  por  Gorka  Vicente  

2

Bienvenida  y  Obje6vos  Quién  soy.  Qué  conocimientos    

tengo  de  .NET.  

Introducción  a  .NET  Breve  explicación  para  aterrizar  en  este  mundo  

Temario  Programación  en  C#  

3

Definiciones  básicas  

Directrices  para  la    programación  en  C#    

Garbage  Collector  Recolector  de  basura  

Clases  y  Objetos  Clases,  Herencia,  Polimorfismo,  Interfaces  

Framework  Design  Guidelines    

Espacios  de  nombres,    clases,  constructores,    

campos  y  propiedades,    métodos  y  Lpos    

4

Patrones  de  Diseño  Breve  introducción  

Enumerados  y  colecciones  Flexibilidad  para  almacenar,  ordenar  y  gesLonar  gran  canLdad  de  datos  

 

Ensamblados,  atributos    y  reflec6on    

Bloques  de  creación  de  .NET  Framework  

Lectura    y  escritura  de  ficheros    Serialización  y  Deserialización  de  datos  

5

Excepciones  GesLón  de  excepciones  existentes  y  creación  de  nuevas  excepciones    

LINQ  y  expresiones  Lambda  Cómo  hacer  que  la  vida  del  desarrollador  sea  más  sencilla  

Delegados,  Eventos    y  Métodos  de  extensión  

Referencias  a  métodos.  Qué  hace  el  código  cuando  no  le  

estamos  observando?  

Tests  unitarios    con  MSTest  El  arte  de  medir  y  mantener  la  calidad  del  soRware  

6

Consumo  de  librerías  Consumo  de  librerías  de  terceros  de  

código  administrado  y  no  administrado  

Servicios  Windows  Aplicaciones  ejecutables  de  larga  duración  

Aplicaciones  cliente  Generación  de  aplicaciones  cliente  

para  el  consumo  de  servicios  remotos    

Otros  puntos  de  interés  Herramientas  de  profiling,  gesLón  de  librerías  mediante  Nuget,  librerías  para  logging,  etc.    

7

Sobre  mí  He  trabajado  durante  13  años  en  el  área  de  Desarrollo  de  SoRware  realizando  trabajos  de  Arquitectura  y  Desarrollo  de  aplicaciones  sobre  múlLples  plataformas  y  lenguajes.    Asimismo,  tengo  una  gran  experiencia  en  el  área  de  la  Seguridad  de  aplicaciones,  ya  que  desde  el  2004  soy  co-­‐autor  de  hdiv.org;  framework  de  Seguridad  para  aplicaciones  Java  y  .NET,  el  cuál  está  siendo  uLlizado  por  enLdades  bancarias,  consultoras,  etc.  de  presLgio  a  nivel  mundial.    

Gorka  Vicente  Ingeniero  en  InformáLca  

Bienvenida  y  Obje6vos  gorkavicente.com  

Bienvenida  y  Obje6vos  Programación  en  C#  

Crear   aplicaciones   cliente   (web   y   escritorio)   que  consuman  servicios  remotos  y  servicios  publicados  por  nosotros  mismos  

Perder  el  miedo  a  .NET  

Ser   capaces   de   crear   librerías   y   consumirlas   desde    proyectos  tanto  locales  como  remotos  

Crear   servicios   Windows   con   el   objeLvo   de   crear  aplicaciones  desatendidas    

Conocer  herramientas  existentes  en  el  mercado    que  nos  faciliten  y  agilicen  el  día  a  día    

Introducción  a  .NET  Aterrizaje  forzoso  en  este  mundo  

10Introducción  a  .NET  Conceptos  generales  

Development  PlaUorm  Technologies  

11Introducción  a  .NET  Conceptos  generales  

Unidad  lógica  de  despliegue  en  la  plataforma  .NET.  

AssembliesComponente  Windows  que  admite  la  compilación  y  proporciona  un  entorno  de  ejecución  administrado,  un  desarrollo  e  implementación  simplificados  y  la  integración  con  una  gran  variedad  de  lenguajes  de  programación.    Consta  de  2  componentes  principales:  •  CLR  •  Biblioteca  de  clases  

Framework .NETCommon  Intermediate  Language    Código  intermedio  resultante  de  la  compilacion  del  código  fuente  y  que  es  interpretado  por  el  CLR.  

CILCommon  Language  Run6me    Entorno  común  de  ejecución  para  lenguajes.  

CLRLenguaje  de  programación  orientado  a  objetos  que  está  incluido  en  la  Plataforma  .NET  y  que  se  ejecuta  en  el  CLR  (Common  Language  RunLme).  

C#

Assembly  manifest  

Type  metadata  

CIL  code  

Resources  

MyAssembly.dll  

12Introducción  a  .NET  Conceptos  generales  

13Introducción  a  .NET  Versiones  del  Framework  

14Introducción  a  .NET  Entorno  de  desarrollo  

Conjunto  completo  de  herramientas  de  desarrollo  para  la  generación  de  aplicaciones  web  ASP.NET,  Servicios  Web  XML,  aplicaciones  de  escritorio  y  aplicaciones  móviles.  Visual  Basic,  Visual  C#  y  Visual  C++  uIlizan  todos  el  mismo  entorno  de  desarrollo  integrado  (IDE),  que  habilita  el  uso  comparIdo  de  herramientas  y  facilita  la  creación  de  soluciones  en  varios  lenguajes.  

15Introducción  a  .NET  Entorno  de  desarrollo  

16Introducción  a  .NET  Anatomía  de  una  aplicación  

Todas  las  aplicaciones  C#  están  estructuradas  exactamente  de  la  misma  forma.  Todas  hacen  uso  de  espacios  de  nombres,  clases  y  métodos.  

17Introducción  a  .NET  Anatomía  de  una  aplicación  

¡  Profundicemos  un  poco  más  !  

Definiciones  básicas  Espacios  de  nombres,  clases,  

constructores,  campos  y  propiedades,  métodos  y  Lpos  

Lenguaje  orientado  a  objetos;  lo  que  significa  que  todo  con  lo  que  vamos  a  trabajar  en  este  lenguaje  son  objetos.    Un  objeto  es  un  agregado  de  datos  y  de  métodos  que  permiten  manipular  dichos  datos,  y  un  programa  en  C#  no  es  más  que  un  conjunto  de  objetos  que  interaccionan  unos  con  otros  a  través  de  sus  métodos.  

Definiciones  básicas  Lenguaje  de  programación  C#  

C#  

20

posibilidad  de  crear  nuevas  clases  basadas  en  una  clase  existente.  

Programación  Orientada  a  Objetos  Los  4  pilares  

Herencia  

Expresa  las  caracterísLcas  esenciales  de  un  objeto.  

Abstracción  ocultamiento  del  estado,  es  decir,  de  los  datos  de  un  objeto  de  manera  que  sólo  se  pueda  cambiar  mediante  las  operaciones  definidas  para  ese  objeto.  

Encapsulamiento  

palabra  griega  que  significa  "con  muchas  formas”.  Tareas  similares  son  realizadas  por  métodos  con  mismo  nombre.  

Polimorfismo  

21

namespace  La  palabra  clave  namespace  se  uLliza  para  declarar  un  ámbito  que  conLene  un  conjunto  de  objetos  relacionados.    Hace  que  las  clases  sean  fáciles  de  usar  y  prevenir  colisiones  con  las  clases  escritas  por  otros  programadores.  

Dentro  de  un  espacio  de  nombres,  se  pueden  declarar  uno  o  varios  de  los  siguientes  6pos:      

Definiciones  básicas  

otro  espacio  de  nombres      class      interface      struct      enum      delegate      

namespace SampleNamespace { class SampleClass { } interface SampleInterface { } struct SampleStruct { } enum SampleEnum { a, b } delegate void SampleDelegate(int i); namespace SampleNamespace.Nested { class SampleClass2 { } } }

Lenguaje  de  programación  C#  

Ejemplo  prácLco  namespace  

namespace SomeNameSpace { public class MyClass { static void Main() { Nested.NestedNameSpaceClass.SayHello(); } } // a nested namespace namespace Nested { public class NestedNameSpaceClass { public static void SayHello() { Console.WriteLine("Hello"); } } } } // Output: Hello

Definiciones  básicas  Lenguaje  de  programación  C#  namespace  

En  el  siguiente  ejemplo  existen  3  clases:    

•  Dog •  Cat •  Fish

 Las  3  clases  están  definidas  en  el  mismo  namespace.  Por  ello,  Dog.Bark() puede  invocar  a  Cat.Meow() y/o  Fish.Swim() sin  problema!!.    

Palabra reservada using Hacer  uso  de  clases  de  otros  espacios  de  nombres  

Definiciones  básicas  Lenguaje  de  programación  C#  namespace  

Definiciones  básicas  Lenguaje  de  programación  C#  namespace  

namespace A { namespace B {

namespace C { public class CClass { } }

} } namespace D { public class DClass { } } namespace F { public class FClass { } }

using System; using A.B.C; namespace E { using D; class Program {

static void Main() { // Can access CClass type directly from A.B.C. CClass var1 = new CClass();

// Can access DClass type from D. DClass var2 = new DClass();

// Must explicitly specify F namespace. F.FClass var3 = new F.FClass();

// Display types. Console.WriteLine(var1); Console.WriteLine(var2); Console.WriteLine(var3); }

} }

?

Definiciones  básicas  Lenguaje  de  programación  C#  namespace  

namespace A { namespace B {

namespace C { public class CClass { } }

} } namespace D { public class DClass { } } namespace F { public class FClass { } }

using System; using A.B.C; namespace E { using D; class Program {

static void Main() { // Can access CClass type directly from A.B.C. CClass var1 = new CClass();

// Can access DClass type from D. DClass var2 = new DClass();

// Must explicitly specify F namespace. F.FClass var3 = new F.FClass();

// Display types. Console.WriteLine(var1); Console.WriteLine(var2); Console.WriteLine(var3); }

} }

A.B.C.CClass D.DClass F.FClass

27

Unidad  lógica  que  encapsula  un  conjunto  de  datos  y  comportamientos  relacionados.    Una  declaración  de  clase  o  struct  es  como  una  planLlla  que  se  uLliza  para  crear  instancias  u  objetos  en  Lempo  de  ejecución.    Una  clase  define  las  operaciones  que  un  objeto  puede  realizar  y  define  un  valor  que  manLene  el  estado  del  objeto.    El  Lpo  struct  es  adecuado  para  representar  objetos  de  poca  complejidad.  

Definiciones  básicas   class Person { private string firstName; private string lastName; private int age; }

Si   definimos   una   clase   o   un  struct   llamado  Person,   Person  es   el   nombre   del   Lpo.   Si  declaramos  e   inicializamos  una  variable   p   de   Lpo   Person,   se  dice  que  p  es  un  objeto  o  una  instancia  de  Person.    

Se   pueden   c rea r   va r i a s  instancias   del   mismo   Lpo  Person  y  cada   instancia  puede  tener  diferentes  valores  en  sus  propiedades  y  campos.  

Lenguaje  de  programación  C#  

Los  structs  son  Lpos  de  valor  y  las  clases  Lpos  de  referencia.  

struct Coord { public int x, y; public Coord(int p1, int p2) { x = p1; y = p2; } }

//Fields, properties, methods and events go here...  

Clases  y  Structs  

Definiciones  básicas  Lenguaje  de  programación  C#  Clases  y  Structs  

29

Campos  variable  de  cualquier  Lpo  que  se  declara  directamente  en  una  clase  o  struct.  Los  campos  son  miembros  de  su  Lpo  contenedor.  

Métodos  bloque  de  código  que  conLene  una  serie  de  instrucciones.  

Constructores  permiten  al  programador  establecer  valores  predeterminados,  limitar  la  creación  de  instancias.  

Destructores  se  uLlizan  para  destruir  instancias  de  clases.  

Todos  los  métodos,  campos,  constantes,  propiedades  y  eventos  se  deben  declarar  dentro  de  un  6po;  estos  elementos  se  denominan  miembros  del  6po.      En  la  lista  siguiente  se  incluyen  los  diversos  6pos  de  miembros  que  pueden  declararse  en  una  clase  o  en  un  struct.  

Operadores  símbolo  formado  por  uno  o  más  caracteres  que  permite  realizar  una  determinada  operación  entre  uno  o  más  datos  y  produce  un  resultado.  

Eventos  habilitan  una  clase  u  objeto  para  noLficarlo  a  otras  clases  u  objetos.  

Constantes  valores  inmutables  que  se  conocen  en  Lempo  de  compilación  y  no  cambian  mientras  dura  el  programa.  

const

Indizadores  permiten  indizar  las  instancias  de  una  clase  o  struct  igual  que  como  se  hace  con  las  matrices  

this Propiedades  miembro  que  ofrece  un  mecanismo  flexible  para  leer,  escribir  o  calcular  el  valor  de  un  campo  privado.   get; set;

Definiciones  básicas  Lenguaje  de  programación  C#  Clases  y  Structs  

namespace ProgrammingGuide { // Class definition. public class MyCustomClass { // Class members: // Property. public int Number { get; set; } // Method. public int Multiply(int num) { return num * Number; } // Instance Constructor. public MyCustomClass() { Number = 0; } } // Another class definition. This one contains // the Main method, the entry point for the program. class Program { static void Main(string[] args) { // Create an object of type MyCustomClass. MyCustomClass myClass = new MyCustomClass(); // Set the value of a public property. myClass.Number = 27; // Call a public method. int result = myClass.Multiply(4); } } }

Definiciones  básicas  Lenguaje  de  programación  C#  Tipos  de  miembros  

Campos  dato  común  a  todos  los  objetos  de  una  determinada  clase.  Se  trata  en  realidad  de  una  variable  definida  dentro  de  una  definición  de  clase.    

Métodos  conjunto  de  instrucciones  a  las  que  se  les  asocia  un  nombre  de  modo  que  si  se  desea  ejecutarlas  basta  referenciarlas  a  través  de  dicho  nombre  en  vez  de  tener  que  escribirlas.  

Constructores  reciben  ese  nombre  debido  a  que  su  código  suele  usarse  precisamente  para  construir  el  objeto,  para  inicializar  sus  miembros.    

Propiedades  miembros  que  ofrecen  un  mecanismo  flexible  para  leer,  escribir  o  calcular  los  valores  de  campos  privados.  Son  métodos  especiales  denominados  descriptores  de  acceso.    

//  Constantes,  Operadores,  Eventos    

Directrices  para  la  programación  

Framework  Design  Guidelines  

Instrucciones  y  pautas  con  las  que  se  pretende  ayudar  a  los  desarrolladores  de  clases  a  comprender  las  ventajas  y  las  desventajas  entre  las  disLntas  soluciones.  

Coherencia  

Facilidad  de  uso  

Un  diseño  de  API  incoherente  afecta  negaIvamente  a  la  producIvidad  de  los  desarrolladores  y  nos  desanima  a  adoptarla  

Directrices  para  la  programación  Framework  Design  Guidelines  

33

Nomenclatura  instrucciones  para  denominar  Lpos  y  miembros  en  las  bibliotecas  

de  clases.    

Diseño  de  6pos  instrucciones  para  uLlizar  clases  estáLcas  y  abstractas,  interfaces,  

enumeraciones  y  estructuras.    

 Diseño  de  miembros  instrucciones  para  diseñar  y  uLlizar  propiedades,  métodos,  

constructores,  campos,  eventos  y  operadores.  Esta  sección  

también  describe  los  procedimientos  recomendados  para  diseñar  

parámetros.    

 

Diseño  de  excepciones  instrucciones  de  diseño  para  diseñar,  iniciar  y  detectar  excepciones.  

Directrices  para  la  programación  Framework  Design  Guidelines  

Diseño  de  extensibilidad  instrucciones  para  diseñar  bibliotecas  que  se  pueden  extender.    

 

34

Nomenclatura  instrucciones  para  denominar  Lpos  y  miembros  en  las  bibliotecas  

de  clases.    

Diseño  de  6pos  instrucciones  para  uLlizar  clases  estáLcas  y  abstractas,  interfaces,  

enumeraciones  y  estructuras.    

 Diseño  de  miembros  instrucciones  para  diseñar  y  uLlizar  propiedades,  métodos,  

constructores,  campos,  eventos  y  operadores.  Esta  sección  

también  describe  los  procedimientos  recomendados  para  diseñar  

parámetros.    

 

Diseño  de  excepciones  instrucciones  de  diseño  para  diseñar,  iniciar  y  detectar  excepciones.  

Diseño  de  extensibilidad  instrucciones  para  diseñar  bibliotecas  que  se  pueden  extender.    

 

Directrices  para  la  programación  Framework  Design  Guidelines  

35

Uso  de  minúsculas  y  mayúsculas  Cuando  un  idenLficador  está  compuesto  de  varias  palabras,  no  uLlizar  separadores,  como  guiones  de  subrayado  ("_")  ni  guiones  ("-­‐"),  entre  las  palabras.  En  su  lugar,  uLlizar  la  mayúscula  para  señalar  el  principio  de  cada  palabra.  

Convenciones  generales  de  nomenclatura  Elegir  nombres  fácilmente  legibles  para  los  idenLficadores.  Por  ejemplo,  una  propiedad  denominada  HorizontalAlignment  es  más  legible  en  inglés  que  AlignmentHorizontal.  Es  preferible  la  legibilidad  a  la  brevedad.  El  nombre  de  propiedad  CanScrollHorizontally  es  mejor  que  ScrollableX  (una  referencia  oculta  al  eje  X).  No  uLlizar  guiones  de  subrayado,  guiones  ni  ningún  otro  carácter  no  alfanumérico.  

Framework  Design  Guidelines  

Nombres  de  ensamblados  y  bibliotecas  DLL  Elegir  nombres  para  las  DLL  que  sugieran  grandes  fragmentos  de  funcionalidad  como  System.Data.  Seguir  el  siguiente  modelo:  

Nombres  de  espacios  de  nombres  Debería  indicar  la  funcionalidad  que  proporcionan  los  Lpos  incluidos  en  el  espacio  de  nombres.  Por  ejemplo,  System.Net.Sockets  conLene  Lpos  que  permiten  a  los  desarrolladores  uLlizar  sockets  para  realizar  comunicaciones  a  través  de  las  redes.  

Nombres  de  clases,  estructuras  e  interfaces  No  uLlizar  prefijos  para  los  nombres  de  clases  (como  la  letra  C).  Las  interfaces,  que  deberían  comenzar  con  la  letra  I,  son  la  excepción  a  esta  regla.  Considerar  finalizar  los  nombres  de  las  clases  derivadas  con  el  nombre  de  la  clase  base.  

Nombres  de  miembros  de  Ipos,  parámetros  Métodos:  proporcionar  nombres  de  métodos  que  sean  verbos  ya  que  facilita  a  los  desarrolladores  la  comprensión  de  lo  que  hace  el  método.  Propiedades:  asignar  nombres  a  las  propiedades  mediante  un  sustanLvo,  un  sintagma  nominal  o  un  adjeLvo.    

<Company>.<Component>.dll

Donde  <Component> conLene  una  o  más  cláusulas  separadas  por  puntos:  

Contoso.WebControls.dll

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

Nomenclatura  

Uso  de  minúsculas  y  mayúsculas  Cuando  un  idenLficador  está  compuesto  de  varias  palabras,  no  uLlizar  separadores,  como  guiones  de  subrayado  ("_")  ni  guiones  ("-­‐"),  entre  las  palabras.  En  su  lugar,  uLlizar  la  mayúscula  para  señalar  el  principio  de  cada  palabra.  

Convenciones  generales  de  nomenclatura  

Nombres  de  ensamblados  y  bibliotecas  DLL  Elegir  nombres  para  las  DLL  que  sugieran  grandes  fragmentos  de  funcionalidad  como  System.Data.  Seguir  el  siguiente  modelo:  

Nombres  de  espacios  de  nombres  Debería  indicar  la  funcionalidad  que  proporcionan  los  Lpos  incluidos  en  el  espacio  de  nombres.  Por  ejemplo,  System.Net.Sockets  conLene  Lpos  que  permiten  a  los  desarrolladores  uLlizar  sockets  para  realizar  comunicaciones  a  través  de  las  redes.  

Nombres  de  clases,  estructuras  e  interfaces  No  uLlizar  prefijos  para  los  nombres  de  clases  (como  la  letra  C).  Las  interfaces,  que  deberían  comenzar  con  la  letra  I,  son  la  excepción  a  esta  regla.  Considerar  finalizar  los  nombres  de  las  clases  derivadas  con  el  nombre  de  la  clase  base.  

Nombres  de  miembros  de  Ipos,  parámetros  Métodos:  proporcionar  nombres  de  métodos  que  sean  verbos  ya  que  facilita  a  los  desarrolladores  la  comprensión  de  lo  que  hace  el  método.  Propiedades:  asignar  nombres  a  las  propiedades  mediante  un  sustanLvo,  un  sintagma  nominal  o  un  adjeLvo.    

<Company>.<Component>.dll

Donde  <Component> conLene  una  o  más  cláusulas  separadas  por  puntos:  

Contoso.WebControls.dll

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

Elegir  nombres  fácilmente  legibles  para  los  idenLficadores.  Por  ejemplo,  una  propiedad  denominada  HorizontalAlignment  es  más  legible  en  inglés  que  AlignmentHorizontal.  Es  preferible  la  legibilidad  a  la  brevedad.  El  nombre  de  propiedad  CanScrollHorizontally  es  mejor  que  ScrollableX  (una  referencia  oculta  al  eje  X).  No  uLlizar  guiones  de  subrayado,  guiones  ni  ningún  otro  carácter  no  alfanumérico.  

Framework  Design  Guidelines  Nomenclatura  

37

Case  

AppDomain

Ejemplo  iden6ficador  

class  

Tipo  de  enumeración  

Event  

Valores  de  enumeración  

Clase  de  excepción  

Campo  estáIco  de  sólo  lectura  

Pascal  

Pascal  

Pascal  

Pascal  

Pascal  

Pascal  

interface   Pascal  

Método   Pascal  

Espacio  de  nombres   Pascal  

Parámetro   Camel  

Propiedad   Pascal  

ErrorLevel

FatalError

ValueChanged

WebException

RedValue

IDisposable

ToString

System.Drawing

typeName

BackColor

Framework  Design  Guidelines  Nomenclatura  

Uso  de  minúsculas  y  mayúsculas  ULlizar  la  gra^a  Pascal  para  todos  los  nombres  de  miembros  públicos,  6pos  y  espacios  de  nombres  que  constan  de  varias  palabras.    ULlizar  el  uso  combinado  de  mayúsculas  y  minúsculas  Lpo  Camel  para  los  nombres  de  parámetros.  

Gra^a  Pascal  La  primera  letra  del  idenLficador  y  la  primera  letra  de  las  siguientes  palabras  concatenadas  están  en  mayúsculas.  El  esLlo  de  mayúsculas  y  minúsculas  Pascal  se  puede  uLlizar  en  idenLficadores  de  tres  o  más  caracteres.  Por  ejemplo:    

Gra^a  Camel  La  primera  letra  del  idenLficador  está  en  minúscula  y  la  primera  letra  de  las  siguientes  palabras  concatenadas  en  mayúscula.  Por  ejemplo:    

BackColor

backColor

Uso  de  minúsculas  y  mayúsculas  Cuando  un  idenLficador  está  compuesto  de  varias  palabras,  no  uLlizar  separadores,  como  guiones  de  subrayado  ("_")  ni  guiones  ("-­‐"),  entre  las  palabras.  En  su  lugar,  uLlizar  la  mayúscula  para  señalar  el  principio  de  cada  palabra.  

Convenciones  generales  de  nomenclatura  

Nombres  de  ensamblados  y  bibliotecas  DLL  Elegir  nombres  para  las  DLL  que  sugieran  grandes  fragmentos  de  funcionalidad  como  System.Data.  Seguir  el  siguiente  modelo:  

Nombres  de  espacios  de  nombres  Debería  indicar  la  funcionalidad  que  proporcionan  los  Lpos  incluidos  en  el  espacio  de  nombres.  Por  ejemplo,  System.Net.Sockets  conLene  Lpos  que  permiten  a  los  desarrolladores  uLlizar  sockets  para  realizar  comunicaciones  a  través  de  las  redes.  

Nombres  de  clases,  estructuras  e  interfaces  No  uLlizar  prefijos  para  los  nombres  de  clases  (como  la  letra  C).  Las  interfaces,  que  deberían  comenzar  con  la  letra  I,  son  la  excepción  a  esta  regla.  Considerar  finalizar  los  nombres  de  las  clases  derivadas  con  el  nombre  de  la  clase  base.  

Nombres  de  miembros  de  Ipos,  parámetros  Métodos:  proporcionar  nombres  de  métodos  que  sean  verbos  ya  que  facilita  a  los  desarrolladores  la  comprensión  de  lo  que  hace  el  método.  Propiedades:  asignar  nombres  a  las  propiedades  mediante  un  sustanLvo,  un  sintagma  nominal  o  un  adjeLvo.    

<Company>.<Component>.dll

Donde  <Component> conLene  una  o  más  cláusulas  separadas  por  puntos:  

Contoso.WebControls.dll

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

Elegir  nombres  fácilmente  legibles  para  los  idenLficadores.  Por  ejemplo,  una  propiedad  denominada  HorizontalAlignment  es  más  legible  en  inglés  que  AlignmentHorizontal.  Es  preferible  la  legibilidad  a  la  brevedad.  El  nombre  de  propiedad  CanScrollHorizontally  es  mejor  que  ScrollableX  (una  referencia  oculta  al  eje  X).  No  uLlizar  guiones  de  subrayado,  guiones  ni  ningún  otro  carácter  no  alfanumérico.  

Framework  Design  Guidelines  Nomenclatura  

Uso  de  minúsculas  y  mayúsculas  Cuando  un  idenLficador  está  compuesto  de  varias  palabras,  no  uLlizar  separadores,  como  guiones  de  subrayado  ("_")  ni  guiones  ("-­‐"),  entre  las  palabras.  En  su  lugar,  uLlizar  la  mayúscula  para  señalar  el  principio  de  cada  palabra.  

Convenciones  generales  de  nomenclatura  

Nombres  de  ensamblados  y  bibliotecas  DLL  Elegir  nombres  para  las  DLL  que  sugieran  grandes  fragmentos  de  funcionalidad  como  System.Data.  Seguir  el  siguiente  modelo:  

Nombres  de  espacios  de  nombres  Debería  indicar  la  funcionalidad  que  proporcionan  los  Lpos  incluidos  en  el  espacio  de  nombres.  Por  ejemplo,  System.Net.Sockets  conLene  Lpos  que  permiten  a  los  desarrolladores  uLlizar  sockets  para  realizar  comunicaciones  a  través  de  las  redes.  

Nombres  de  clases,  estructuras  e  interfaces  No  uLlizar  prefijos  para  los  nombres  de  clases  (como  la  letra  C).  Las  interfaces,  que  deberían  comenzar  con  la  letra  I,  son  la  excepción  a  esta  regla.  Considerar  finalizar  los  nombres  de  las  clases  derivadas  con  el  nombre  de  la  clase  base.  

Nombres  de  miembros  de  Ipos,  parámetros  Métodos:  proporcionar  nombres  de  métodos  que  sean  verbos  ya  que  facilita  a  los  desarrolladores  la  comprensión  de  lo  que  hace  el  método.  Propiedades:  asignar  nombres  a  las  propiedades  mediante  un  sustanLvo,  un  sintagma  nominal  o  un  adjeLvo.    

<Company>.<Component>.dll

Donde  <Component> conLene  una  o  más  cláusulas  separadas  por  puntos:  

Contoso.WebControls.dll

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

Elegir  nombres  fácilmente  legibles  para  los  idenLficadores.  Por  ejemplo,  una  propiedad  denominada  HorizontalAlignment  es  más  legible  en  inglés  que  AlignmentHorizontal.  Es  preferible  la  legibilidad  a  la  brevedad.  El  nombre  de  propiedad  CanScrollHorizontally  es  mejor  que  ScrollableX  (una  referencia  oculta  al  eje  X).  No  uLlizar  guiones  de  subrayado,  guiones  ni  ningún  otro  carácter  no  alfanumérico.  

Framework  Design  Guidelines  Nomenclatura  

Uso  de  minúsculas  y  mayúsculas  Cuando  un  idenLficador  está  compuesto  de  varias  palabras,  no  uLlizar  separadores,  como  guiones  de  subrayado  ("_")  ni  guiones  ("-­‐"),  entre  las  palabras.  En  su  lugar,  uLlizar  la  mayúscula  para  señalar  el  principio  de  cada  palabra.  

Convenciones  generales  de  nomenclatura  

Nombres  de  ensamblados  y  bibliotecas  DLL  Elegir  nombres  para  las  DLL  que  sugieran  grandes  fragmentos  de  funcionalidad  como  System.Data.  Seguir  el  siguiente  modelo:  

Nombres  de  espacios  de  nombres  Debería  indicar  la  funcionalidad  que  proporcionan  los  Lpos  incluidos  en  el  espacio  de  nombres.  Por  ejemplo,  System.Net.Sockets  conLene  Lpos  que  permiten  a  los  desarrolladores  uLlizar  sockets  para  realizar  comunicaciones  a  través  de  las  redes.  

Nombres  de  clases,  estructuras  e  interfaces  No  uLlizar  prefijos  para  los  nombres  de  clases  (como  la  letra  C).  Las  interfaces,  que  deberían  comenzar  con  la  letra  I,  son  la  excepción  a  esta  regla.  Considerar  finalizar  los  nombres  de  las  clases  derivadas  con  el  nombre  de  la  clase  base.  

Nombres  de  miembros  de  Ipos,  parámetros  Métodos:  proporcionar  nombres  de  métodos  que  sean  verbos  ya  que  facilita  a  los  desarrolladores  la  comprensión  de  lo  que  hace  el  método.  Propiedades:  asignar  nombres  a  las  propiedades  mediante  un  sustanLvo,  un  sintagma  nominal  o  un  adjeLvo.    

<Company>.<Component>.dll

Donde  <Component> conLene  una  o  más  cláusulas  separadas  por  puntos:  

Contoso.WebControls.dll

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

Elegir  nombres  fácilmente  legibles  para  los  idenLficadores.  Por  ejemplo,  una  propiedad  denominada  HorizontalAlignment  es  más  legible  en  inglés  que  AlignmentHorizontal.  Es  preferible  la  legibilidad  a  la  brevedad.  El  nombre  de  propiedad  CanScrollHorizontally  es  mejor  que  ScrollableX  (una  referencia  oculta  al  eje  X).  No  uLlizar  guiones  de  subrayado,  guiones  ni  ningún  otro  carácter  no  alfanumérico.  

Framework  Design  Guidelines  Nomenclatura  

Uso  de  minúsculas  y  mayúsculas  Cuando  un  idenLficador  está  compuesto  de  varias  palabras,  no  uLlizar  separadores,  como  guiones  de  subrayado  ("_")  ni  guiones  ("-­‐"),  entre  las  palabras.  En  su  lugar,  uLlizar  la  mayúscula  para  señalar  el  principio  de  cada  palabra.  

Convenciones  generales  de  nomenclatura  

Nombres  de  ensamblados  y  bibliotecas  DLL  Elegir  nombres  para  las  DLL  que  sugieran  grandes  fragmentos  de  funcionalidad  como  System.Data.  Seguir  el  siguiente  modelo:  

Nombres  de  espacios  de  nombres  Debería  indicar  la  funcionalidad  que  proporcionan  los  Lpos  incluidos  en  el  espacio  de  nombres.  Por  ejemplo,  System.Net.Sockets  conLene  Lpos  que  permiten  a  los  desarrolladores  uLlizar  sockets  para  realizar  comunicaciones  a  través  de  las  redes.  

Nombres  de  clases,  estructuras  e  interfaces  No  uLlizar  prefijos  para  los  nombres  de  clases  (como  la  letra  C).  Las  interfaces,  que  deberían  comenzar  con  la  letra  I,  son  la  excepción  a  esta  regla.  Considerar  finalizar  los  nombres  de  las  clases  derivadas  con  el  nombre  de  la  clase  base.  

Nombres  de  miembros  de  Ipos,  parámetros  Métodos:  proporcionar  nombres  de  métodos  que  sean  verbos  ya  que  facilita  a  los  desarrolladores  la  comprensión  de  lo  que  hace  el  método.  Propiedades:  asignar  nombres  a  las  propiedades  mediante  un  sustanLvo,  un  sintagma  nominal  o  un  adjeLvo.    

<Company>.<Component>.dll

Donde  <Component> conLene  una  o  más  cláusulas  separadas  por  puntos:  

Contoso.WebControls.dll

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

Elegir  nombres  fácilmente  legibles  para  los  idenLficadores.  Por  ejemplo,  una  propiedad  denominada  HorizontalAlignment  es  más  legible  en  inglés  que  AlignmentHorizontal.  Es  preferible  la  legibilidad  a  la  brevedad.  El  nombre  de  propiedad  CanScrollHorizontally  es  mejor  que  ScrollableX  (una  referencia  oculta  al  eje  X).  No  uLlizar  guiones  de  subrayado,  guiones  ni  ningún  otro  carácter  no  alfanumérico.  

Framework  Design  Guidelines  Nomenclatura  

42

Nomenclatura  instrucciones  para  denominar  Lpos  y  miembros  en  las  bibliotecas  

de  clases.    

Diseño  de  6pos  instrucciones  para  uLlizar  clases  estáLcas  y  abstractas,  interfaces,  

enumeraciones  y  estructuras.    

 Diseño  de  miembros  instrucciones  para  diseñar  y  uLlizar  propiedades,  métodos,  

constructores,  campos,  eventos  y  operadores.  Esta  sección  

también  describe  los  procedimientos  recomendados  para  diseñar  

parámetros.    

 

Diseño  de  excepciones  instrucciones  de  diseño  para  diseñar,  iniciar  y  detectar  excepciones.  

Directrices  para  la  programación  Framework  Design  Guidelines  

Diseño  de  extensibilidad  instrucciones  para  diseñar  bibliotecas  que  se  pueden  extender.    

 

43

Diseño  de  clases  abstractas  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  6pos  

Una  interfaz  define  las  firmas  para  un  conjunto  de  miembros  (métodos,  etc.)  que  deben  proporcionar  los  implementadores.  Las  interfaces  no  pueden  proporcionar  los  detalles  de  implementación  para  los  miembros.  Las  clases  pueden  implementar  varias  interfaces.  Considerar  la  posibilidad  de  definir  interfaces  para  lograr  un  efecto  similar  al  de  la  herencia  múlLple.    

Elegir  entre  clases  e  interfaces  

Diseño  de  enumeraciones  Las  enumeraciones  proporcionan  conjuntos  de  valores  constantes  que  son  úLles  para  la  definición  inflexible  de  Lpos  de  miembros  y  mejorar  la  legibilidad  del  código.  No  uLlizar  una  enumeración  para  conjuntos  abiertos  como  la  versión  del  sistema  operaLvo.    

44

Diseño  de  clases  abstractas  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  6pos  

Una  interfaz  define  las  firmas  para  un  conjunto  de  miembros  (métodos,  etc.)  que  deben  proporcionar  los  implementadores.  Las  interfaces  no  pueden  proporcionar  los  detalles  de  implementación  para  los  miembros.  Las  clases  pueden  implementar  varias  interfaces.  Considerar  la  posibilidad  de  definir  interfaces  para  lograr  un  efecto  similar  al  de  la  herencia  múlLple.    

Elegir  entre  clases  e  interfaces  

Diseño  de  enumeraciones  Las  enumeraciones  proporcionan  conjuntos  de  valores  constantes  que  son  úLles  para  la  definición  inflexible  de  Lpos  de  miembros  y  mejorar  la  legibilidad  del  código.  No  uLlizar  una  enumeración  para  conjuntos  abiertos  como  la  versión  del  sistema  operaLvo.    

45

Diseño  de  clases  abstractas  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  6pos  

Una  interfaz  define  las  firmas  para  un  conjunto  de  miembros  (métodos,  etc.)  que  deben  proporcionar  los  implementadores.  Las  interfaces  no  pueden  proporcionar  los  detalles  de  implementación  para  los  miembros.  Las  clases  pueden  implementar  varias  interfaces.  Considerar  la  posibilidad  de  definir  interfaces  para  lograr  un  efecto  similar  al  de  la  herencia  múlLple.    

Elegir  entre  clases  e  interfaces  

Diseño  de  enumeraciones  

public static class BadFurnishings { public static int Table = 1; public static int Chair = 2; public static int Lamp = 3; }

public enum GoodFurnishings { Table, Chair, Lamp }

El  ejemplo  de  código  siguiente  muestra  un  diseño  incorrecto.  

la  enumeración  que  se  debería  uLlizar  en  lugar  de  las  constantes  estáLcas.  

Las  enumeraciones  proporcionan  conjuntos  de  valores  constantes  que  son  úLles  para  la  definición  inflexible  de  Lpos  de  miembros  y  mejorar  la  legibilidad  del  código.  No  uLlizar  una  enumeración  para  conjuntos  abiertos  como  la  versión  del  sistema  operaLvo.    

46

Nomenclatura  instrucciones  para  denominar  Lpos  y  miembros  en  las  bibliotecas  

de  clases.    

Diseño  de  6pos  instrucciones  para  uLlizar  clases  estáLcas  y  abstractas,  interfaces,  

enumeraciones  y  estructuras.    

 Diseño  de  miembros  instrucciones  para  diseñar  y  uLlizar  propiedades,  métodos,  

constructores,  campos,  eventos  y  operadores.  Esta  sección  

también  describe  los  procedimientos  recomendados  para  diseñar  

parámetros.    

 

Diseño  de  excepciones  instrucciones  de  diseño  para  diseñar,  iniciar  y  detectar  excepciones.  

Directrices  para  la  programación  Framework  Design  Guidelines  

Diseño  de  extensibilidad  instrucciones  para  diseñar  bibliotecas  que  se  pueden  extender.    

 

47

Sobrecarga  de  métodos  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  miembros  

En  general,  los  métodos  representan  acciones  y  las  propiedades  representan  datos.  ULlizar  una  propiedad,  en  lugar  de  un  método,  si  el  valor  de  la  propiedad  está  almacenado  en  la  memoria  del  proceso  (clase)  y  la  propiedad  sólo  proporcionaría  acceso  al  valor.  

Elegir  entre  propiedades  y  métodos  

Diseño  de  propiedades  Crear  propiedades  de  sólo  lectura  si  el  llamador  no  debería  poder  cambiar  sus  valores.  Proporcionar  valores  predeterminados  sensatos  para  todas  las  propiedades,  garanLzando  que  esos  valores  predeterminados  no  producen  una  vulnerabilidad  de  seguridad  o  un  diseño  sumamente  ineficiente.  

Diseño  de  constructores  

Diseño  de  eventos  

Proporcionar  constructores  sencillos.  Un  constructor  sencillo  Lene  un  número  muy  pequeño  de  parámetros.    

Los  eventos  son  mecanismos  que  permiten  al  código  específico  de  la  aplicación  ejecutarse  cuando  se  produce  una  acción.  ULlice  System.EventHandler<T>  en  lugar  de  crear  manualmente  nuevos  delegados  que  se  van  a  uLlizar  como  controladores  de  eventos.  

Diseño  de  campos  No  proporcione  campos  de  instancia  que  sean  públicos  o  protegidos.  En  lugar  de  uLlizar  campos  públicamente  visibles,  uLlice  campos  privados  y  expóngalos  mediante  propiedades.  ULlizar  campos  constantes  para  las  constantes  que  nunca  vayan  a  cambiar.  

Sobrecarga  de  métodos  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  miembros  

En  general,  los  métodos  representan  acciones  y  las  propiedades  representan  datos.  ULlizar  una  propiedad,  en  lugar  de  un  método,  si  el  valor  de  la  propiedad  está  almacenado  en  la  memoria  del  proceso  (clase)  y  la  propiedad  sólo  proporcionaría  acceso  al  valor.  

Elegir  entre  propiedades  y  métodos  

Diseño  de  propiedades  Crear  propiedades  de  sólo  lectura  si  el  llamador  no  debería  poder  cambiar  sus  valores.  Proporcionar  valores  predeterminados  sensatos  para  todas  las  propiedades,  garanLzando  que  esos  valores  predeterminados  no  producen  una  vulnerabilidad  de  seguridad  o  un  diseño  sumamente  ineficiente.  

public class EmployeeRecord { private int employeeId; private int department; public EmployeeRecord() { } public EmployeeRecord (int id, int departmentId) { EmployeeId = id; Department = departmentId; } public int Department { get {return department;} set {department = value;} } public int EmployeeId { get {return employeeId;} set {employeeId = value;} } public EmployeeRecord Clone() { return new EmployeeRecord(employeeId, department); } }

Sobrecarga  de  métodos  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  miembros  

En  general,  los  métodos  representan  acciones  y  las  propiedades  representan  datos.  ULlizar  una  propiedad,  en  lugar  de  un  método,  si  el  valor  de  la  propiedad  está  almacenado  en  la  memoria  del  proceso  (clase)  y  la  propiedad  sólo  proporcionaría  acceso  al  valor.  

Elegir  entre  propiedades  y  métodos  

Diseño  de  propiedades  Crear  propiedades  de  sólo  lectura  si  el  llamador  no  debería  poder  cambiar  sus  valores.  Proporcionar  valores  predeterminados  sensatos  para  todas  las  propiedades,  garanLzando  que  esos  valores  predeterminados  no  producen  una  vulnerabilidad  de  seguridad  o  un  diseño  sumamente  ineficiente.  

Diseño  de  constructores  

Diseño  de  eventos  

Proporcionar  constructores  sencillos.  Un  constructor  sencillo  Lene  un  número  muy  pequeño  de  parámetros.    

Los  eventos  son  mecanismos  que  permiten  al  código  específico  de  la  aplicación  ejecutarse  cuando  se  produce  una  acción.  ULlice  System.EventHandler<T>  en  lugar  de  crear  manualmente  nuevos  delegados  que  se  van  a  uLlizar  como  controladores  de  eventos.  

Diseño  de  campos  No  proporcione  campos  de  instancia  que  sean  públicos  o  protegidos.  En  lugar  de  uLlizar  campos  públicamente  visibles,  uLlice  campos  privados  y  expóngalos  mediante  propiedades.  ULlizar  campos  constantes  para  las  constantes  que  nunca  vayan  a  cambiar.  

Sobrecarga  de  métodos  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  miembros  

En  general,  los  métodos  representan  acciones  y  las  propiedades  representan  datos.  ULlizar  una  propiedad,  en  lugar  de  un  método,  si  el  valor  de  la  propiedad  está  almacenado  en  la  memoria  del  proceso  (clase)  y  la  propiedad  sólo  proporcionaría  acceso  al  valor.  

Elegir  entre  propiedades  y  métodos  

Diseño  de  propiedades  Crear  propiedades  de  sólo  lectura  si  el  llamador  no  debería  poder  cambiar  sus  valores.  Proporcionar  valores  predeterminados  sensatos  para  todas  las  propiedades,  garanLzando  que  esos  valores  predeterminados  no  producen  una  vulnerabilidad  de  seguridad  o  un  diseño  sumamente  ineficiente.  

Diseño  de  constructores  Proporcionar  constructores  sencillos.  Un  constructor  sencillo  Lene  un  número  muy  pequeño  de  parámetros.    

Diseño  de  eventos  Los  eventos  son  mecanismos  que  permiten  al  código  específico  de  la  aplicación  ejecutarse  cuando  se  produce  una  acción.  ULlice  System.EventHandler<T>  en  lugar  de  crear  manualmente  nuevos  delegados  que  se  van  a  uLlizar  como  controladores  de  eventos.  

Diseño  de  campos  No  proporcione  campos  de  instancia  que  sean  públicos  o  protegidos.  En  lugar  de  uLlizar  campos  públicamente  visibles,  uLlice  campos  privados  y  expóngalos  mediante  propiedades.  ULlizar  campos  constantes  para  las  constantes  que  nunca  vayan  a  cambiar.  

Sobrecarga  de  métodos  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  miembros  

En  general,  los  métodos  representan  acciones  y  las  propiedades  representan  datos.  ULlizar  una  propiedad,  en  lugar  de  un  método,  si  el  valor  de  la  propiedad  está  almacenado  en  la  memoria  del  proceso  (clase)  y  la  propiedad  sólo  proporcionaría  acceso  al  valor.  

Elegir  entre  propiedades  y  métodos  

Diseño  de  propiedades  Crear  propiedades  de  sólo  lectura  si  el  llamador  no  debería  poder  cambiar  sus  valores.  Proporcionar  valores  predeterminados  sensatos  para  todas  las  propiedades,  garanLzando  que  esos  valores  predeterminados  no  producen  una  vulnerabilidad  de  seguridad  o  un  diseño  sumamente  ineficiente.  

Diseño  de  constructores  Proporcionar  constructores  sencillos.  Un  constructor  sencillo  Lene  un  número  muy  pequeño  de  parámetros.    

Diseño  de  eventos  

Diseño  de  campos  No  proporcione  campos  de  instancia  que  sean  públicos  o  protegidos.  En  lugar  de  uLlizar  campos  públicamente  visibles,  uLlice  campos  privados  y  expóngalos  mediante  propiedades.  ULlizar  campos  constantes  para  las  constantes  que  nunca  vayan  a  cambiar.  

Los  eventos  son  mecanismos  que  permiten  al  código  específico  de  la  aplicación  ejecutarse  cuando  se  produce  una  acción.  ULlice  System.EventHandler<T> en  lugar  de  crear  manualmente  nuevos  delegados  que  se  van  a  uLlizar  como  controladores  de  eventos.  

Sobrecarga  de  métodos  GaranLzar  que  la  funcionalidad  de  la  clase  abstracta  sea  correcta  y  se  pueda  extender  con  facilidad.  No  definir  constructores  de  Lpo  public.  Deberán  ser  los  Lpos  concretos  (hijos)  quienes  deban  tener  constructores  públicos.    

Framework  Design  Guidelines  Diseño  de  miembros  

En  general,  los  métodos  representan  acciones  y  las  propiedades  representan  datos.  ULlizar  una  propiedad,  en  lugar  de  un  método,  si  el  valor  de  la  propiedad  está  almacenado  en  la  memoria  del  proceso  (clase)  y  la  propiedad  sólo  proporcionaría  acceso  al  valor.  

Elegir  entre  propiedades  y  métodos  

Diseño  de  propiedades  Crear  propiedades  de  sólo  lectura  si  el  llamador  no  debería  poder  cambiar  sus  valores.  Proporcionar  valores  predeterminados  sensatos  para  todas  las  propiedades,  garanLzando  que  esos  valores  predeterminados  no  producen  una  vulnerabilidad  de  seguridad  o  un  diseño  sumamente  ineficiente.  

Diseño  de  constructores  

Diseño  de  eventos  

Diseño  de  campos  No  proporcione  campos  de  instancia  que  sean  públicos  o  protegidos.  En  lugar  de  uLlizar  campos  públicamente  visibles,  uLlice  campos  privados  y  expóngalos  mediante  propiedades.  ULlizar  campos  constantes  para  las  constantes  que  nunca  vayan  a  cambiar.  

Proporcionar  constructores  sencillos.  Un  constructor  sencillo  Lene  un  número  muy  pequeño  de  parámetros.    

Los  eventos  son  mecanismos  que  permiten  al  código  específico  de  la  aplicación  ejecutarse  cuando  se  produce  una  acción.  ULlice  System.EventHandler<T>  en  lugar  de  crear  manualmente  nuevos  delegados  que  se  van  a  uLlizar  como  controladores  de  eventos.  

53

Nomenclatura  instrucciones  para  denominar  Lpos  y  miembros  en  las  bibliotecas  

de  clases.    

Diseño  de  6pos  instrucciones  para  uLlizar  clases  estáLcas  y  abstractas,  interfaces,  

enumeraciones  y  estructuras.    

 Diseño  de  miembros  instrucciones  para  diseñar  y  uLlizar  propiedades,  métodos,  

constructores,  campos,  eventos  y  operadores.  Esta  sección  

también  describe  los  procedimientos  recomendados  para  diseñar  

parámetros.    

 

Diseño  de  excepciones  instrucciones  de  diseño  para  diseñar,  iniciar  y  detectar  excepciones.  

Directrices  para  la  programación  Framework  Design  Guidelines  

Diseño  de  extensibilidad  instrucciones  para  diseñar  bibliotecas  que  se  pueden  extender.    

 

Framework  Design  Guidelines  Diseño  de  extensibilidad  

Capacidad  de  agregar  o  modificar  el  comportamiento  de  objetos  

Framework  Design  Guidelines  Diseño  de  extensibilidad  

Miembros  virtuales  Un  miembro  definido  como  virtual  permite  al  desarrollador  cambiar  el  comportamiento  del  miembro  proporcionando  una  implementación  diferente.  

Clases  no  selladas  Una  clase  no  sellada  permite  a  otras  clases  heredar  de  ella.  De  forma  predeterminada,  la  mayoría  de  las  clases  no  deberían  estar  selladas.  Los  desarrolladores  pueden  agregar  un  constructor  a  un  Lpo  derivado  de  la  clase,  y  uLlizar  ese  constructor  para  inicializar  las  propiedades  de  la  clase  base  con  los  valores  necesarios  para  el  escenario.  

Tipos  e  interfaces  abstractos  Son  mecanismos  para  especificar  abstracciones  de  programación.  Una  abstracción  especifica  un  contrato  al  que  se  deben  adherir  los  herederos  o  implementadores.  

Clases  base  para  implementar  abstracciones  Son  clases  diseñadas  para  ayudar  a  los  desarrolladores  a  implementar  clases  abstractas  e  interfaces  (abstracciones).  Proporcionan  algunos  de  los  detalles  de  implementación  de  una  abstracción  y  en  algunos  casos  pueden  uLlizarse  sin  herencia.  

Framework  Design  Guidelines  Diseño  de  extensibilidad  

Miembros  virtuales  Un  miembro  definido  como  virtual  permite  al  desarrollador  cambiar  el  comportamiento  del  miembro  proporcionando  una  implementación  diferente.  

Clases  no  selladas  Una  clase  no  sellada  permite  a  otras  clases  heredar  de  ella.  De  forma  predeterminada,  la  mayoría  de  las  clases  no  deberían  estar  selladas.  Los  desarrolladores  pueden  agregar  un  constructor  a  un  Lpo  derivado  de  la  clase,  y  uLlizar  ese  constructor  para  inicializar  las  propiedades  de  la  clase  base  con  los  valores  necesarios  para  el  escenario.  

class A { public virtual void G() { Console.WriteLine("A.G"); } } class B : A { public override void G() { Console.WriteLine("B.G"); } }

Tipos  e  interfaces  abstractos  Son  mecanismos  para  especificar  abstracciones  de  programación.  Una  abstracción  especifica  un  contrato  al  que  se  deben  adherir  los  herederos  o  implementadores.  

Framework  Design  Guidelines  Diseño  de  extensibilidad  

Miembros  virtuales  Un  miembro  definido  como  virtual  permite  al  desarrollador  cambiar  el  comportamiento  del  miembro  proporcionando  una  implementación  diferente.  

Clases  no  selladas  Una  clase  no  sellada  permite  a  otras  clases  heredar  de  ella.  De  forma  predeterminada,  la  mayoría  de  las  clases  no  deberían  estar  selladas.  Los  desarrolladores  pueden  agregar  un  constructor  a  un  Lpo  derivado  de  la  clase,  y  uLlizar  ese  constructor  para  inicializar  las  propiedades  de  la  clase  base  con  los  valores  necesarios  para  el  escenario.  

Tipos  e  interfaces  abstractos  Son  mecanismos  para  especificar  abstracciones  de  programación.  Una  abstracción  especifica  un  contrato  al  que  se  deben  adherir  los  herederos  o  implementadores.  

Clases  base  para  implementar  abstracciones  Son  clases  diseñadas  para  ayudar  a  los  desarrolladores  a  implementar  clases  abstractas  e  interfaces  (abstracciones).  Proporcionan  algunos  de  los  detalles  de  implementación  de  una  abstracción  y  en  algunos  casos  pueden  uLlizarse  sin  herencia.  

Framework  Design  Guidelines  Diseño  de  extensibilidad  

Miembros  virtuales  Un  miembro  definido  como  virtual  permite  al  desarrollador  cambiar  el  comportamiento  del  miembro  proporcionando  una  implementación  diferente.  

Clases  no  selladas  Una  clase  no  sellada  permite  a  otras  clases  heredar  de  ella.  De  forma  predeterminada,  la  mayoría  de  las  clases  no  deberían  estar  selladas.  Los  desarrolladores  pueden  agregar  un  constructor  a  un  Lpo  derivado  de  la  clase,  y  uLlizar  ese  constructor  para  inicializar  las  propiedades  de  la  clase  base  con  los  valores  necesarios  para  el  escenario.  

Tipos  e  interfaces  abstractos  Son  mecanismos  para  especificar  abstracciones  de  programación.  Una  abstracción  especifica  un  contrato  al  que  se  deben  adherir  los  herederos  o  implementadores.  

Clases  base  para  implementar  abstracciones  Son  clases  diseñadas  para  ayudar  a  los  desarrolladores  a  implementar  clases  abstractas  e  interfaces  (abstracciones).  Proporcionan  algunos  de  los  detalles  de  implementación  de  una  abstracción  y  en  algunos  casos  pueden  uLlizarse  sin  herencia.  

59

Nomenclatura  instrucciones  para  denominar  Lpos  y  miembros  en  las  bibliotecas  

de  clases.    

Diseño  de  6pos  instrucciones  para  uLlizar  clases  estáLcas  y  abstractas,  interfaces,  

enumeraciones  y  estructuras.    

 Diseño  de  miembros  instrucciones  para  diseñar  y  uLlizar  propiedades,  métodos,  

constructores,  campos,  eventos  y  operadores.  Esta  sección  

también  describe  los  procedimientos  recomendados  para  diseñar  

parámetros.    

 

Diseño  de  excepciones  instrucciones  de  diseño  para  diseñar,  iniciar  y  detectar  excepciones.  

Directrices  para  la  programación  Framework  Design  Guidelines  

Diseño  de  extensibilidad  instrucciones  para  diseñar  bibliotecas  que  se  pueden  extender.    

 

Framework  Design  Guidelines  Diseño  de  excepciones  

Generación  de  excepciones  No  devolver  códigos  de  error.  Las  excepciones  son  el  principal  medio  de  informar  de  los  errores  producidos.  

public void ProcessMessage(string message) { if (message == null) { throw new ArgumentNullException("message"); } … }

Diseñar  excepciones  personalizadas  Evitar  la  jerarquía  de  excepciones  profunda.  Derivar  las  excepciones  de  System.Exception  o  de  una  de  las  demás  excepciones  de  base  comunes.  Finalizar  los  nombres  de  clases  de  excepción  con  el  sufijo  Exception.  

public class NewException : BaseException, ISerializable { public NewException() { // Add implementation. } public NewException(string message) { // Add implementation. } public NewException(string message, Exception inner) { // Add implementation. } // This constructor is needed for serialization. protected NewException(SerializationInfo info, StreamingContext context) { // Add implementation. } }

Framework  Design  Guidelines  Diseño  de  excepciones  

Generación  de  excepciones  No  devolver  códigos  de  error.  Las  excepciones  son  el  principal  medio  de  informar  de  los  errores  producidos.  

public void ProcessMessage(string message) { if (message == null) { throw new ArgumentNullException("message"); } … }

Diseñar  excepciones  personalizadas  Evitar  la  jerarquía  de  excepciones  profunda.  Derivar  las  excepciones  de  System.Exception  o  de  una  de  las  demás  excepciones  de  base  comunes.  Finalizar  los  nombres  de  clases  de  excepción  con  el  sufijo  Exception.  

public class YourException : BaseException, ISerializable { public YourException() { // Add implementation. } public YourException(string message) { // Add implementation. } public YourException(string message, Exception inner) { // Add implementation. } // This constructor is needed for serialization. protected YourException(SerializationInfo info, StreamingContext context) { // Add implementation. } }

Clases  y  Objetos  ¿Quién  es  quién?  

Una  clase  define  un  6po  de  objeto,  pero  no  es  propiamente  un  objeto  

Clases  y  Objetos  ¿Quién  es  quién?  

Un  objeto  es  una  en6dad  concreta  basada  en  una  clase.    Se  suele  denominar  instancia  de  una  clase.  

Clases  y  Objetos  ¿Quién  es  quién?  

Los  objetos  sólo  aparecen  en  6empo  de  ejecución  

Clases  y  Objetos  ¿Quién  es  quién?  

Los  objetos  se  pueden  crear  con  la  palabra  clave  new  seguida  del  nombre  de  la  clase  en  la  que  se  

basará  el  objeto  

Clases  y  Objetos  ¿Quién  es  quién?  

new <nombreClase>(<parámetros>)

Customer object1 = new Customer();  

Palabra reservada this Hace  referencia  a  la  instancia  actual  de  la  clase  

Clases  y  Objetos  ¿Quién  es  quién?  

class Person { private string firstName; private string lastName; private int age; public Person(string firstname) { this.firstname = firstname; } }

Calificar  miembros  con  el  fin  de  evitar  ambigüedades  con  nombres  similares:  

Palabra reservada this

Pasar  un  objeto  como  parámetro  a  otros  métodos:  

PrintReport(this)

Declarar  indizadores:  

public int this[int param] { get { return array[param]; } set { array[param] = value; } }

Clases  y  Objetos  ¿Quién  es  quién?  

Tipos,  variables  y  valores  C#  es  un  lenguaje  fuertemente  Lpado.  Todas  las  variables  y  constantes  Lenen  un  Lpo.  

La  biblioteca  de  clases  .NET  Framework  define  un  conjunto  de  Lpos  numéricos  integrados  y  Lpos  más  complejos  que  representan  una  amplia  variedad  de  construcciones  lógicas,  como  el  sistema  de  archivos,  conexiones  de  red,  colecciones  y  matrices  de  objetos  y  fechas.  

Clases  y  Objetos  Tipos,  valores  y  variables  

Al  declarar  una  variable  o  una  constante  en  un  programa,  debemos  especificar  su  6po  o  u6lizar  la  palabra  clave  var  para  permiLr  que  el  compilador  infiera  el  Lpo.  

// Declaration only float temperature; string name; MyClass myClass; // Declaration with initializers (four examples) char firstLetter = 'C'; var limit = 3; int[] source = { 0, 1, 2, 3, 4, 5 }; var query = from item in source where item <= limit select item;

Tipos  integrados  

Tipos  personalizados  

conjunto  estándar  que  C#  proporciona  de  Lpos  numéricos  integrados  para  representar  enteros,  valores  de  punto  flotante,  expresiones  Boolean,  caracteres  de  texto,  valores  decimales  y  otros  Lpos  de  datos.  También  hay  Lpos  object  y  string  integrados.    int, bool, byte, char, float, double, object, string, …

las  construcciones  struct,  class,  interface  y  enum  se  uLlizan  para  crear  sus  propios  Lpos  personalizados.  La  biblioteca  de  clases  de  .NET  Framework  en  sí  es  una  colección  de  Lpos  personalizados  proporcionada  por  MicrosoR  que  el  programador  puede  uLlizar  en  sus  propias  aplicaciones.  

Clases  y  Objetos  Tipos,  valores  y  variables  

Dos  puntos  fundamentales  sobre  el  sistema  de  Lpos  en  .NET  Framework:    

•  admite  el  principio  de  herencia  

 •  cada  uno  de  los  Lpos  se  define  como  un  6po  de  valor  o  un  6po  de  

referencia  

SISTEMA  DE  TIPOS  

Los  Lpos  pueden  derivarse  de  otros  Lpos  denominados  Lpos  base.  El  Lpo  derivado  hereda  (con  algunas  restricciones)  los  métodos,  las  propiedades  y  otros  miembros  del  Lpo  base.  

Esto  incluye  todos  los  Lpos  personalizados  de  la  biblioteca  de  clases  .NET  Framework  y  también  los  Lpos  propios  definidos  por  el  usuario.    Los  Lpos  que  definamos  mediante  la  palabra  clave  struct  son  Lpos  de  valor;  todos  los  Lpos  numéricos  integrados  son  structs.  Los  Lpos  que  definamos  mediante  la  palabra  clave  class  son  Lpos  de  referencia.  

Clases  y  Objetos  Tipos,  valores  y  variables  

SISTEMA  DE  TIPOS  

Clases  y  Objetos  Tipos,  valores  y  variables  Tipos  de  valor  y  referencia  

C#  6ene  dos  variedades  de  6pos:    valor  y  referencia  

 Las  variables  de  6pos  referencia  almacenan  referencias  a  sus  datos  (objetos)  

Las  variables  de  6pos  de  valor  con6enen  directamente  los  datos  

Las  variables  de  Lpo  de  valor  con6enen  directamente  sus  valores  en  la  memoria  asignada  en  la  pila.    Los  Lpos  de  valor  son  todos  los  6pos  de  datos  integrados  básicos  o  una  estructura  definida  por  el  usuario.  Una  excepción  es  el  Lpo  de  datos  string,  que  es  un  Lpo  de  referencia.  

Los  Lpos  de  valor  derivan  de  System.ValueType,  que  a  su  vez  deriva  de  System.Object.      Con  Lpos  de  valor,  cada  variable  Lene  su  propia  copia  de  los  datos,  y  no  es  posible  que  las  operaciones  en  una  variable  afecten  a  otra.        

Tipos  de  valor  

int x = 42; Cuando  la  variable  x  queda  fuera  de  ámbito,  porque  el  método  en  que  se  definió  ha  finalizado  su  ejecución,  el  valor  se  descarta  de  la  pila.  

Clases  y  Objetos  Tipos,  valores  y  variables  Tipos  de  valor  y  referencia  

74

REPRESENTS   DEFAULT  VALUE  

Boolean  value  

8-­‐bit  unsigned  integer  

16-­‐bit  Unicode  character  

128-­‐bit  precise  decimal  values  with  28-­‐29  significant  digits  

64-­‐bit  double-­‐precision  floaIng  point  type  

32-­‐bit  single-­‐precision  floaIng  point  type  

-­‐2.147.483.648  to  2.147.483.647    

false  

0  

’\0’  

0.0M  

0  

true  or  false  

0  to  255  

U  +0000  to  U  +ffff    

(-­‐7.9  x  1028  to  7.9  x  1028)  /  100  to  28    

(+/-­‐)5.0x10-­‐324  to  (+/-­‐)1.7x10308    

-­‐3.4x1038  to  +3.4x1038      

-­‐128  to  127  

RANGE  TYPE  

bool

byte

decimal

char

double

int

float

short

sbyte

32-­‐bit  signed  integer  type  

long 64-­‐bit  signed  integer  type  

8-­‐bit  signed  integer  type  

-­‐923.372.036.854.775.808  to  9.223.372.036.854.775.807    

0.0D  

0.0F  

0L  

0  

16-­‐bit  signed  integer  type  

uint 32-­‐bit  unsigned  integer  type  

ulong 64-­‐bit  unsigned  integer  type  

-­‐32.768  to  32,767      

0  to  4.294.967.295    

0  to  18.446.744.073.709.551.615    

0  

0  

ushort 16-­‐bit  unsigned  integer  type   0  to  65535    

0  

0  

Tipos  de  valor  

Tipos  de  referencia  

Las  variables  de  Lpos  referencia  almacenan  referencias  a  sus  datos  (objetos).    Con  los  Lpos  referencia,  dos  variables  pueden  hacer  referencia  al  mismo  objeto;  por  consiguiente,  las  operaciones  en  una  variable  pueden  afectar  al  objeto  referenciado  por  otra  variable.            

La  memoria  consumida  por  c1  no  se  devuelve  al  montón  cuando  finaliza  el  método;  sólo  se  reclama  cuando  el  sistema  de  recolección  de  elementos  no  uBlizados  de  C#  determina  que  ya  no  la  necesita.  

Customer c1 = new Customer(”Joe");

Las  palabras  clave  siguientes  se  usan  para  declarar  Lpos  de    referencia:  

 

class  

interface  

delegate  

C#  también  proporciona  los  siguientes  Ipos  de  referencia  integrados:  

dynamic  

Object  

string  

Se  dice  que  c1  es  una  referencia  a  un  objeto  de  Lpo  Customer. Esta  referencia  apunta  al  objeto  pero  no  conLene  los  datos.  

Clases  y  Objetos  Tipos,  valores  y  variables  Tipos  de  valor  y  referencia  

Ejemplo  prácLco  namespace  

En  general,  las  clases  se  uLlizan  para  modelar  comportamiento  más  complejo  o  datos  que  se  piensan  modificar  una  vez  creado  un  objeto  de  clase.  Los  structs  son  más  adecuadas  para  pequeñas  estructuras  de  datos  que  conLenen  principalmente  datos  que  no  se  piensan  modificar  una  vez  creado  el  struct.  

Clases  y  Objetos  Tipos,  valores  y  variables  Tipos  de  referencia  

Ejemplo  prácLco  referencias  

Ejemplo  prácLco:  solución  referencias  

Una  clase  es  un  6po  de  referencia  Cuando  se  crea  un  objeto  de  la  clase,  la  variable  a  la  que  se  asigna  el  objeto  sólo  incluye  una  referencia  a  dicha  memoria.  Cuando  la  referencia  a  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.  

Un  struct  es  de  6po  de  valor  Cuando  se  crea  un  struct,  la  variable  a  la  que  se  asigna  incluye  los  datos  reales  del  struct.  Cuando  el  struct  se  asigna  a  una  nueva  variable,  se  copia.  La  nueva  variable  y  la  variable  original  conLenen  por  tanto  dos  copias  independientes  de  los  mismos  datos.  Los  cambios  realizados  en  una  copia  no  afectan  a  la  otra  copia.  

Clases  y  Objetos  Tipos,  valores  y  variables  Tipos  de  referencia  y  de  valor  

Los  structs  son  Bpos  de  valor  y  las  clases  Bpos  de  referencia  

struct

class

class TheClass { public string willIChange; } struct TheStruct { public string willIChange; }

class TestClassAndStruct { static void ClassTaker(TheClass c) { c.willIChange = "Changed"; } static void StructTaker(TheStruct s) { s.willIChange = "Changed"; } static void Main() { TheClass testClass = new TheClass(); TheStruct testStruct = new TheStruct(); testClass.willIChange = "Not Changed"; testStruct.willIChange = "Not Changed"; ClassTaker(testClass); StructTaker(testStruct); Console.WriteLine("Class field = {0}", testClass.willIChange); Console.WriteLine("Struct field = {0}", testStruct.willIChange); // Keep the console window open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } }

Diferencias  entre  pasar  a  un  método  un  struct  y  una  referencia  a  clase  

Clases  y  Objetos  Tipos,  valores  y  variables  Tipos  de  referencia  y  de  valor  

Class field = ? Struct field = ? Press any key to exit.

class TheClass { public string willIChange; } struct TheStruct { public string willIChange; }

class TestClassAndStruct { static void ClassTaker(TheClass c) { c.willIChange = "Changed"; } static void StructTaker(TheStruct s) { s.willIChange = "Changed"; } static void Main() { TheClass testClass = new TheClass(); TheStruct testStruct = new TheStruct(); testClass.willIChange = "Not Changed"; testStruct.willIChange = "Not Changed"; ClassTaker(testClass); StructTaker(testStruct); Console.WriteLine("Class field = {0}", testClass.willIChange); Console.WriteLine("Struct field = {0}", testStruct.willIChange); // Keep the console window open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } }

Class field = Changed Struct field = Not Changed Press any key to exit.

Diferencias  entre  pasar  a  un  método  un  struct  y  una  referencia  a  clase  

Clases  y  Objetos  Tipos,  valores  y  variables  Tipos  de  referencia  y  de  valor  

Ejemplo  prácLco  

Swapping  elephants  

Ejemplo  prácLco:  solución  

Swapping  elephants  

Recordemos  lo  que  decíamos  hace  un  rato…    

“Las  variables  de  Ipos  referencia  almacenan  referencias  a  sus  datos  (objetos).    Con  los  Ipos  referencia,  dos  variables  pueden  hacer  referencia  al  mismo  objeto;  por  consiguiente,  las  operaciones  en  una  variable  pueden  afectar  al  objeto  referenciado  por  otra  variable.”  

Recordemos  qué  decíamos  hace  un  rato…    

“Las  variables  de  Ipos  referencia  almacenan  referencias  a  sus  datos  (objetos).    Con  los  Ipos  referencia,  dos  variables  pueden  hacer  referencia  al  mismo  objeto;  por  consiguiente,  las  operaciones  en  una  variable  pueden  afectar  al  objeto  referenciado  por  otra  variable.”  

         

Clases  y  Objetos  Tipos,  valores  y  variables  

SISTEMA  DE  TIPOS  

Nullables  

int? i = 10; double? d1 = 3.14; bool? flag = null; char? letter = 'a'; int?[] arr = new int?[10];

Tipo  de  dato  especial  que  nos  permite  indicar  a  las  variables  de  este  Lpo,  además  de  los  valores  del  rango  admiLdo,  el  valor  null.    

System.Nullable<T> variable_name  T? variable_name  

Los  Lpos  que  aceptan  valores  NULL  se  declaran  de  dos  formas:  

T  es  el  Lpo  subyacente  del  Lpo  que  acepta  valores  NULL.  T  puede  ser  cualquier  Lpo  de  valor  incluido  struct;  no  puede  ser  Lpo  de  referencia.  

using System; namespace CalculatorApplication { class NullablesAtShow { static void Main(string[] args) { int? num1 = null; int? num2 = 45; double? num3 = new double?(); double? num4 = 3.1415; bool? boolval = new bool?(); // display the values Console.WriteLine("Nullables at Show: {0}, {1}, {2}, {3}", num1, num2, num3, num4); Console.WriteLine("A Nullable boolean value: {0}”, boolval); Console.ReadLine(); } } }

?

Nullables  EJEMPLO  PRÁCTICO  

using System; namespace CalculatorApplication { class NullablesAtShow { static void Main(string[] args) { int? num1 = null; int? num2 = 45; double? num3 = new double?(); double? num4 = 3.1415; bool? boolval = new bool?(); // display the values Console.WriteLine("Nullables at Show: {0}, {1}, {2}, {3}", num1, num2, num3, num4); Console.WriteLine("A Nullable boolean value: {0}”, boolval); Console.ReadLine(); } } }

EJEMPLO  PRÁCTICO  

Nullables at Show: , 45 , , 3.1415 A Nullable boolean value:

Nullables  

Clases  y  Objetos  Tipos,  valores  y  variables  Nullables  

Este  Lpo  de  dato  cuenta  con  dos  propiedades  de  sólo  lectura  que  serán  muy  ú6les  a  la  hora  de  trabajar  con  ellos.  

int? x = 10; if (x.HasValue) { System.Console.WriteLine(x.Value); } else { System.Console.WriteLine("Undefined"); }

Es  de  Lpo  bool.  Se  establece  como  true  cuando  la  variable  conLene  un  valor  que  no  es  null.

HasValue

Value  es  del  mismo  Lpo  que  el  Lpo  subyacente.  Si  HasValue  es  true,  Value  conLene  un  valor  significaLvo.  Si  HasValue  es  false,  al  tener  acceso  a  Value  se  producirá  una  excepción  InvalidOperationException.  

Value int? y = 10; if (y != null) { System.Console.WriteLine(y.Value); } else { System.Console.WriteLine("Undefined"); }

Ejemplo  prácLco  

Nullables  

int i; i = "Hello"; // Error: "Cannot implicitly convert type 'string' to 'int'"

Dado  que  a  C#  se  le  asignan  Lpos  estáLcos  en  Lempo  de  compilación,  después  de  declarar  una  variable,  no  se  puede  volver  a  declarar  ni  tampoco  uLlizar  para  almacenar  valores  de  otro  Lpo,  a  menos  que  dicho  Lpo  pueda  converLrse  en  el  Lpo  de  la  variable.  

CONVERSIÓN  DE  TIPOS  

Clases  y  Objetos  Tipos,  valores  y  variables  Conversión  de  6pos  

 

93

Conversiones  implícitas  

En   los   Lpos   numéricos   integrados,  puede   realizarse   una   conversión  implícita   cuando   el   valor   que   se   va   a  almacenar  puede  ajustarse  a  la  variable  sin   necesidad   de   truncamiento   o  redondeo.  

int num = 2147483647; long bigNum = num;

una  variable  de  Bpo  long  (entero  de  8  bytes)  puede  almacenar  cualquier  valor  que  pueda  almacenar  a  su  vez  

un  elemento  int  (4  bytes  en  un  equipo  de  32  bits)  

Conversiones  explícitas  

Requieren  un  operador  de  conversión.  La   conversión   se   requiere   cuando   es  posible   que   se   pierda   información   en  el  proceso.      El   compilador   requiere   que   se   realice  una   conversión   explícita,   denominada  conversión  de  Lpo.    

double x = 1234.7; int a; // Cast double to int. a = (int)x; // Output // 1234

Conversiones    definidas  por  el  usuario  

Se   realizan   a   través   de   métodos   especiales   que   el  usuario   puede   definir   para   habilitar   las   conversiones  explícitas   e   implícitas   entre   Lpos   personalizados   que  no  Lenen  una  relación  de  clase  base-­‐clase  derivada.  

class SampleClass { public static explicit operator SampleClass(int i) { SampleClass temp = new SampleClass(); // code to convert from int to SampleClass... return temp; } }

Conversiones  con  clases  auxiliares  

Para   realizar   conversiones   entre   Lpos  no  compaLbles,   como   los  enteros  y   los  objetos   System.DateTime,   o   bien  cadenas   hexadecimales   y   matrices   de  by t e s ,   puede   uL l i z a r   l a   c l a s e  S y s t em .B i tConve r t e r ,   l a   c l a s e  System.Convert  y  los  métodos  Parse  de  los   Lpos   numéricos   integrados,   como  Int32.Parse.  

Convert.ToInt32("1234")

Las  conversiones  declaradas  como  implicit  se  producen  automáBcamente  cuando  son  necesarias.    Las  conversiones  declaradas  como  explicit  requieren  que  se  llame  a  una  conversión  de  Bpos.    Todas  las  conversiones  se  deben  declarar  como  staBc.  

Clases  y  Objetos  Tipos,  valores  y  variables  Conversión  de  6pos  

 

COFFEE  BREAK  El  InsLtuto  Tecnológico  de  Massachusess  (MIT)  ha  realizado  un  estudio  que  señala  que  el  “coffee  break  ”  puede  incrementar  el  rendimiento  laboral  en  8%.  El  moLvo  está  más  en  el  descanso  y  la  relación  con  los  compañeros,  ya  que  ésta  genera  moLvación  y  aumenta  la  socialización  produciendo  confianza  y  mayor  producLvidad.  

95

posibilidad  de  crear  nuevas  clases  basadas  en  una  clase  existente.  

Programación  Orientada  a  Objetos  Los  4  pilares  

Herencia  

Abstracción  

palabra  griega  que  significa  "con  muchas  formas”.  Tareas  similares  son  realizadas  por  métodos  con  mismo  nombre.  

Polimorfismo  

Expresa  las  caracterísLcas  esenciales  de  un  objeto.  

ocultamiento  del  estado,  es  decir,  de  los  datos  de  un  objeto  de  manera  que  sólo  se  pueda  cambiar  mediante  las  operaciones  definidas  para  ese  objeto.  

Encapsulamiento  

96

Child  B  Child  A   Child  C  

Parent  

Programación  Orientada  a  Objetos  Los  4  pilares  Herencia  

La  herencia  es  transi6va.    Las  clases  Child  D  y  Child  E  heredan   los  miembros  declarados  en  Child  A  y  Parent.       Child  D   Child  E  

Una   clase   derivada   sólo   puede   tener   una   clase  base  directa.  

La   clase   derivada   obLene   implícitamente   todos  los   miembros   de   la   clase   base,   salvo   sus  constructores  y  destructores.  

No  se  admite   la  herencia  múl6ple;  es  decir,  sólo  se   puede   especificar   una   clase   base   para   una  clase  derivada.  

public class Parent { }

public class ChildA : Parent { }

public class ChildD : ChildA { }

public class ChildE : ChildA { }

public class ChildC : Parent { }

97Los  4  pilares  Herencia  

98Los  4  pilares  Herencia  

99Los  4  pilares  Herencia  

100

Hacer  uso  de  :  para  heredar  de  una  clase  padre  

public class B : A { }

Clases  y  Objetos  Programación  Orientada  a  Objetos  Herencia  

 

101Los  4  pilares  Herencia  

When  a  subclass  inherits  from  a  base  class,  all  of  the  fields,  properLes,  and  methods  in  the  base  class  are  automa6cally  added  to  the  subclass.  

102

Para  especificar  que  una  clase  NO  se  puede  usar  como  clase  base  

public sealed class A { }

Clases  y  Objetos  Programación  Orientada  a  Objetos  Herencia  

 

Palabra reservada sealed

103Los  4  pilares  Herencia  

Qué  podemos  hacer  si  una  clase  base  6ene  un  método  que  una  subclase  necesita  modificar?  

Algunas  aves  no  vuelan!  

104

Cuando  una  clase  base  declara  un  método  como  virtual,  una  clase  derivada  puede  sobreescribir  

el  método  con  su  propia  implementación  

Clases  y  Objetos  Programación  Orientada  a  Objetos  Herencia  

 

105

Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

Child  A  

Parent  1   Parent  2  Herencia  múl6ple  en  C#?  

Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

Herencia  múl6ple  en  C#?  

Child  A  

Parent  1   Parent  2  

No   se   admite   la   herencia  múlLple;   es   decir,   sólo  se   puede   especificar   una   clase   base   para   una  clase  derivada.  

Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

Herencia  múl6ple  en  C#?  

Child  A  

Parent  1   Parent  2  

No   se   admite   la   herencia  múlLple;   es   decir,   sólo  se   puede   especificar   una   clase   base   para   una  clase  derivada.  

Se  permiten  múl6ples  interfaces.  

Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

…pero  qué  son  los  Interfaces?  

Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

contrato  en  donde  se  especifican  las  definiciones  de  un  grupo  de  funcionalidades  relacionadas.  

…pero  qué  son  los  Interfaces?  

Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

contrato  en  donde  se  especifican  las  definiciones  de  un  grupo  de  funcionalidades  relacionadas.    

o  definiciones  de  métodos,  eventos,  indizadores  y  propiedades  que  una  clase  o  struct  debe  cumplir.  

…pero  qué  son  los  Interfaces?  

Clases  y  Objetos  Programación  Orientada  a  Objetos  Interfaces  

public interface ISampleInterface { void SampleMethod(); } public class ImplementationClass : ISampleInterface { void SampleMethod() { // Method implementation. } }

115

Las  interfaces  no  con6enen  implementaciones  de  métodos.      

Una   interfaz   es   como   una   clase   base   abstracta.   Cualquier   clase   o   struct   que   implemente   la   interfaz   debe  implementar  todos  sus  miembros.  

Las  interfaces  pueden  contener  eventos,  métodos,  indizadores  y  propiedades.  

Una  interfaz  no  puede  ser  instanciada  directamente.  

Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

Una  clase  o  struct  puede  implementar  varias  interfaces.  Una  clase  puede  heredar  una  clase  base  y  también  implementar  una  o  más  interfaces.      

Una  interfaz  6ene  las  siguientes  propiedades:  

Una  interfaz  puede  heredar  de  una  o  varias  interfaces  base.      

116Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

public interface IFlyable { void Fly(); } public class Bird : IFlyable { public void Fly() { } } public class Plane : IFlyable { public void Fly() { } }

List<IFlyable> things = GetBirdInstancesAndPlaneInstancesMixed(); foreach(IFlyable item in things) { item.Fly(); }

Child  A  

Parent  1   Interface  1  

Clases  y  Objetos  Programación  Orientada  a  Objetos  

 

Con  las  interfaces,  a  través  de  sus  contratos,  podemos  crear  el  efecto  de  herencia  múl6ple  

Podemos  observar  como  la  clase  ChildA  hereda  de  la  clase  Parent1  y  también  implementa  la  interfaz  Interface1.  Se  suele  decir  que:    

extends  

ChildA  extends  Parent1 ChildA  implements  Interface1    

implements  

Herencia  e  interfaces  

What  happens  if  you  have  a  bee  that  needs  to  sLng  and  collect  nectar?  

Herencia  e  interfaces  

Ejemplo  prácLco:  Beehive  simulator  

Herencia  e  Interfaces  

Analizar  el  código  fuente  del  ejemplo  de  la  colmena  en  GitHub:  

hsps://github.com/dbaker3/head-­‐first-­‐c-­‐sharp/tree/master/BeehiveSimulatorCh7    

122

posibilidad  de  crear  nuevas  clases  basadas  en  una  clase  existente.  

Programación  Orientada  a  Objetos  Los  4  pilares  

Herencia  

Expresa  las  caracterísLcas  esenciales  de  un  objeto.  

Abstracción  

palabra  griega  que  significa  "con  muchas  formas”.  Tareas  similares  son  realizadas  por  métodos  con  mismo  nombre.  

Polimorfismo  

ocultamiento  del  estado,  es  decir,  de  los  datos  de  un  objeto  de  manera  que  sólo  se  pueda  cambiar  mediante  las  operaciones  definidas  para  ese  objeto.  

Encapsulamiento  

123Los  4  pilares  Abstracción  

Algunas  clases  nunca  pueden  ser  instanciadas.  Recordemos  nuestra  jerarquía  en  el  simulador  del  zoo.  DefiniLvamente  teníamos  grupos  de  instancias  de  leones,  hipopótamos  y  perros.  Pero  ¿qué  pasa  con  las  clases  Feline  y  Canine?  ¿y  con  Animal?  Hay  clases  que  simplemente  no  necesitan  ser  instanciadas…y  de  hecho,  no  6ene  ningún  sen6do  que  se  instancien.  

Clases  abstractas  

124Los  4  pilares  Abstracción  

Clases  abstractas  

Una  clase  abstracta  es  como  una  clase  normal.  ConLene  campos  y  métodos  y  pueden  heredar  de  otras,  exactamente  igual  que  una  clase  normal.    

 Una  clase  abstracta  es  como  un  interfaz.  Cuando  creamos  una  clase  que  implementa  un  interfaz,  nos  comprometemos  a  implementar  todas  las  propiedades  y  métodos  definidos  en  el  interfaz.  Una  clase  abstracta  funciona  de  la  misma  forma,  puede  incluir  declaraciones  de  propiedades  y  métodos  que,  al  igual  que  un  interfaz,  deben  ser  implementados  por  las  clases  heredadas.    

 Pero  una  clase  abstracta  no  puede  ser  instanciada.  La  principal  diferencia  entre  una  clase  abstracta  y  una  clase  concreta  es  que  no  es  posible  hacer  un  new  y  crear  una  instancias  de  la  clase  abstracta.  

 

125Los  4  pilares  Abstracción  

Clases  abstractas  

Una  clase  abstracta  es  como  una  clase  normal.  ConLene  campos  y  métodos  y  pueden  heredar  de  otras,  exactamente  igual  que  una  clase  normal.    

 Una  clase  abstracta  es  como  un  interfaz.  Cuando  creamos  una  clase  que  implementa  un  interfaz,  nos  comprometemos  a  implementar  todas  las  propiedades  y  métodos  definidos  en  el  interfaz.  Una  clase  abstracta  funciona  de  la  misma  forma,  puede  incluir  declaraciones  de  propiedades  y  métodos  que,  al  igual  que  un  interfaz,  deben  ser  implementados  por  las  clases  heredadas.    

 Pero  una  clase  abstracta  no  puede  ser  instanciada.  La  principal  diferencia  entre  una  clase  abstracta  y  una  clase  concreta  es  que  no  es  posible  hacer  un  new  y  crear  una  instancias  de  la  clase  abstracta.  

 

126Los  4  pilares  Abstracción  

Clases  abstractas  

Una  clase  abstracta  es  como  una  clase  normal.  ConLene  campos  y  métodos  y  pueden  heredar  de  otras,  exactamente  igual  que  una  clase  normal.    

 Una  clase  abstracta  es  como  un  interfaz.  Cuando  creamos  una  clase  que  implementa  un  interfaz,  nos  comprometemos  a  implementar  todas  las  propiedades  y  métodos  definidos  en  el  interfaz.  Una  clase  abstracta  funciona  de  la  misma  forma,  puede  incluir  declaraciones  de  propiedades  y  métodos  que,  al  igual  que  un  interfaz,  deben  ser  implementados  por  las  clases  heredadas.    

 Pero  una  clase  abstracta  no  puede  ser  instanciada.  La  principal  diferencia  entre  una  clase  abstracta  y  una  clase  concreta  es  que  no  es  posible  hacer  un  new  y  crear  una  instancias  de  la  clase  abstracta.  

 

public abstract class Stream { public abstract void Write(char ch); public void WriteString(string s) { foreach (char ch in s) { Write(s); } } } public class File : Stream { public override void Write(char ch) { ... write ch to disk... } }

Clases  y  Objetos  Programación  Orientada  a  Objetos  Abstracción  

 

public abstract class Stream { public abstract void Write(char ch); public void WriteString(string s) { foreach (char ch in s) { Write(s); } } } public class File : Stream { public override void Write(char ch) { ... write ch to disk... } }

Clases  y  Objetos  Programación  Orientada  a  Objetos  Abstracción  

 

Los  métodos  abstract  no  Lenen  

implementación  

public abstract class Stream { public abstract void Write(char ch); public void WriteString(string s) { foreach (char ch in s) { Write(s); } } } public class File : Stream { public override void Write(char ch) { ... write ch to disk... } }

Clases  y  Objetos  Programación  Orientada  a  Objetos  Abstracción  

 

Los  métodos  abstract  no  Lenen  

implementación  

Los  métodos  abstract  son  virtual implícitamente    

public abstract class Stream { public abstract void Write(char ch); public void WriteString(string s) { foreach (char ch in s) { Write(s); } } } public class File : Stream { public override void Write(char ch) { ... write ch to disk... } }

Clases  y  Objetos  Programación  Orientada  a  Objetos  Abstracción  

 

Los  métodos  abstract  no  Lenen  

implementación  

Los  métodos  abstract  son  virtual implícitamente    

Si  una  clase  Lene  métodos  abstract,  la  clase  debe  declararse  también  como  

abstract

public abstract class Stream { public abstract void Write(char ch); public void WriteString(string s) { foreach (char ch in s) { Write(s); } } } public class File : Stream { public override void Write(char ch) { ... write ch to disk... } }

Clases  y  Objetos  Programación  Orientada  a  Objetos  Abstracción  

 

Los  métodos  abstract  no  Lenen  

implementación  

Los  métodos  abstract  son  virtual implícitamente    

Si  una  clase  Lene  métodos  abstract,  la  clase  debe  declararse  también  como  

abstract

No  pueden  crearse  objetos  de  clases  abstractas  

new Stream()

public abstract class Stream { public abstract void Write(char ch); public void WriteString(string s) { foreach (char ch in s) { Write(s); } } } public class File : Stream { public override void Write(char ch) { ... write ch to disk... } }

Clases  y  Objetos  Programación  Orientada  a  Objetos  Abstracción  

 

Los  métodos  abstract  no  Lenen  

implementación  

Los  métodos  abstract  son  virtual implícitamente    

Si  un  clase  Lene  métodos  abstract,  la  clase  debe  declararse  también  como  

abstract

No  pueden  crearse  objetos  de  clases  abstractas  

new Stream()

Ejemplo  prácLco:  Planet  Mission  

Abstract  classes  

Analizar  el  código  fuente  del  ejemplo  Planet  Mission  en  Codeplex  (chapter  7)  :  

hsps://hfcsharp.codeplex.com  

134

posibilidad  de  crear  nuevas  clases  basadas  en  una  clase  existente.  

Programación  Orientada  a  Objetos  Los  4  pilares  

Herencia  

Expresa  las  caracterísLcas  esenciales  de  un  objeto.  

Abstracción  

palabra  griega  que  significa  "con  muchas  formas”.  Tareas  similares  son  realizadas  por  métodos  con  mismo  nombre.  

Polimorfismo  

ocultamiento  del  estado,  es  decir,  de  los  datos  de  un  objeto  de  manera  que  sólo  se  pueda  cambiar  mediante  las  operaciones  definidas  para  ese  objeto.  

Encapsulamiento  

135

Estaremos  haciendo  uso  de  polimorfismo  cuando  tomemos  una  instancia  de  una  clase    

y  la  u6licemos  en  una  declaración  o  un  método  que  espera  un  6po  diferente;    como  una  clase  padre  o  una  interfaz    

que  la  clase  implemente  

Clases  y  Objetos  Programación  Orientada  a  Objetos  Polimorfismo  

 

class Shape { // A few example members public int X { get; private set; } public int Y { get; private set; } public int Height { get; set; } public int Width { get; set; } // Virtual method public virtual void Draw() { Console.WriteLine("Performing base class drawing tasks"); } }

class Circle : Shape { public override void Draw() { // Code to draw a circle... Console.WriteLine("Drawing a circle"); base.Draw(); } }

class Rectangle : Shape { public override void Draw() { // Code to draw a rectangle... Console.WriteLine("Drawing a rectangle"); base.Draw(); } }

public class Triangle : Shape { public override void Draw() { // Code to draw a triangle... Console.WriteLine("Drawing a triangle"); base.Draw(); } }

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. IList<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle()); shapes.Add(new Triangle()); shapes.Add(new Circle()); // Polymorphism at work #2: the virtual method Draw is // invoked on each of the derived classes, not the base class. foreach (Shape s in shapes) { s.Draw(); } // Keep the console open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } }

?

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. System.Collections.Generic.List<Shape> shapes = new System.Collections.Generic.List<Shape>(); shapes.Add(new Rectangle()); shapes.Add(new Triangle()); shapes.Add(new Circle()); // Polymorphism at work #2: the virtual method Draw is // invoked on each of the derived classes, not the base class. foreach (Shape s in shapes) { s.Draw(); } // Keep the console open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } }

class Circle : Shape { public override void Draw() { // Code to draw a circle... Console.WriteLine("Drawing a circle"); base.Draw(); } }

class Shape { // A few example members public int X { get; private set; } public int Y { get; private set; } public int Height { get; set; } public int Width { get; set; } // Virtual method public virtual void Draw() { Console.WriteLine("Performing base class drawing tasks"); } }

Drawing a rectangle Performing base class drawing tasks Drawing a triangle Performing base class drawing tasks Drawing a circle Performing base class drawing tasks Press any key to exit.

public class Triangle : Shape { public override void Draw() { // Code to draw a triangle... Console.WriteLine("Drawing a triangle"); base.Draw(); } }

Ejemplo  prácLco  

Let’s  build  a  house  

Analizar  el  código  fuente  del  ejemplo  Let’s  build  a  house  en  Codeplex  (chapter  7)  :  

hsps://hfcsharp.codeplex.com  

Garbage  Collector  Recolector  de  Basura  

142

Qué  es?  Es  el  responsable  de  liberar  

memoria,  eliminando  todos  aquellos  objetos  que  están  inaccesibles.  

Qué  es  un  objeto  inaccesible?  

Un  objeto  inaccesible  es  un  objeto  al  cual  NO  apunta  ninguna  referencia;  es  decir,  un  objeto  al  cual  no  se  puede  

acceder  de  ninguna  manera.  

Cuándo  libera  memoria  el  Garbage  Collector?  El  motor  de  opLmización  del  

recolector  de  elementos  no  uLlizados  determina  cuál  es  el  mejor  momento  para  realizar  una  recolección,  según  

las  asignaciones  que  se  estén  realizando.  

Puedo  hacer  algo  cuando  un  objeto  es  destruido  por  el  

Garbage  Collector?  Sí.  Hay  un  metodo  especial  que  el  Garbage  Collector  invoca  cuando  destruye  un  objeto:  destructor    

No  libera  las  referencias  en  el  momento  en  el  que  se  dejan  de  uLlizar  

Garbage  Collector  Recolector  de  basura  

143

Generación  0  

Generación  0  Es  la  generación  más  joven  y  conLene  los  objetos  de  corta  duración.  Un  ejemplo  de  objeto  de  corta  duración  es  una  variable  temporal.  La  recolección  de  elementos  no  uLlizados  se  produce  con  mayor  frecuencia  en  esta  generación.    Los  objetos  recién  asignados  consLtuyen  una  nueva  generación  de  objetos  e  implícitamente  son  recolecciones  de  generación  0,  a  menos  que  sean  objetos  grandes,  en  cuyo  caso  entran  en  el  montón  de  objetos  grandes  en  una  recolección  de  la  generación  2.    La  mayoría  de  los  objetos  se  reclaman  para  la  recolección  de  elementos  no  uLlizados  en  la  generación  0  y  no  sobreviven  a  la  generación  siguiente.  

Generación  1  Esta  generación  conLene  objetos  de  corta  duración  y  sirve  como  búfer  entre  los  objetos  de  corta  y  larga  duración.  

Generación  2  Esta  generación  conLene  los  objetos  de  larga  duración.  Un  ejemplo  de  objeto  de  larga  duración  es  un  objeto  de  una  aplicación  de  servidor  que  conLene  datos  estáLcos  que  están  acLvos  mientras  dura  el  proceso.  

Hay  tres  generaciones  de  objetos  en  el  montón:  

Organización  de  memoria  El  montón  se  organiza  en  generaciones,  para  poder  administrar  objetos  de  larga  y  corta  duración.    84%  

Garbage  Collector  Recolector  de  basura  

Generación  1  

Generación  2  

Para  que  un  objeto  se  mantenga  en  el  montón  de  memoria,  éste  debe  ser  refenciado.  Una  vez  deja  de  ser  referenciado,  pasado  un  Lempo,  el  objeto  es  eliminado.  

Garbage  Collector  Recolector  de  basura  

                 

Dispose  vs.  

Finalizer  

Patrones  de  Diseño  Breve  introducción  

149Patrones  de  Diseño  Breve  introducción  

Los  patrones  de  diseño  son  el  esqueleto  de  las  soluciones  a  problemas  comunes  en  el  desarrollo  de  soXware.  

150Patrones  de  Diseño  Breve  introducción  

Los  patrones  de  diseño  brindan  una  solución  ya  probada  y  documentada  a  problemas  de  desarrollo  de  soRware  que  están  sujetos  a  contextos  similares.  

Creacionales  solucionan  problemas  de  creación  de  instancias.  Nos  ayudan  a  encapsular  y  abstraer  dicha  creación  (Factory,  Singleton,  Builder,  etc.)  

Estructurales  solucionan  problemas  de  composición  (agregación)  de  clases  y  objetos  (Adapter,  Facade,  Proxy,  Composite,  etc.)  

De  comportamiento  ofrecen  soluciones  respecto  a  la  interacción  y  responsabilidades  entre  clases  y  objetos,  así  como  los  algoritmos  que  encapsulan  (Iterator,  Observer,  Strategy,  State,  etc.)  

151Patrones  de  Diseño  Breve  introducción  

C#  advanced  07-­‐Design  paserns  

por  Mohammad  Shaker  

Enumerados  y  Colecciones  Flexibilidad  para  almacenar,  ordenar  y  

gesLonar  gran  canLdad  de  datos  

153Enumerados  y  Colecciones  Breve  introducción  

enumeración  Manera  eficaz  de  definir  un  conjunto  de  constantes  integrales  con  nombre  que  pueden  asignarse  a  una  variable  

enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday };

El   desarrollador   ve   claramente   qué   valores   son  válidos  para  la  variable.      

En   Visual   Studio,   IntelliSense   muestra   los   valores  definidos.      

De  forma  predeterminada,  el  Ipo  subyacente  de  cada  elemento  de  la  enumeración  es  int

Days today = Days.Monday; int dayNumber =(int)today; Console.WriteLine("{0} is day number #{1}.", today, dayNumber);

Monday is day number #0

154Enumerados  y  Colecciones  Breve  introducción  

155Enumerados  y  Colecciones  Breve  introducción  

156Enumerados  y  Colecciones  Breve  introducción  

Colecciones  Estructura  de  datos  flexible  para  trabajar  con  grupos  de  objetos  

.NET  Framework  proporciona  colecciones  en  los  siguientes  espacios  de  nombres:      

System.Collections.Generic System.Collections.Concurrent System.Collections    

Hacen  uso  de  la  memoria  dinámicamente.      

Capacidad  para  enumerar  la  colección.      

Ofrecen   métodos   para   agregar,   quitar   o   buscar  elementos  en  la  colección.      

Genéricas  Se  agregaron  en  la  versión  2.0  de  .NET  Framework  y  son  colecciones  fuertemente  Lpadas  en  Lempo  de  

compilación.  

No  genéricas  Almacenan  elementos  como  

Object  y  requieren  conversión.  

Enumerados  y  Colecciones  Breve  introducción  

Las  colecciones  almacenan  elementos  de…  cualquier  6po  

Enumerados  y  Colecciones  Breve  introducción  

Las  colecciones  almacenan  elementos  de…  cualquier  6po  

List<T> name = new List<T>

Enumerados  y  Colecciones  Breve  introducción  

Las  colecciones  almacenan  elementos  de…  cualquier  6po  

List<T> name = new List<T>

La  <T> en  List<T>  significa  que  la  lista  es  genérica.    La  T  es  reemplazada  por  un  Lpo  –  List<string>  significa  una  lista  de  strings.  

 

Enumerados  y  Colecciones  Breve  introducción  

Las  colecciones  almacenan  elementos  de…  cualquier  6po  

List<T> name = new List<T>

La  <T> en  List<T>  significa  que  la  lista  es  genérica.    La  T  es  reemplazada  por  un  Lpo  –  List<string>  significa  una  lista  de  strings.  

 

List<string> strings = new List<string>(); List<int> ints = new List<int>(); List<byte> bytes = new List<byte>(); List<User> users = new List<User>(); List<WorkItem> workItems = new List<WorkItem>();

Las  listas  son  más  flexibles  que  los  arrays  

List<string> salmons = new List<string>(); salmons.Add("chinook"); salmons.Add("coho"); salmons.Add("pink"); salmons.Add("sockeye"); // Iterate through the list. foreach (string salmon in salmons) { Console.Write(salmon + " "); } // Output: chinook coho pink sockeye

List  of  Ducks  

Enumerados  y  Colecciones  Breve  introducción  

LinkedList  Acceso  a  elementos  de  forma  secuencial.    

ObservableCollec6on  Recepción  de  noLficaciones  cuando  se  quitan  o  se  

agregan  elementos  a  la  colección.    

 Stack  LIFO  (Last  Input  First  Output).    

 

HashSet  Conjunto  de  funciones  matemáLcas.    

 

Dic6onary  Almacena  elementos  como  pares  clave/valor  para  una  

consulta  rápida  por  clave.    

List  Acceso  a  elementos  por  índice.    

Queue  FIFO  (First  Input  First  Output).    

SortedList  Colección  ordenada.    

COFFEE  BREAK  El  InsLtuto  Tecnológico  de  Massachusess  (MIT)  ha  realizado  un  estudio  que  señala  que  el  “coffee  break  ”  puede  incrementar  el  rendimiento  laboral  en  8%.  El  moLvo  está  más  en  el  descanso  y  la  relación  con  los  compañeros,  ya  que  ésta  genera  moLvación  y  aumenta  la  socialización  produciendo  confianza  y  mayor  producLvidad.  

Atributos,  Ensamblados  y  Reflec6on  

Bloques  de  creación  de  .NET  Framework  

[Author("Brian Kernighan")] class MyClass { ... }

ATRIBUTOS  

Atributos,  Ensamblados  y  Reflec6on  Bloques  de  creación  de  .NET  Framework  

Se  puede  decir  que  un  atributo  es  una  clase  que  se  puede  uLlizar  para  “decorar”  a  otras  clases  o  elementos  (métodos,  variables,  etc.)  

Qué esLos  atributos  se  guardan  con  los  datos  y  puesto  que  ofrecen  información  sobre  éstos,  se  les  llama  metadatos.  

MetadatosDicha  información  se  guarda  en  6empo  de  compilación,  en  el  assembly,  junto  a  los  datos  y  puede  ser  consultada  durante  la  ejecución.  

Assembly

Permiten  al  desarrollador  especificar  información  declaraIva  en  enLdades  definidas  en  el  código  

Todos  los  atributos  heredan  directa    o  indirectamente  de  System.Attribute

Atributos,  Ensamblados  y  Reflec6on  

[Author("Brian Kernighan")] class MyClass { ... }

[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct) ] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } }

[Author("John Curry")] struct MyStruct { ... }

especifica  los  elementos  del  lenguaje  a  los  que  se  puede  aplicar  el  atributo  

Bloques  de  creación  de  .NET  Framework  

Todos  los  atributos  heredan  directa    o  indirectamente  de  System.Attribute

[Author("Brian Kernighan")] class MyClass { ... }

[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct) ] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } }

[Author("John Curry")] struct MyStruct { ... }

especifica  los  elementos  del  lenguaje  a  los  que  se  puede  aplicar  el  atributo  

Atributos,  Ensamblados  y  Reflec6on  Bloques  de  creación  de  .NET  Framework  

Todos  los  atributos  heredan  directa    o  indirectamente  de  System.Attribute

[Author("Brian Kernighan")] class MyClass { ... }

[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct) ] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } }

[Author("John Curry")] struct MyStruct { ... }

especifica  los  elementos  del  lenguaje  a  los  que  se  puede  aplicar  el  atributo  

Atributos,  Ensamblados  y  Reflec6on  Bloques  de  creación  de  .NET  Framework  

172

System.AttributeUsage  es  un  atributo  que  puede  aplicarse  a  definiciones  de  atributos  personalizados  para  controlar  cómo  se  aplica  el  nuevo  atributo.    

 

System.AttributeUsage

All,  Assembly,  Class,  Constructor,  Delegate,  Enum,  Event,  Field,  GenericParameter,  Interface,  Method,  Module,  Parameter,  Property,  ReturnValue,  Struct    

[System.AttributeUsage( )] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } }

173

System.AttributeUsage  es  un  atributo  que  puede  aplicarse  a  definiciones  de  atributos  personalizados  para  controlar  cómo  se  aplica  el  nuevo  atributo.    

 

System.AttributeUsage

All,  Assembly,  Class,  Constructor,  Delegate,  Enum,  Event,  Field,  GenericParameter,  Interface,  Method,  Module,  Parameter,  Property,  ReturnValue,  Struct    

[System.AttributeUsage(System.AttributeTargets.Class)] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } }

[Author("Brian Kernighan")] class MyClass { ... }

174

System.AttributeUsage  es  un  atributo  que  puede  aplicarse  a  definiciones  de  atributos  personalizados  para  controlar  cómo  se  aplica  el  nuevo  atributo.    

 

System.AttributeUsage

All,  Assembly,  Class,  Constructor,  Delegate,  Enum,  Event,  Field,  GenericParameter,  Interface,  Method,  Module,  Parameter,  Property,  ReturnValue,  Struct    

[System.AttributeUsage(System.AttributeTargets.Method)] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } }

[Author("Brian Kernighan")] void MyMethod1(int param1) { ... }

[Author("Brian Kernighan")] bool MyMethod2() { ... }

175

System.AttributeUsage  es  un  atributo  que  puede  aplicarse  a  definiciones  de  atributos  personalizados  para  controlar  cómo  se  aplica  el  nuevo  atributo.    

 

System.AttributeUsage

All,  Assembly,  Class,  Constructor,  Delegate,  Enum,  Event,  Field,  GenericParameter,  Interface,  Method,  Module,  Parameter,  Property,  ReturnValue,  Struct    

[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Method | System.AttributeTargets.Parameter)] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } }

[Author("Brian Kernighan")] bool MyMethod2() { ... }

[Author(”John Curry")] class MyClass { ... }

bool MyMethod2([Author("Brian Kernighan")] int param1) { ... }

[Serializable]

[Serializable] Indica  que  el  objeto  es  Serializable

[Serializable] Indica  que  el  objeto  es  Serializable

El  objeto  puede  converIrse  en  una  secuencia  de  bytes  para  almacenar  el  objeto  o  transmiIrlo  a  memoria,  una  base  de  datos  o  a  un  archivo.

public class Test { public static void Main() { //Creates a new TestSimpleObject object. TestSimpleObject obj = new TestSimpleObject(); Console.WriteLine("Before serialization the object contains: "); obj.Print(); //Opens a file and serializes the object into it in binary format. Stream stream = File.Open("data.xml", FileMode.Create); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, obj); stream.Close(); //Empties obj. obj = null; //Opens file "data.xml" and deserializes the object from it. stream = File.Open("data.xml", FileMode.Open); formatter = new BinaryFormatter(); obj = (TestSimpleObject)formatter.Deserialize(stream); stream.Close(); Console.WriteLine(""); Console.WriteLine("After deserialization the object contains: "); obj.Print(); } }

[Serializable()] public class TestSimpleObject { public int member1; public string member2; public string member3; public double member4; // A field that is not serialized. [NonSerialized()] public string member5; public TestSimpleObject() { member1 = 11; member2 = "hello"; member3 = "hello"; member4 = 3.14159265; member5 = "hello world!"; } public void Print() { Console.WriteLine("member1 = '{0}'", member1); Console.WriteLine("member2 = '{0}'", member2); Console.WriteLine("member3 = '{0}'", member3); Console.WriteLine("member4 = '{0}'", member4); Console.WriteLine("member5 = '{0}'", member5); } }

Assembly  manifest  

Type  metadata  

CIL  code  

Resources  

ASSEMBLIES  Colección  de  Lpos  y  recursos  que  forman  una  unidad  lógica  de  funcionalidad  y  que  se  compilan  para  trabajar  conjuntamente.  

Se   puede   obtener   información   mediante   programación  sobre  un  ensamblado  usando  la  reflexión.  

Es   posible   comparLr   un   ensamblado   entre   aplicaciones  colocándolo  en  la  caché  global  de  ensamblados.      

Los   ensamblados   sólo   se   cargan   en   la   memoria   si   son  necesarios.  Si  no  se  uLlizan,  no  se  cargan.  

Los  ensamblados  se  implementan  como  archivos  .exe  o  .dll.   Unidad  lógica  de  despliegue  en  la  plataforma  .NET.  

MyAssembly.dll

Atributos,  Ensamblados  y  Reflec6on  Bloques  de  creación  de  .NET  Framework  

REFLECTION  Permite  obtener  información  acerca  de  los  ensamblados  cargados  y  los  Lpos  definidos  en  los  mismos,  como  clases,  interfaces  y  6pos  de  valor,  así  como  instanciar  objetos,  invocar  métodos  o  tener  acceso  a  sus  campos  y  propiedades  en  6empo  de  ejecución.      

System.Reflection

.NET  Framework  proporciona   un   espacio   de   nombres  dedicado   que   conLene   los   Lpos   que   recuperan   la  información   sobre   los   ensamblados,   módulos,  miembros,   parámetros   y   otras   enLdades   del   código  administrado  examinando  sus  metadatos:      

Es  úLl  cuando  es  necesario  obtener  acceso  a  atributos  en  los  metadatos  del  programa.  

Para  examinar  e  instanciar  Lpos  en  un  ensamblado.      

Atributos,  Ensamblados  y  Reflec6on  Bloques  de  creación  de  .NET  Framework  

Es   úLl   cuando   es   necesario   obtener   acceso   a  atributos  en  los  metadatos  del  programa.  

Recuperemos  el  atributo  Author  definido  anteriormente…  

Atributos,  Ensamblados  y  Reflec6on  ReflecLon  

[Author("Brian Kernighan")] class MyClass { ... }

Atributos,  Ensamblados  y  Reflec6on  Acceso  a  los  atributos  mediante  reflecLon  

Necesitamos  leer  "Brian Kernighan"  para  saber  el  autor  de  la  clase?  cómo  podemos  hacerlo?  

[Author("Brian Kernighan")] class MyClass { ... }

Atributos,  Ensamblados  y  Reflec6on  Acceso  a  los  atributos  mediante  reflecLon  

Necesitamos  leer  "Brian Kernighan"  para  saber  el  autor  de  la  clase?  cómo  podemos  hacerlo?  

¡¡  Reflec6on  !!    

[Author("Brian Kernighan")] class MyClass { ... }

Atributos,  Ensamblados  y  Reflec6on  Acceso  a  los  atributos  mediante  reflecLon  

Necesitamos  leer  "Brian Kernighan"  para  saber  el  autor  de  la  clase?  cómo  podemos  hacerlo?  

¡¡  Reflec6on  !!    El  hecho  de  poder  definir  atributos  personalizados  y  colocarlos  en  el  código  fuente  tendría  un  valor  escaso  si  no  se  dispone  de  un  método  para  recuperar  la  información  y  actuar  sobre  ella.    Mediante  el  uso  de  la  reflexión  se  puede  recuperar  la  información  definida  con  atributos  personalizados.  

 

[Author("Brian Kernighan")] class MyClass { ... }

Atributos,  Ensamblados  y  Reflec6on  Acceso  a  los  atributos  mediante  reflecLon  

// Class with the Author attribute. [Author("P. Ackerman")] public class FirstClass { // ... } // Class without the Author attribute. public class SecondClass { // ... } // Class with multiple Author attributes. [Author("P. Ackerman"), Author("R. Koch", version = 2.0)] public class ThirdClass { // ... }

class TestAuthorAttribute { static void Test() { PrintAuthorInfo(typeof(FirstClass)); PrintAuthorInfo(typeof(SecondClass)); PrintAuthorInfo(typeof(ThirdClass)); } private static void PrintAuthorInfo(System.Type t) { System.Console.WriteLine("Author information for {0}", t); // Using reflection. System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // Reflection. // Displaying output. foreach (System.Attribute attr in attrs) { if (attr is Author) { Author a = (Author)attr; System.Console.WriteLine( "{0}, version {1:f}", a.GetName(), a.version ); } } } } ?

[System.AttributeUsage(System.AttributeTargets.Class)] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } public string GetName() { return name; } }

// Class with the Author attribute. [Author("P. Ackerman")] public class FirstClass { // ... } // Class without the Author attribute. public class SecondClass { // ... } // Class with multiple Author attributes. [Author("P. Ackerman"), Author("R. Koch", version = 2.0)] public class ThirdClass { // ... }

class TestAuthorAttribute { static void Test() { PrintAuthorInfo(typeof(FirstClass)); PrintAuthorInfo(typeof(SecondClass)); PrintAuthorInfo(typeof(ThirdClass)); } private static void PrintAuthorInfo(System.Type t) { System.Console.WriteLine("Author information for {0}", t); // Using reflection. System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // Reflection. // Displaying output. foreach (System.Attribute attr in attrs) { if (attr is Author) { Author a = (Author)attr; System.Console.WriteLine( "{0}, version {1:f}", a.GetName(), a.version ); } } } }

[System.AttributeUsage(System.AttributeTargets.Class)] public class Author : System.Attribute { private string name; public double version; public Author(string name) { this.name = name; version = 1.0; } public string GetName() { return name; } }

Author information for FirstClass P. Ackerman, version 1.00 Author information for SecondClass Author information for ThirdClass R. Koch, version 2.00 P. Ackerman, version 1.00

Para  examinar  e  instanciar  Lpos  en  un  ensamblado.  

Atributos,  Ensamblados  y  Reflec6on  ReflecLon  

[assembly:AssemblyVersionAttribute("1.0.2000.0")] public class Example { private int factor; public Example(int f) { factor = f; } public int SampleMethod(int x) { Console.WriteLine( "\nExample.SampleMethod({0}) executes.", x ); return x * factor; } }

using System; using System.Reflection; using System.Security.Permissions; public static void Main() { Assembly assem = Assembly.GetExecutingAssembly(); Console.WriteLine("Assembly Full Name:"); Console.WriteLine(assem.FullName); // The AssemblyName type can be used to parse the full name. AssemblyName assemName = assem.GetName(); Console.WriteLine("\nName: {0}", assemName.Name); Console.WriteLine("Version: {0}.{1}", assemName.Version.Major, assemName.Version.Minor); Console.WriteLine("\nAssembly CodeBase:"); Console.WriteLine(assem.CodeBase); // Create an object from the assembly, passing in the correct // number and type of arguments for the constructor. object o = assem.CreateInstance("Example", false, BindingFlags.ExactBinding, null, new Object[] { 2 }, null, null); // Make a late-bound call to an instance method of the object. MethodInfo m = assem.GetType("Example").GetMethod("SampleMethod"); Object ret = m.Invoke(o, new Object[] { 42 }); Console.WriteLine("SampleMethod returned {0}.", ret); Console.WriteLine("\nAssembly entry point:"); Console.WriteLine(assem.EntryPoint); }

 

?

[assembly:AssemblyVersionAttribute("1.0.2000.0")] public class Example { private int factor; public Example(int f) { factor = f; } public int SampleMethod(int x) { Console.WriteLine( "\nExample.SampleMethod({0}) executes.", x ); return x * factor; } }

using System; using System.Reflection; using System.Security.Permissions; public static void Main() { Assembly assem = Assembly.GetExecutingAssembly(); Console.WriteLine("Assembly Full Name:"); Console.WriteLine(assem.FullName); // The AssemblyName type can be used to parse the full name. AssemblyName assemName = assem.GetName(); Console.WriteLine("\nName: {0}", assemName.Name); Console.WriteLine("Version: {0}.{1}", assemName.Version.Major, assemName.Version.Minor); Console.WriteLine("\nAssembly CodeBase:"); Console.WriteLine(assem.CodeBase); // Create an object from the assembly, passing in the correct // number and type of arguments for the constructor. object o = assem.CreateInstance("Example", false, BindingFlags.ExactBinding, null, new Object[] { 2 }, null, null); // Make a late-bound call to an instance method of the object. MethodInfo m = assem.GetType("Example").GetMethod("SampleMethod"); Object ret = m.Invoke(o, new Object[] { 42 }); Console.WriteLine("SampleMethod returned {0}.", ret); Console.WriteLine("\nAssembly entry point:"); Console.WriteLine(assem.EntryPoint); }

 

Assembly Full Name: source, Version=1.0.2000.0, Culture=neutral, PublicKeyToken=null Name: source Version: 1.0 Assembly CodeBase: file:///C:/sdtree/AssemblyClass/cs/source.exe Example.SampleMethod(42) executes. SampleMethod returned 84. Assembly entry point: Void Main()

Ejemplo  prácLco  

Reflec6on:  Obtener  los  constructores  de  la  clase  String

using System; using System.Reflection; class ListMembers { public static void Main(String[] args) { Type t = typeof(System.String); Console.WriteLine( "Listing all the public constructors of the {0} type", t ); // Constructors. ConstructorInfo[] ci = t.GetConstructors( BindingFlags.Public | BindingFlags.Instance); Console.WriteLine("//Constructors"); PrintMembers(ci); } public static void PrintMembers(MemberInfo[] ms) { foreach (MemberInfo m in ms) { Console.WriteLine("{0}{1}", " Console.WriteLine(); } } }

 

Listing all the public constructors of the System.String type //Constructors Void.ctor(Char*) Void.ctor(Char*, Int32, Int32) Void.ctor(SByte*) Void.ctor(SByte*, Int32, Int32) Void.ctor(SByte*, Int32, Int32, System.Text.Encoding) Void.ctor(Char[], Int32, Int32) Void.ctor(Char[]) Void.ctor(Char, Int32) Press any key to continue...

Lectura  y  escritura  de  ficheros  

Serialización  y  Deserialización  de  datos  

195Lectura  y  escritura  de  ficheros  Serialización  y  Deserialización  de  datos  

Cada  vez  que  deseemos  leer  datos  de  un  archivo  o  escribir  datos  en  un  archivo,  deberemos  hacer  uso  del  objeto  Stream que  .NET Framework nos  ofrece.  

Clase Stream La  clase  Stream  es  una  clase  abstracta,  por  lo  que  no  es  posible  uLlizarla  directamente.    

Clase Stream

Cada  subclase  añade  métodos  y  propiedades  específicas  a  la  funcionalidad  de  la  clase

La  clase  Stream  es  una  clase  abstracta,  por  lo  que  no  es  posible  uLlizarla  directamente.    

Debemos  hacer  uso  de  sus  clases  derivadas  que  se  especializan  en  el  tratamiento  de  streams  para  diferentes  orígenes  y  desLnos.  

Clase Stream

Cada  subclase  añade  métodos  y  propiedades  específicas  a  la  funcionalidad  de  la  clase

La  clase  Stream  es  una  clase  abstracta,  por  lo  que  no  es  posible  uLlizarla  directamente.    

Podemos  escribir  datos  en  el  stream  a  través  del  método  Write().    

Podemos  obtener  o  establecer  la  posición    dentro  del  stream  mediante  el  método  Seek().  

A  través  del  método  Read() podemos  leer  datos  desde  un  fichero,  desde  la  red  o  desde  memoria.    

Clase FileStream

Actúa  como  intermediario  entre  el  sistema  de  archivos  y  nuestra  aplicación,  permiLendo  realizar  de  una  manera  limpia  y  sencilla  operaciones  de  escritura  y  lectura  en  archivos.    

// Se crea el FileStream mediante el método Create de File Filestream fs = File.Create(@"C:\FileStream.txt"); // Se define el texto que vamos a escribir string data = "hello world"; // Se obtiene la equivalencia en bytes de la cadena utilizando // codificación UTF8 byte[] bytes = Encoding.UTF8.GetBytes(data.ToString()); fs.Write(bytes, 0, bytes.Length); fs.Flush(); fs.Close();

Clase FileStream

Todo  stream  se  debe  cerrar  al  finalizar  la  operación  que  se  realiza  sobre  él,  ya  que  de  lo  contrario  el  archivo  quedaría  bloqueado  y  no  se  liberarían  recursos  del  sistema  operaLvo.  

Clases StreamWriter y StreamReader

La  plataforma  .NET  ofrece  otras  maneras  de  administrar  Streams  para  hacerle  la  vida  más  fácil  al  desarrollador:  

Reciben   Ipos   de   datos   naIvos   del   lenguaje:   int,   bool,  decimal,  float,  string,  char,  etc.  

Hacen   uso   por   defecto   de   la   codificación   UTF8,  pudiendo  definir  una  disLnta  en  los  constructores.  

StreamWriter StreamReader

Hacer  uso  del  constructor  de  StreamWriter  para  abrir  o  crear  un  fichero.  1  

Clases StreamWriter y StreamReader Escribamos  texto  en  un  fichero  en  3  sencillos  pasos  

Hacer  uso  del  constructor  de  StreamWriter  para  abrir  o  crear  un  fichero.  

Hacer  uso  de  los  métodos  Write() y  WriteLine() para  escribir  en  el  fichero.  

1  

2  

Clases StreamWriter y StreamReader Escribamos  texto  en  un  fichero  en  3  sencillos  pasos  

Hacer  uso  del  constructor  de  StreamWriter  para  abrir  o  crear  un  fichero.  

Hacer  uso  de  los  métodos  Write() y  WriteLine() para  escribir  en  el  fichero.  

Invocar  a  Close() para  garanLzar  que  todos  los  datos  se  escriben  correctamente.  

1  

2  

3  

Clases StreamWriter y StreamReader Escribamos  texto  en  un  fichero  en  3  sencillos  pasos  

Filestream fs = File.Create(@"C:\FileStream.txt"); string data = "hello world”; byte[] bytes = Encoding.UTF8.GetBytes(data.ToString()); fs.Write(bytes, 0, bytes.Length); fs.Flush(); fs.Close();

FileStream vs. StreamWriter

FileStream

Filestream fs = File.Create(@"C:\FileStream.txt"); string data = "hello world”; byte[] bytes = Encoding.UTF8.GetBytes(data.ToString()); fs.Write(bytes, 0, bytes.Length); fs.Flush(); fs.Close();

StreamWriter writer = new StreamWriter(@"C:\FileStream.txt"); writer.WriteLine("hello world"); writer.Close();

FileStream vs. StreamWriter

StreamWriter

FileStream

Filestream fs = File.Create(@"C:\FileStream.txt"); string data = "hello world”; byte[] bytes = Encoding.UTF8.GetBytes(data.ToString()); fs.Write(bytes, 0, bytes.Length); fs.Flush(); fs.Close();

StreamWriter writer = new StreamWriter(@"C:\FileStream.txt"); writer.WriteLine("hello world"); writer.Close();

FileStream vs. StreamWriter

StreamWriter

FileStream

208Clases File y Directory

El  espacio  de  nombres  System.IO  dispone  de  las  clases  File,  FileInfo,  Directory   y   DirectoryInfo   ideales   para   trabajar   con   ficheros   y  directorios.  

StreamWriter writer = new StreamWriter(@"C:\FileStream.txt"); writer.WriteLine("hello world"); writer.Close();

C#  nos  ofrece  el  mecanismo  para  evitar  olvidarnos  cerrar  los  streams  IDisposable,  Dispose()  

Gran  parte  de  los  bugs  vienen  derivados  de  despistes  de  los  desarrolladores  al  no  cerrar  éstos  

using (StreamWriter writer = new StreamWriter(@"C:\FileStream.txt”)) { writer.WriteLine("hello world"); writer.WriteLine(”another genius secret plan"); }

C#  nos  ofrece  el  mecanismo  para  evitar  olvidarnos  cerrar  los  streams  IDisposable,  Dispose()  

StreamWriter writer = new StreamWriter(@"C:\FileStream.txt"); writer.WriteLine("hello world"); writer.Close();

Gran  parte  de  los  bugs  vienen  derivados  de  despistes  de  los  desarrolladores  al  no  cerrar  éstos  

Evitemos  errores  del  sistema  de  ficheros  haciendo  uso  de  palabra  using

Evitemos  errores  del  sistema  de  ficheros  haciendo  uso  de  palabra  using

using (StreamWriter writer = new StreamWriter(@"C:\FileStream.txt”)) { writer.WriteLine("hello world"); writer.WriteLine(”another genius secret plan"); }

C#  nos  ofrece  el  mecanismo  para  evitar  olvidarnos  cerrar  los  streams  IDisposable,  Dispose()  

StreamWriter writer = new StreamWriter(@"C:\FileStream.txt"); writer.WriteLine("hello world"); writer.Close();

Gran  parte  de  los  bugs  vienen  derivados  de  despistes  de  los  desarrolladores  al  no  cerrar  éstos  

Evitemos  errores  del  sistema  de  ficheros  haciendo  uso  de  palabra  using

using (StreamWriter writer = new StreamWriter(@"C:\FileStream.txt”)) { writer.WriteLine("hello world"); writer.WriteLine(”another genius secret plan"); }

C#  nos  ofrece  el  mecanismo  para  evitar  olvidarnos  cerrar  los  streams  IDisposable,  Dispose()  

StreamWriter writer = new StreamWriter(@"C:\FileStream.txt"); writer.WriteLine("hello world"); writer.Close();

Gran  parte  de  los  bugs  vienen  derivados  de  despistes  de  los  desarrolladores  al  no  cerrar  éstos  

Evitemos  errores  del  sistema  de  ficheros  haciendo  uso  de  palabra  using

using (StreamWriter writer = new StreamWriter(@"C:\FileStream.txt”)) { writer.WriteLine("hello world"); writer.WriteLine(”another genius secret plan"); }

C#  nos  ofrece  el  mecanismo  para  evitar  olvidarnos  cerrar  los  streams  IDisposable,  Dispose()  

StreamWriter writer = new StreamWriter(@"C:\FileStream.txt"); writer.WriteLine("hello world"); writer.Close();

Gran  parte  de  los  bugs  vienen  derivados  de  despistes  de  los  desarrolladores  al  no  cerrar  éstos  

Gran  parte  de  los  bugs  vienen  derivados  de  despistes  de  los  desarrolladores  al  no  cerrar  éstos  

Evitemos  errores  del  sistema  de  ficheros  haciendo  uso  de  palabra  using

using (StreamWriter writer = new StreamWriter(@"C:\FileStream.txt”)) { writer.WriteLine("hello world"); writer.WriteLine(”another genius secret plan"); }

C#  nos  ofrece  el  mecanismo  para  evitar  olvidarnos  cerrar  los  streams  IDisposable,  Dispose()  

StreamWriter writer = new StreamWriter(@"C:\FileStream.txt"); writer.WriteLine("hello world"); writer.Close();

Lectura  y  escritura  de  ficheros  Serialización  y  Deserialización  de  datos  

Sólo  puedo  escribir  y  leer  texto  en  los  ficheros?  Si  quisiera  guardar  la  información  

de  un  objeto…  podría  hacerlo?

Lectura  y  escritura  de  ficheros  Serialización  y  Deserialización  de  datos  

Sólo  puedo  escribir  y  leer  texto  en  los  ficheros?  Si  quisiera  guardar  la  información  

de  un  objeto…  podría  hacerlo?

¡¡¡  SÍ  !!! Podríamos  guardar  en  cada  línea  del  fichero  el  valor  de  cada  campo  del  objeto  pero  esto  supondría  un  gran  trabajo  y  poco  flexible  a  cambios.  Lo  que  haremos  es…  

Lectura  y  escritura  de  ficheros  Serialización  y  Deserialización  de  datos  

Sólo  puedo  escribir  y  leer  texto  en  los  ficheros?  Si  quisiera  guardar  la  información  

de  un  objeto…  podría  hacerlo?

Serializar  y  Deserializar  el  objeto.

¡¡¡  SÍ  !!! Podríamos  guardar  en  cada  línea  del  fichero  el  valor  de  cada  campo  del  objeto  pero  esto  supondría  un  gran  trabajo  y  poco  flexible  a  cambios.  Lo  que  haremos  es…  

Lectura  y  escritura  de  ficheros  Serialización  y  Deserialización  de  datos  

Sólo  puedo  escribir  y  leer  texto  en  los  ficheros?  Si  quisiera  guardar  la  información  

de  un  objeto…  podría  hacerlo?

Serializar  y  Deserializar  el  objeto.

¡¡¡  SÍ  !!!

Proceso  de  conver6r  un  objeto  en  una  secuencia  de  bytes  para  almacenar  el  objeto  o  transmiLrlo  a  memoria,  una  base  de  datos,  o  en  un  archivo.  Su  propósito  principal  es  guardar  el  estado  de  un  objeto  para  poder  crearlo  de  nuevo  cuando  se  necesita.  El  proceso  inverso  se  denomina  deserialización.  

Podríamos  guardar  en  cada  línea  del  fichero  el  valor  de  cada  campo  del  objeto  pero  esto  supondría  un  gran  trabajo  y  poco  flexible  a  cambios.  Lo  que  haremos  es…  

Qué  le  pasa  a  un  objeto  cuando  éste  es  serializado?  

Qué  es  exactamente  el  estado  de  un  objeto?  El  estado  de  un  objeto  son  los  valores  de  cada  uno  de  los  campos  que  componen  dicho  objeto.  

Qué  le  pasa  a  un  objeto  cuando  éste  es  serializado?  Cada  campo  del  objeto  será  serializado  a  excepción  de  aquellos  que  tengan  el  atributo  NonSerializedAttribute.    

Si  un  objeto  referencia  a  otros  objetos,  éstos  también  se  serializan…  incluso  los  objetos  referenciados  por  éstos.  

Excepciones  GesLón  de  excepciones  existentes  y  creación  de  nuevas  excepciones  

Excepciones  GesLón  de  excepciones  existentes  y  creación    

de  nuevas  excepciones  

Mecanismo  de  ges6ón  o  control  de  errores  que  provee  el  lenguaje  de  programación  y  que  representa  el  medio  para  lograr  la  escritura  de  programas  más  robustos  y  tolerantes  a  fallos.  

224

Todas  las  excepciones  derivan  en  úlLma  instancia  de  System.Exception

226

C#  permite  controlar  las  excepciones  a  través  de  las  palabras  clave  try,  catch,  finally.  

Excepciones  Control  de  excepciones  

try { … // código propenso a generar excepciones } catch (DivideByZeroException e) { … // tratamiento de cualquier excepción de tipo // DivideByZeroException ocurrida en el bloque try }

Palabras reservadas try-catch Permiten  controlar  las  excepciones  

try { … // código propenso a generar excepciones } catch (DivideByZeroException e) { … // tratamiento de cualquier excepción de tipo // DivideByZeroException ocurrida en el bloque try }

Palabras reservadas try-catch Permiten  controlar  las  excepciones  

Cuándo  debo  hacer  uso  de  try-­‐catch?  Un  consejo  sería  sólo  hacer  uso  cuando  el  código  implementado  Lene  cierto  riesgo.  Por  ejemplo,  código  que  se  ejecuta  con  la  entrada  de  datos  por  parte  del  usuario  de  aplicación.  Debemos  darle  información  de  lo  que  está  pasando  y  no  mostrar  un  error  inesperado  que  pueda  causar  mala  impresión  e  incluso  pueda  mostrar  información  confidencial  que  nos  pueda  comprometer.  

try { … // código propenso a generar excepciones } catch (DivideByZeroException e) { … // tratamiento de cualquier excepción de tipo // DivideByZeroException ocurrida en el bloque try }

Palabras reservadas try-catch Permiten  controlar  las  excepciones  

Cuándo  debo  hacer  uso  de  try-­‐catch?  Un  consejo  sería  sólo  hacer  uso  cuando  el  código  implementado  Lene  cierto  riesgo.  Por  ejemplo,  código  que  se  ejecuta  con  la  entrada  de  datos  por  parte  del  usuario  de  aplicación.  Debemos  darle  información  de  lo  que  está  pasando  y  no  mostrar  un  error  inesperado  que  pueda  causar  mala  impresión  e  incluso  pueda  mostrar  información  confidencial  que  nos  pueda  comprometer.  

El  bloque  del  catch  sólo  se  ejecutará  si  en  la  parte  del  try  ha  ocurrido  alguna  excepción.  

try { … // código propenso a generar excepciones } catch { … // tratamiento de cualquier excepción ocurrida // en el bloque try }

Palabras reservadas try-catch Permiten  controlar  las  excepciones  

Cuándo  debo  hacer  uso  de  try-­‐catch?  Un  consejo  sería  sólo  hacer  uso  cuando  el  código  implementado  Lene  cierto  riesgo.  Por  ejemplo,  código  que  se  ejecuta  con  la  entrada  de  datos  por  parte  del  usuario  de  aplicación.  Debemos  darle  información  de  lo  que  está  pasando  y  no  mostrar  un  error  inesperado  que  pueda  causar  mala  impresión  e  incluso  pueda  mostrar  información  confidencial  que  nos  pueda  comprometer.  

El  bloque  del  catch  sólo  se  ejecutará  si  en  la  parte  del  try  ha  ocurrido  alguna  excepción.  

Sin  el  bloque  del  catch  no  se  indica  ninguna  excepción;  cualquier  excepción  que  ocurra  en  el  try  será  capturada  por  este  bloque.  

Si  tenemos  código  que  se  debe  ejecutar  SIEMPRE,  haremos  uso  de  finally

Palabra reservada finally  

Al  finalizar  el  bloque  try  

Cuando  un  programa  eleva  una  excepción,  pueden  pasar  mulLtud  de  escenarios.  Si  la  excepción  no  es  controlada,  el  programa  finalizará  y  fallará.  Si  la  excepción  es  controlada,  el  código  saltará  al  bloque  del  catch.  Pero  qué  pasa  con  el  resto  del  código  existente  en  el  bloque  del  try?  Qué  pasa  si  estábamos  cerrando  un  stream,  o  eliminando  ciertos  recursos?  Dicho  código  necesita  ejecutarse,  incluso  aunque  ocurra  una  excepción.  Es  aquí  donde  entra  en  juego  el  bloque  del  finally.  El  bloque  del  finally  siempre  se  ejecuta,  ocurra  o  no  una  excepción.  

Uso  de  las  sentencias  de  salto  (p.e.,  goto  o  return)  localizadas  en  el  bloque  try

Después  de  finalizar  un  bloque  catch

try { … } catch { … } finally { … // código que se ejecutará // independientemente de si // ha ocurrido una // excepción o no en el bloque // try }

Ejemplo  prácLco  

Excepciones:  Captura  

class ExampleWithoutExceptionHandling { static double UnsafeDivision(double x, double y) { return x / y; } static void Main() { double a = 98; double b = 0; double result = 0; result = UnsafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } }

class ExampleWithoutExceptionHandling { static double UnsafeDivision(double x, double y) { return x / y; } static void Main() { double a = 98; double b = 0; double result = 0; result = UnsafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } }

Unhandled Exception: System.DivideByZeroException: Division by zero at ExampleWithoutExceptionHandling.Main()

El  mensaje  de  excepción  nos  indica  que  la  excepción  no  ha  sido  controlada  o  manejada.  

Localización  en  donde  se  ha  generado.  

El  programa  finaliza  su  ejecución  de  forma  abrupta  debido  a  que  la  excepción  no  ha  sido  manejada.  

class ExampleWithoutExceptionHandling { static double UnsafeDivision(double x, double y) { return x / y; } static void Main() { double a = 98; double b = 0; double result = 0; result = UnsafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } }

Unhandled Exception: System.DivideByZeroException: Division by zero at ExampleWithoutExceptionHandling.Main()

El  mensaje  de  excepción  nos  indica  que  la  excepción  no  ha  sido  controlada  o  manejada.  

Localización  en  donde  se  ha  generado.  

El  programa  finaliza  su  ejecución  de  forma  abrupta  debido  a  que  la  excepción  no  ha  sido  manejada.  

class ExampleWithoutExceptionHandling { static double UnsafeDivision(double x, double y) { return x / y; } static void Main() { double a = 98; double b = 0; double result = 0; result = UnsafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } }

Unhandled Exception: System.DivideByZeroException: Division by zero at ExampleWithoutExceptionHandling.Main()

Localización  en  donde  se  ha  generado.  

El  programa  finaliza  su  ejecución  de  forma  abrupta  debido  a  que  la  excepción  no  ha  sido  manejada.  

El  mensaje  de  excepción  nos  indica  que  la  excepción  no  ha  sido  controlada  o  manejada.  

class ExceptionExample { static double SafeDivision(double x, double y) { if (y == 0) throw new System.DivideByZeroException(); return x / y; } static void Main() { double a = 98, b = 0; double result = 0; try { result = SafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } catch (DivideByZeroException e) { Console.WriteLine("Attempted divide by zero."); } } }

class ExampleWithoutExceptionHandling { static double UnsafeDivision(double x, double y) { return x / y; } static void Main() { double a = 98; double b = 0; double result = 0; result = UnsafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } }

class ExceptionExample { static double SafeDivision(double x, double y) { if (y == 0) throw new System.DivideByZeroException(); return x / y; } static void Main() { double a = 98, b = 0; double result = 0; try { result = SafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } catch (DivideByZeroException e) { Console.WriteLine("Attempted divide by zero."); } } }

class ExampleWithoutExceptionHandling { static double UnsafeDivision(double x, double y) { return x / y; } static void Main() { double a = 98; double b = 0; double result = 0; result = UnsafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } }

Attempted divide by zero Press any key to continue...

Los  usuarios  son  impredecibles!  Proporcionan  todo  Lpo  de  datos  extraños  y  hacen  click  en  siLos  que  nunca  esperaríamos.      Debemos,  por  tanto,  controlar  la  entrada  de  datos  con  un  buen  manejo  de  excepciones.  

¿Qué  sucede  cuando  un  método  al  que  deseamos  llamar  es  arriesgado?  

Hacer  uso  de  varios  bloques  catch  para  tratar  múl6ples  excepciones  

Hacer  uso  de  varios  bloques  catch  para  tratar  múl6ples  excepciones  

Orden de ejecución de los catch

Cuando  existen  varios  bloques  catch,  éstos  son  examinados  en  orden.  En  este  ejemplo,  en  primer  lugar  se  comprobará  si  es  de  Lpo  VatEmptyExcepLon;  en  segundo  lugar  si  es  de  Lpo  HiveLogExcepLon  y  por  úlLmo  si  es  de  Lpo  IOExcepLon.  

Hacer  uso  de  varios  bloques  catch  para  tratar  múl6ples  excepciones   Variable ex

Si  la  excepción  no  se  va  a  uLlizar,  no  es  necesario  declararla.  Orden de ejecución de los catch

Cuando  existen  varios  bloques  catch,  éstos  son  examinados  en  orden.  En  este  ejemplo,  en  primer  lugar  se  comprobará  si  es  de  Lpo  VatEmptyExcepLon;  en  segundo  lugar  si  es  de  Lpo  HiveLogExcepLon  y  por  úlLmo  si  es  de  Lpo  IOExcepLon.  

Hacer  uso  de  varios  bloques  catch  para  tratar  múl6ples  excepciones  

Mismo nombre

Es  aconsejable  uLlizar  el  mismo  nombre  (“ex”)  para  las  excepciones.  

Variable ex Si  la  excepción  no  se  va  a  uLlizar,  no  es  necesario  declararla.  Orden de ejecución de los catch

Cuando  existen  varios  bloques  catch,  éstos  son  examinados  en  orden.  En  este  ejemplo,  en  primer  lugar  se  comprobará  si  es  de  Lpo  VatEmptyExcepLon;  en  segundo  lugar  si  es  de  Lpo  HiveLogExcepLon  y  por  úlLmo  si  es  de  Lpo  IOExcepLon.  

Hacer  uso  de  varios  bloques  catch  para  tratar  múl6ples  excepciones  

throw En  ciertas  ocasiones  nos  puede  ineteresar  elevar  una  excepción  al  método  llamante.  Para  relanzar  una  excepción  podemos  hacerlo  mediante  throw.  

Mismo nombre

Es  aconsejable  uLlizar  el  mismo  nombre  (“ex”)  para  las  excepciones.  

Variable ex Si  la  excepción  no  se  va  a  uLlizar,  no  es  necesario  declararla.  Orden de ejecución de los catch

Cuando  existen  varios  bloques  catch,  éstos  son  examinados  en  orden.  En  este  ejemplo,  en  primer  lugar  se  comprobará  si  es  de  Lpo  VatEmptyExcepLon;  en  segundo  lugar  si  es  de  Lpo  HiveLogExcepLon  y  por  úlLmo  si  es  de  Lpo  IOExcepLon.  

245

A  pesar  de  que  la  biblioteca  base  de  clases  de   .NET  Framework  cuenta  con  un  conjunto  enriquecido  de  clases  de  excepciones,   surgirán   situaciones   en   donde   como   desarrolladores   requeriremos   crear   un   nivel   de   granularidad  adicional  para  el   lanzamiento  y  captura  de  excepciones  de  acuerdo  a   la   lógica  de  negocio  y  el  dominio  de  nuestra  aplicación.    

Para  ello,  crearemos  nuestras  propias  excepciones  personalizadas.    

Excepciones  Creación  de  excepciones  personalizadas  

[Serializable()] public class YourException : System.Exception { public YourException() : base() { } public YourException(string message) : base(message) { } public YourException (string message, System.Exception inner) : base(message, inner) { } // A constructor is needed for serialization when an // exception propagates from a remoting server to the client. protected YourException (System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } }

246

Ejemplo  prácLco  

Excepciones  personalizadas  

247

Recordemos  que  cuando  declaramos  una  referencia  en  un  “using”,  su  método  Dispose()  es  invocado  automáLcamente  al  finalizar  el  bloque.  

Aquellas  clases  que  implementan  la  interfaz  System.IDisposable  y  que  encapsulan  recursos  no  administrados  por  el  CLR,  como:  archivos,  gráficos,  o  bases  de  datos,  etc.  implementan  el  método  abstracto  Dispose()  para  la  liberación  de  los  recursos  (e.g.,  memoria)  ocupados.  Para  este  Lpo  de  clases,  la  sentencia  using  provee  una  sintaxis  más  cómoda  y  versáLl  que  usar  la  sentencia  try-catch-finally

Una  manera  de  evitar  muchos  problemas: using en  lugar  de  try-finally

Los  streams  son  perfectos  puesto  que  Lenen  su  propia  implementación  para  cuando  el  objeto  es  eliminado  y  hacer  que  el  stream  se  cierre.  Pero  qué  pasa  si  tenemos  nuestro  propio  objeto  en  el  cuál  siempre  necesitamos  hacer  algo  cuando  éste  es  eliminado?  No  sería  buena  idea  implementar  un  código  que  se  ejecutara  siempre  cuando  el  objeto  es  eliminado  para  poder  uLlizarlo  en  la  instrucción  using?    

Implementa  el  interfaz  IDisposable  y  escribe  el  código    para  liberar  recursos  en  el  método  Dispose()

IDisposable

Or  anything  else  that  implements  IDisposable.  

LINQ  y  expresiones  Lambda  Cómo  hacer  que  la  vida  del  desarrollador  sea  más  

sencilla  

LINQ  Language  Integrated    Query  

Permite   consultar   datos   de   forma   sencilla   e   intuiLva,  agruparlos,   ordenarlos,   mezclar   datos   de   diferentes   orígenes  de  datos  y  muchas  cosas  más!  

LINQ  Language    

Integrated    Query  

Conjunto  de  tecnologías  que  consiste  en  la  integración  directa  de  funciones  de  consulta  en  el  lenguaje  C#  

Conjunto  de  tecnologías  que  consiste  en  la  integración  directa  de  funciones  de  consulta  en  el  lenguaje  C#  

Qué  es  una  función  de  consulta?  

Qué  es  una  función  de  consulta?  es  una  expresión  que  recupera  datos  de  un  origen  de  datos

Conjunto  de  tecnologías  que  consiste  en  la  integración  directa  de  funciones  de  consulta  en  el  lenguaje  C#  

Con  LINQ  podemos  consultar  cualquier  objeto  que  implemente  el  interfaz  IEnumerable<T>

Qué  es  una  función  de  consulta?  es  una  expresión  que  recupera  datos  de  un  origen  de  datos

LINQ  permite  realizar  consultas  de  forma  sencilla  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

LINQ  permite  realizar  consultas  de  forma  sencilla  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

LINQ  permite  realizar  consultas  de  forma  sencilla  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

1   Obtención  del  origen  de  datos.  

LINQ  permite  realizar  consultas  de  forma  sencilla  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

1   Obtención  del  origen  de  datos.  

Sintaxis  de  consulta.  

LINQ  permite  realizar  consultas  de  forma  sencilla  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

1   Obtención  del  origen  de  datos.  

Sintaxis  de  consulta.  

LINQ  permite  realizar  consultas  de  forma  sencilla  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

LINQ  permite  realizar  consultas  de  forma  sencilla  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

LINQ  permite  realizar  consultas  de  forma  sencilla  

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // numQuery is an IEnumerable<int> var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n); foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Sintaxis  de  método.  

LINQ  permite  realizar  consultas  de  forma  sencilla  

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

Origen  de  datos.  Un   Lpo   que   se   puede   consultar   no   requiere  ninguna   modificación   o   tratamiento   especial  para  servir  como  origen  de  datos  LINQ  

La  consulta.  especifica  qué  información  se  va  a  recuperar  de  uno  o  varios  orígenes  de  datos.  Opcionalmente,  una   consulta   también   especifica   cómo   debería  ordenarse,   agruparse   y   darse   forma   a   esa  información  antes  de  ser  devuelta.  Una  consulta  se   almacena   en   una   variable   de   consulta   y   se  inicializa  con  una  expresión  de  consulta.    Lo   importante   es   que,   en   LINQ,   la   propia  variable   de   consulta  no   realiza   ninguna   acción  ni   devuelve   datos.   Simplemente   almacena   la  información   necesaria   para   generar   los  resultados   cuando   la   consulta   se   ejecute  posteriormente.  

La  ejecución.  La  ejecución  real  de  la  consulta  se  aplaza  hasta  que  se  procese  una   iteración   en   la  variable  de  consulta,  en  una  instrucción  foreach.  

Northwnd db = new Northwnd(@"c:\northwnd.mdf");

LINQ  permite  realizar  consultas  de  forma  sencilla  

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

IQueryable<Customer> custQuery = from cust in db.Customers where cust.City == "London" select cust;

Origen  de  datos.  Un   Lpo   que   se   puede   consultar   no   requiere  ninguna   modificación   o   tratamiento   especial  para  servir  como  origen  de  datos  LINQ  

La  consulta.  especifica  qué  información  se  va  a  recuperar  de  uno  o  varios  orígenes  de  datos.  Opcionalmente,  una   consulta   también   especifica   cómo   debería  ordenarse,   agruparse   y   darse   forma   a   esa  información  antes  de  ser  devuelta.  Una  consulta  se   almacena   en   una   variable   de   consulta   y   se  inicializa  con  una  expresión  de  consulta.    Lo   importante   es   que,   en   LINQ,   la   propia  variable   de   consulta  no   realiza   ninguna   acción  ni   devuelve   datos.   Simplemente   almacena   la  información   necesaria   para   generar   los  resultados   cuando   la   consulta   se   ejecute  posteriormente.  

La  ejecución.  La  ejecución  real  de  la  consulta  se  aplaza  hasta  que  se  procese  una   iteración   en   la  variable  de  consulta,  en  una  instrucción  foreach.  

LINQ  permite  realizar  consultas  de  forma  sencilla  

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

Origen  de  datos.  Un   Lpo   que   se   puede   consultar   no   requiere  ninguna   modificación   o   tratamiento   especial  para  servir  como  origen  de  datos  LINQ  

La  consulta.  especifica  qué  información  se  va  a  recuperar  de  uno  o  varios  orígenes  de  datos.  Opcionalmente,  una   consulta   también   especifica   cómo   debería  ordenarse,   agruparse   y   darse   forma   a   esa  información  antes  de  ser  devuelta.  Una  consulta  se   almacena   en   una   variable   de   consulta   y   se  inicializa  con  una  expresión  de  consulta.    Lo   importante   es   que,   en   LINQ,   la   propia  variable   de   consulta  no   realiza   ninguna   acción  ni   devuelve   datos.   Simplemente   almacena   la  información   necesaria   para   generar   los  resultados   cuando   la   consulta   se   ejecute  posteriormente.  

La  ejecución.  La  ejecución  real  de  la  consulta  se  aplaza  hasta  que  se  procese  una   iteración   en   la  variable  de  consulta,  en  una  instrucción  foreach.  

foreach (var c in custQuery) { Console.Write("{0}, {1}", c.Name, c.City); }

LINQ  permite  realizar  consultas  de  forma  sencilla  

Todas  las  operaciones  de  consulta  LINQ  se  componen  de  tres  acciones  disLntas:  

1   Obtención  del  origen  de  datos.  

Creación  de  la  consulta.      2  

Ejecución  de  la  consulta.      3  

Origen  de  datos.  Un   Lpo   que   se   puede   consultar   no   requiere  ninguna   modificación   o   tratamiento   especial  para  servir  como  origen  de  datos  LINQ  

La  consulta.  especifica  qué  información  se  va  a  recuperar  de  uno  o  varios  orígenes  de  datos.  Opcionalmente,  una   consulta   también   especifica   cómo   debería  ordenarse,   agruparse   y   darse   forma   a   esa  información  antes  de  ser  devuelta.  Una  consulta  se   almacena   en   una   variable   de   consulta   y   se  inicializa  con  una  expresión  de  consulta.    Lo   importante   es   que,   en   LINQ,   la   propia  variable   de   consulta  no   realiza   ninguna   acción  ni   devuelve   datos.   Simplemente   almacena   la  información   necesaria   para   generar   los  resultados   cuando   la   consulta   se   ejecute  posteriormente.  

La  ejecución.  La  ejecución  real  de  la  consulta  se  aplaza  hasta  que  se  procese  una   iteración   en   la  variable  de  consulta,  en  una  instrucción  foreach.  

foreach (var c in custQuery) { Console.Write("{0}, {1}", c.Name, c.City); }

IQueryable<Customer> custQuery = from cust in db.Customers where cust.City == "London" select cust;

Northwnd db = new Northwnd(@"c:\northwnd.mdf");

hsps://code.msdn.microsoR.com/101-­‐LINQ-­‐Samples-­‐3y9811b  

Ejemplos  prácLcos  

101  LINQ  Samples

using System; using System.Linq; static void Main(string[] args) { string[] names = { "Alonso", "Zheng", "Smith", "Jones", "Smythe", "Small", "Ruiz", "Hsieh", "Jorgenson", "Ilyich", "Singh", "Samba” }; var queryResults = Console.WriteLine("Names beginning with S:"); foreach (var item in queryResults) { Console.WriteLine(item); } Console.Write("Program finished, press Enter/Return to continue…"); Console.ReadLine(); }

Names beginning with S: Smith Smythe Small Singh Samba Program finished, press Enter/Return to continue...

using System; using System.Linq; static void Main(string[] args) { string[] names = { "Alonso", "Zheng", "Smith", "Jones", "Smythe", "Small", "Ruiz", "Hsieh", "Jorgenson", "Ilyich", "Singh", "Samba” }; var queryResults = Console.WriteLine("Names beginning with S:"); foreach (var item in queryResults) { Console.WriteLine(item); } Console.Write("Program finished, press Enter/Return to continue:"); Console.ReadLine(); }

Names beginning with S: Smith Smythe Small Singh Samba Program finished, press Enter/Return to continue:

from n in names where n.StartsWith("S") select n;  

273

Expresiones  Lambda  Son   un   Lpo   especial   de   métodos   anónimos   que   uLlizan   =>  como   operador   y   que   se   pueden   uLlizar   para   crear   Lpos  delegados   o   árboles   de   expresión.   Son   especialmente   úLles  para  escribir  expresiones  de  consulta  LINQ.  

(a, b) => { return a + b; }

You  can  think  of  lambda  expressions  as  anonymous  methods  that  take  parameters  and  can  return  values.      

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Reimplementación  del  ejemplo  haciendo  uso  de  expresiones  lambda.      

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n); foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

expresión  lambda  manera  sencilla  de  escribir  código  que  de  lo  contrario  sería  más  complejo  y  debería  escribirse  como  método  anónimo,  delegado  genérico  o  árbol  de  expresión.  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Reimplementación  del  ejemplo  haciendo  uso  de  expresiones  lambda.      

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n); foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

expresión  lambda  manera  sencilla  de  escribir  código  que  de  lo  contrario  sería  más  complejo  y  debería  escribirse  como  método  anónimo,  delegado  genérico  o  árbol  de  expresión.  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Reimplementación  del  ejemplo  haciendo  uso  de  expresiones  lambda.      

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n); foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

expresión  lambda  manera  sencilla  de  escribir  código  que  de  lo  contrario  sería  más  complejo  y  debería  escribirse  como  método  anónimo,  delegado  genérico  o  árbol  de  expresión.  

variable  de  entrada  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Reimplementación  del  ejemplo  haciendo  uso  de  expresiones  lambda.      

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n); foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

expresión  lambda  manera  sencilla  de  escribir  código  que  de  lo  contrario  sería  más  complejo  y  debería  escribirse  como  método  anónimo,  delegado  genérico  o  árbol  de  expresión.  

variable  de  entrada   En  el  cuerpo  de  una  expresión  se  pueden  incluir  llamadas  a  métodos  y  código  más  complejo.  

int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; var numQuery = from num in numbers where (num % 2) == 0 select num; foreach (int num in numQuery) { Console.Write("{0,1} ", num); }

Reimplementación  del  ejemplo  haciendo  uso  de  expresiones  lambda.      

Entendemos  la  signatura  del  método  Where?  

var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n);

Enumerable. Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate )

 

Entendemos  la  signatura  del  método  Where?  

var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n);

Clase  a  la  que  realmente  pertenece  el  método  Where.  Proporciona  un  conjunto  de  métodos  static  que  implementan  IEnumerable<T>.  

Colección  de  Lpo  IEnumerable<TSource> sobre  la  que  se  va  a  aplicar  el  predicado  predicate.  

Enumerable. Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate )

Entendemos  la  signatura  del  método  Where?  

var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n);

Clase  a  la  que  realmente  pertenece  el  método  Where.  Proporciona  un  conjunto  de  métodos  static  que  implementan  IEnumerable<T>.  

Colección  de  Lpo  IEnumerable<TSource> sobre  la  que  se  va  a  aplicar  el  predicado  predicate.  

Enumerable. Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate )

Entendemos  la  signatura  del  método  Where?  

var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n);

Función  que  se  aplicará  sobre  cada  elemento  de  source.  En  una  función  se  especifican  los  parámetros  de  entrada  y  el  Ipo  del  resultado.  Aquí  por  tanto  se  espera  1  parámetro  de  Ipo  TSource  de  entrada  y  un  bool  como  resultado.  

Clase  a  la  que  realmente  pertenece  el  método  Where.  Proporciona  un  conjunto  de  métodos  static  que  implementan  IEnumerable<T>.  

Colección  de  Lpo  IEnumerable<TSource> sobre  la  que  se  va  a  aplicar  el  predicado  predicate.  

Enumerable. Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate )

Entendemos  la  signatura  del  método  Where?  

var numQuery = numbers .Where(num => num % 2 == 0) .OrderBy(n => n);

Función  que  se  aplicará  sobre  cada  elemento  de  source.  En  una  función  se  especifican  los  parámetros  de  entrada  y  el  Ipo  del  resultado.  Aquí  por  tanto  se  espera  1  parámetro  de  Ipo  TSource  de  entrada  y  un  bool  como  resultado.  

Clase  a  la  que  realmente  pertenece  el  método  Where.  Proporciona  un  conjunto  de  métodos  static  que  implementan  IEnumerable<T>.  

 Delegados,  Eventos  y  Métodos  de  extensión  Referencias  a  métodos.  Qué  hace  el  código  

cuando  no  le  estamos  observando?  

 

Delegados  

Son   básicamente   un   puntero   de   función   en   C++,   pero  Lenen  seguridad  de  Lpos  (fuertemente  Lpados).  

Permiten  pasar  los  métodos  como  parámetros.  

Tipo  que  representa  referencias  a  métodos  con  una  lista  de  parámetros  determinada  y  un  Ipo  de  valor  devuelto.  

Has  pensado  alguna  vez  pasar  un  método  como  argumento  a  otros  métodos?  

Pueden   uLlizarse   para   definir   métodos   de   devolución   de  llamada.  

Pueden  encadenarse  entre  sí;  por  ejemplo,  se  puede  llamar  a  varios  métodos  en  un  solo  evento.  

Un  delegado  es  un  Ipo  de  referencia,  como  otro  cualquiera,  que  en  lugar  de  apuntar  a  un  objeto,  apunta  a  un  método.  

Delegados  Declaración  de  delegados  

{modificador acceso} delegate {tipo retorno} {identificador}({lista argumentos});

public delegate int MyDelegate(string s);

En  este  ejemplo  el  delegado  puede  uLlizarse  para  referenciar  a  cualquier  método  que  contenga  como  parámetro  de  entrada  un  string  y  como  resultado  de  salida  un  int.  

La  declaración  de  un  delegado  determina  los  métodos  que  pueden  ser  referenciados  por  el  delegado.  

Delegados  Instanciación  de  delegados  

public delegate void PrintString(string s); ... PrintString ps1 = new PrintString(WriteToScreen); PrintString ps2 = new PrintString(WriteToFile);

Una  vez  que  el  delegado  se  ha  declarado,  debemos  crear  un  objeto  delegado  con  la  palabra  reservada  new  y  asociarlo  a  algún  método  en  parLcular  que  cumpla  con  la  signatura  del  delegado  declarado.  

Cuando  se  instancia  un  delegado,  el  argumento  que  se  le  pasa  al  delegado  es  solamente  el  nombre  del  método.  No  se  deben  indicar  los  parámetros  de  entrada  del  método!  

Delegados  Invocación  de  métodos  haciendo  uso  de  los  delegados  instanciados  

public delegate void PrintString(string s); ... PrintString ps1 = new PrintString(WriteToScreen); PrintString ps2 = new PrintString(WriteToFile); ps1("Texto a escribir en pantalla"); ps2("Texto a escribir en fichero");

Declaración  de  delegado.  

public class Program { static void Main(string[] args) { //create delegate instances PerformCalculation pc1 = new PerformCalculation(Add); PerformCalculation pc2 = new PerformCalculation(Mult); //calling the methods using the delegate objects int result1 = pc1(5, 7); Console.WriteLine(”Result Add: {0}", result1); int result1 = pc1(5, 7); Console.WriteLine(”Result Mult: {0}", result2); } public static int Add(int a, int b) { return a + b; } public static int Mult(int a, int b) { return a * b; } }

public delegate int PerformCalculation(int x, int y);

Instanciación  de  delegados.  

3  Invocación  de  métodos  mediante  los  delegados  instanciados  

Result Add: 12 Result Mult: 35

1  

2  

Ejemplo  del  delegado  printString.      

Ejemplo  prácLco  

 Delegados Implementar  una  aplicación  de  consola  que  haga  uso  del  delegado  printString y  los  métodos  WriteToScreen  y  WriteToFile.  

Ejemplo  de  delegado.      

public void Increment(MagicNumber mn) {

mn.Numer++; } public void Decrement(MagicNumber mn) {

mn.Numer--; }

public class MagicNumber { public int Number { get; set; } }

public delegate void MagicNumberModifier(MagicNumber mn);

List<MagicNumber> magicNumbers = new List<MagicNumber>(); magicNumbers.Add(new MagicNumber() { Number = 4}); magicNumbers.Add(new MagicNumber() { Number = 6}); magicNumbers.Add(new MagicNumber() { Number = 9}); magicNumbers.Add(new MagicNumber() { Number = 13}); magicNumbers.Add(new MagicNumber() { Number = 20});

Creamos  una  lista  de  MagicNumber

Ejemplo  prácLco  

 Delegados Definir  un  método  que  aplique  el  delegado  MagicNumberModifier  a  la  lista  magicNumbers.  

Eventos  Mensaje  que  envía  un  objeto  cuando  ocurre  una  acción.  La  acción  puede  estar  causada  por  la  interacción  del  usuario,  como  un  click,  o  por  otra   lógica  del  programa.  El  objeto  que  provoca  el  evento  se  conoce  como   remitente  del  evento.  El  objeto  que  captura  el  evento  y  responde  a  él  se  denomina  receptor  del  evento.  

C#  permite  hacer  uso    del  patrón  publicador-­‐subscriptor  a  través  del  uso  de  delegados  y  eventos.    

El   remitente   determina   cuándo   se   produce   un   evento;   los   receptores   o   suscriptores  determinan  qué  operación  se  realiza  en  respuesta  al  evento.  

Un  evento  puede   tener  varios  suscriptores.  Un  suscriptor  puede  controlar  varios  eventos  de  varios  editores.  

Nunca  se  provocan  eventos  que  no  Lenen  suscriptores.  

Si   un   evento   Lene   varios   suscriptores,   se   invoca   a   los   controladores   de   eventos  síncronamente  cuando  se  produce  el  evento.  

En   la   biblioteca   de   clases   .NET   Framework,   los   eventos   se   basan   en   el   delegado  EventHandler  y  en  la  clase  base  EventArgs.  

Eventos  Sintaxis  a  seguir  para  declarar  un  evento.  

{modificador acceso} event {delegado} {identificador};

Para  declarar  un  evento  en  una  clase  en  primer  lugar  debemos  declarar  un  delegado  para  dicho  evento.  

public delegate void NumManipulationHandler();

Después  declaramos  el  evento:  

public event NumManipulationHandler ChangeNum;

1  

2  

Declaración  de  delegado.  public class EventSample { private int value; public delegate void NumManipulationHandler(); public event NumManipulationHandler ChangeNum; protected virtual void OnNumChanged() { if (ChangeNum != null) { ChangeNum(); } else { Console.WriteLine("Event fired!"); } } public EventTest(int n) { SetValue(n); } public void SetValue(int n) { if (value != n) { value = n; OnNumChanged(); } } }

Declaración  del  evento.  

Event Fired! Event Fired! Event Fired! Press any key to continue...

1  

2  

public class MainClass { public static void Main() { EventTest e = new EventTest(5); e.SetValue(7); e.SetValue(11); Console.ReadKey(); } }

public class BoilerEventAppl   { class Boiler { private int temp; private int pressure; public Boiler(int t, int p) { temp = t; pressure = p; } public int getTemp() { return temp; } public int getPressure() { return pressure; } } } // this class keeps a provision for writing into the log file class BoilerInfoLogger { FileStream fs; StreamWriter sw; public BoilerInfoLogger(string filename) { fs = new FileStream(filename, FileMode.Append, FileAccess.Write); sw = new StreamWriter(fs); } public void Logger(string info) { sw.WriteLine(info); } public void Close() { sw.Close(); fs.Close(); } }  

// event publisher class DelegateBoilerEvent { public delegate void BoilerLogHandler(string status); //Defining event based on the above delegate public event BoilerLogHandler BoilerEventLog; public void LogProcess() { string remarks = "O. K"; Boiler b = new Boiler(100, 12); int t = b.getTemp(); int p = b.getPressure(); if (t > 150 || t < 80 || p < 12 || p > 15) remarks = "Need Maintenance”; OnBoilerEventLog("Logging Info:\n"); OnBoilerEventLog("Temparature " + t + "\nPressure: " + p); OnBoilerEventLog("\nMessage: " + remarks); } protected void OnBoilerEventLog(string message) { if (BoilerEventLog != null) { BoilerEventLog(message); } } }  

eventos Ejemplo  prácLco  

Logging info: Temperature 100 Pressure 12 Message: O.K

public class RecordBoilerInfo { static void Logger(string info) { Console.WriteLine(info); } static void Main(string[] args) { BoilerInfoLogger filelog = new BoilerInfoLogger("e:\\boiler.txt"); DelegateBoilerEvent boilerEvent = new DelegateBoilerEvent(); boilerEvent.BoilerEventLog += new DelegateBoilerEvent.BoilerLogHandler(Logger); boilerEvent.BoilerEventLog += new DelegateBoilerEvent.BoilerLogHandler(filelog.Logger); boilerEvent.LogProcess(); Console.ReadLine(); filelog.Close(); } }

[modificador_acceso] static class Nombre_Clase_Estatica { [modificador_acceso] static bool Nombre_Metodo(this Tipo_A_Extender nombre [,otros_parametros] { // Implementación } }

Métodos  de  extensión  permiten  "agregar"  métodos  a  los  Lpos  existentes  sin  crear  un  nuevo  Lpo  derivado,  recompilar  o  modificar  de  otra  manera  el  Lpo  original.  

[modificador_acceso] static class Nombre_Clase_Estatica { [modificador_acceso] static bool Nombre_Metodo(this Tipo_A_Extender nombre [,otros_parametros] { // Implementación } }

Métodos  de  extensión  permiten  "agregar"  métodos  a  los  Lpos  existentes  sin  crear  un  nuevo  Lpo  derivado,  recompilar  o  modificar  de  otra  manera  el  Lpo  original.  

namespace ExtensionMethods { public static class StringExtensions { public static int WordCount(this String str) { return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; } } }

Método  de  extensión  para  la  clase String    

 

Tests  unitarios  con  MSTest  El  arte  de  medir  y  mantener    

la  calidad  del  soRware  

Tests  unitarios  Beneficios  de  las  pruebas  unitarias  

Fomentan  el  cambio  y  la  refactorización.  Podemos  cambiar  sin  ningún  problema  nuestro  código  si  lo  consideramos  mejorable.  Si  el  cambio  no  estuviera  realizado  correctamente,  las  pruebas  nos  avisarían  de  ello.  Seguramente  la  frase  “si  funciona  no  lo  toques”  a  más  de  uno  nos  resultará  familiar.  Si  hubiera  pruebas  unitarias,  no  sería  necesario  pronunciarla.    

 Se  reducen  drás6camente  los  problemas  y  6empos  dedicados  a  la  integración.  En  las  pruebas  se  simulan  las  dependencias,  lo  que  nos  permite  que  podamos  probar  nuestro  código  sin  disponer  del  resto  de  módulos.  Ya  sabemos,  por  experiencia,  que  los  procesos  de  integración  son  más  de  una  vez  traumáLcos,  dejándolos  habitualmente  para  el  final  del  proyecto.  La  frase  “sólo  queda  integrar”,  haciendo  referencia  a  que  el  proyecto  está  cerca  de  terminar,  suele  ser  engañosa,  ya  que  el  periodo  de  integración  suele  estar  lleno  de  curvas.  

Nos  ayudan  a  entender  mejor  el  código.  A  través  de  las  pruebas  podemos  comprender  mejor  qué  hace  un  método  y  qué  se  espera  de  él.  

Nos  permiten  probar  o  depurar  un  módulo  sin  necesidad  de  disponer  del  sistema  completo.  Aunque  seamos  los  propietarios  de  toda  la  aplicación,  en  algunas  situaciones  montar  un  entorno  para  poder  probar  una  incidencia  es  más  costoso  que  corregir  la  incidencia  propiamente  dicha.  Si  parLmos  de  la  prueba  unitaria  podemos  centrarnos  en  corregir  el  error  de  una  forma  más  rápida  y  lógicamente,  asegurándonos  posteriormente  que  todo  funciona  según  lo  esperado.  

Forma  de  probar  el  correcto  funcionamiento  de  una  parte  del  código.  

Tests  unitarios  Beneficios  de  las  pruebas  unitarias  

Se  reducen  drás6camente  los  problemas  y  6empos  dedicados  a  la  integración.  En  las  pruebas  se  simulan  las  dependencias,  lo  que  nos  permite  que  podamos  probar  nuestro  código  sin  disponer  del  resto  de  módulos.  Ya  sabemos,  por  experiencia,  que  los  procesos  de  integración  son  más  de  una  vez  traumáLcos,  dejándolos  habitualmente  para  el  final  del  proyecto.  La  frase  “sólo  queda  integrar”,  haciendo  referencia  a  que  el  proyecto  está  cerca  de  terminar,  suele  ser  engañosa,  ya  que  el  periodo  de  integración  suele  estar  lleno  de  curvas.  

Forma  de  probar  el  correcto  funcionamiento  de  una  parte  del  código.  

Nos  ayudan  a  entender  mejor  el  código.  A  través  de  las  pruebas  podemos  comprender  mejor  qué  hace  un  método  y  qué  se  espera  de  él.  

Nos  permiten  probar  o  depurar  un  módulo  sin  necesidad  de  disponer  del  sistema  completo.  Aunque  seamos  los  propietarios  de  toda  la  aplicación,  en  algunas  situaciones  montar  un  entorno  para  poder  probar  una  incidencia  es  más  costoso  que  corregir  la  incidencia  propiamente  dicha.  Si  parLmos  de  la  prueba  unitaria  podemos  centrarnos  en  corregir  el  error  de  una  forma  más  rápida  y  lógicamente,  asegurándonos  posteriormente  que  todo  funciona  según  lo  esperado.  

Fomentan  el  cambio  y  la  refactorización.  Podemos  cambiar  sin  ningún  problema  nuestro  código  si  lo  consideramos  mejorable.  Si  el  cambio  no  estuviera  realizado  correctamente,  las  pruebas  nos  avisarían  de  ello.  Seguramente  la  frase  “si  funciona  no  lo  toques”  a  más  de  uno  nos  resultará  familiar.  Si  hubiera  pruebas  unitarias,  no  sería  necesario  pronunciarla.    

 

Tests  unitarios  Beneficios  de  las  pruebas  unitarias  

Nos  ayudan  a  entender  mejor  el  código.  A  través  de  las  pruebas  podemos  comprender  mejor  qué  hace  un  método  y  qué  se  espera  de  él.  

Forma  de  probar  el  correcto  funcionamiento  de  una  parte  del  código.  

Nos  permiten  probar  o  depurar  un  módulo  sin  necesidad  de  disponer  del  sistema  completo.  Aunque  seamos  los  propietarios  de  toda  la  aplicación,  en  algunas  situaciones  montar  un  entorno  para  poder  probar  una  incidencia  es  más  costoso  que  corregir  la  incidencia  propiamente  dicha.  Si  parLmos  de  la  prueba  unitaria  podemos  centrarnos  en  corregir  el  error  de  una  forma  más  rápida  y  lógicamente,  asegurándonos  posteriormente  que  todo  funciona  según  lo  esperado.  

Fomentan  el  cambio  y  la  refactorización.  Podemos  cambiar  sin  ningún  problema  nuestro  código  si  lo  consideramos  mejorable.  Si  el  cambio  no  estuviera  realizado  correctamente,  las  pruebas  nos  avisarían  de  ello.  Seguramente  la  frase  “si  funciona  no  lo  toques”  a  más  de  uno  nos  resultará  familiar.  Si  hubiera  pruebas  unitarias,  no  sería  necesario  pronunciarla.    

 Se  reducen  drás6camente  los  problemas  y  6empos  dedicados  a  la  integración.  En  las  pruebas  se  simulan  las  dependencias,  lo  que  nos  permite  que  podamos  probar  nuestro  código  sin  disponer  del  resto  de  módulos.  Ya  sabemos,  por  experiencia,  que  los  procesos  de  integración  son  más  de  una  vez  traumáLcos,  dejándolos  habitualmente  para  el  final  del  proyecto.  La  frase  “sólo  queda  integrar”,  haciendo  referencia  a  que  el  proyecto  está  cerca  de  terminar,  suele  ser  engañosa,  ya  que  el  periodo  de  integración  suele  estar  lleno  de  curvas.  

Tests  unitarios  Beneficios  de  las  pruebas  unitarias  

Nos  permiten  probar  o  depurar  un  módulo  sin  necesidad  de  disponer  del  sistema  completo.  Aunque  seamos  los  propietarios  de  toda  la  aplicación,  en  algunas  situaciones  montar  un  entorno  para  poder  probar  una  incidencia  es  más  costoso  que  corregir  la  incidencia  propiamente  dicha.  Si  parLmos  de  la  prueba  unitaria  podemos  centrarnos  en  corregir  el  error  de  una  forma  más  rápida  y  lógicamente,  asegurándonos  posteriormente  que  todo  funciona  según  lo  esperado.  

Forma  de  probar  el  correcto  funcionamiento  de  una  parte  del  código.  

Fomentan  el  cambio  y  la  refactorización.  Podemos  cambiar  sin  ningún  problema  nuestro  código  si  lo  consideramos  mejorable.  Si  el  cambio  no  estuviera  realizado  correctamente,  las  pruebas  nos  avisarían  de  ello.  Seguramente  la  frase  “si  funciona  no  lo  toques”  a  más  de  uno  nos  resultará  familiar.  Si  hubiera  pruebas  unitarias,  no  sería  necesario  pronunciarla.    

 Se  reducen  drás6camente  los  problemas  y  6empos  dedicados  a  la  integración.  En  las  pruebas  se  simulan  las  dependencias,  lo  que  nos  permite  que  podamos  probar  nuestro  código  sin  disponer  del  resto  de  módulos.  Ya  sabemos,  por  experiencia,  que  los  procesos  de  integración  son  más  de  una  vez  traumáLcos,  dejándolos  habitualmente  para  el  final  del  proyecto.  La  frase  “sólo  queda  integrar”,  haciendo  referencia  a  que  el  proyecto  está  cerca  de  terminar,  suele  ser  engañosa,  ya  que  el  periodo  de  integración  suele  estar  lleno  de  curvas.  

Nos  ayudan  a  entender  mejor  el  código.  A  través  de  las  pruebas  podemos  comprender  mejor  qué  hace  un  método  y  qué  se  espera  de  él.  

Tests  unitarios   Forma  de  probar  el  correcto  funcionamiento  de  una  parte  del  código.  

¡¡  La  vida  del  desarrollador  será    mucho  más  fácil  !!  

La  calidad  de  nuestro  código  mejorará,  se  reducirán  los  Bempos  de  depuración  y  la  corrección  de  incidencias.    Por  tanto,  el  cliente  estará  mucho  más  contento  porque  la  aplicación  hace  lo  que  él  quiere  que  haga,  que  realmente  es  por  lo  que  ha  pagado.      

Beneficios  de  las  pruebas  unitarias  

Tests  unitarios  Caracterís6cas  de  una  buena  prueba  unitaria  

Automa6zable.  Las  pruebas  unitarias  se  Lenen  que  poder  ejecutar  sin  necesidad  de  intervención  manual.  Esta  caracterísLca  posibilita  que  podamos  automaLzar  su  ejecución,  siendo  muy  úLl  en  integración  conLnua.  

 Tienen  que  poder  repe6rse  tantas  veces  como  uno  quiera.  Por  este  moLvo,  la  rapidez  de  las  pruebas  Lene  un  factor  clave.  Si  pasar  las  pruebas  es  un  proceso  lento  no  se  pasarán  de  forma  habitual,  por  lo  que  se  perderán  los  beneficios  que  éstas  nos  ofrecen.  

Deben  poder  cubrir  casi  la  totalidad  del  código  (o  por  lo  menos  el  más  crí6co)  de  nuestra  aplicación.  Una  prueba  unitaria  sera  tan  buena  como  su  cobertura  de  código.  La  cobertura  de  código  marca  la  canLdad  de  código  de  la  aplicación  que  está  someLdo  a  una  prueba.  Por  tanto,  si  la  cobertura  es  baja,  significará  que  gran  parte  de  nuestro  código  está  sin  probar.  

Independientes.  La  ejecución  de  una  prueba  no  debe  afectar  a  la  ejecución  de  otra.  Después  de  la  ejecución  de  una  prueba  el  entorno  debería  quedar  igual  que  estaba  antes  de  realizar  la  prueba.      Profesionales.  Cualquier  desarrollador  debería  poder  conocer  claramente  cuál  es  el  objeLvo  de  la  prueba  y  su  funcionamiento.  Esto  sólo  se  consigue  si  se  trata  el  código  de  pruebas  como  el  código  de  la  aplicación,  con  la  misma  profesionalidad,  documentación,  etc.  

Tests  unitarios  Caracterís6cas  de  una  buena  prueba  unitaria  

Automa6zable.  Las  pruebas  unitarias  se  Lenen  que  poder  ejecutar  sin  necesidad  de  intervención  manual.  Esta  caracterísLca  posibilita  que  podamos  automaLzar  su  ejecución,  siendo  muy  úLl  en  integración  conLnua.  

 Tienen  que  poder  repe6rse  tantas  veces  como  uno  quiera.  Por  este  moLvo,  la  rapidez  de  las  pruebas  Lene  un  factor  clave.  Si  pasar  las  pruebas  es  un  proceso  lento  no  se  pasarán  de  forma  habitual,  por  lo  que  se  perderán  los  beneficios  que  éstas  nos  ofrecen.  

Deben  poder  cubrir  casi  la  totalidad  del  código  (o  por  lo  menos  el  más  crí6co)  de  nuestra  aplicación.  Una  prueba  unitaria  sera  tan  buena  como  su  cobertura  de  código.  La  cobertura  de  código  marca  la  canLdad  de  código  de  la  aplicación  que  está  someLdo  a  una  prueba.  Por  tanto,  si  la  cobertura  es  baja,  significará  que  gran  parte  de  nuestro  código  está  sin  probar.  

Independientes.  La  ejecución  de  una  prueba  no  debe  afectar  a  la  ejecución  de  otra.  Después  de  la  ejecución  de  una  prueba  el  entorno  debería  quedar  igual  que  estaba  antes  de  realizar  la  prueba.      Profesionales.  Cualquier  desarrollador  debería  poder  conocer  claramente  cuál  es  el  objeLvo  de  la  prueba  y  su  funcionamiento.  Esto  sólo  se  consigue  si  se  trata  el  código  de  pruebas  como  el  código  de  la  aplicación,  con  la  misma  profesionalidad,  documentación,  etc.  

Tests  unitarios  Caracterís6cas  de  una  buena  prueba  unitaria  

Automa6zable.  Las  pruebas  unitarias  se  Lenen  que  poder  ejecutar  sin  necesidad  de  intervención  manual.  Esta  caracterísLca  posibilita  que  podamos  automaLzar  su  ejecución,  siendo  muy  úLl  en  integración  conLnua.  

 Tienen  que  poder  repe6rse  tantas  veces  como  uno  quiera.  Por  este  moLvo,  la  rapidez  de  las  pruebas  Lene  un  factor  clave.  Si  pasar  las  pruebas  es  un  proceso  lento  no  se  pasarán  de  forma  habitual,  por  lo  que  se  perderán  los  beneficios  que  éstas  nos  ofrecen.  

Deben  poder  cubrir  casi  la  totalidad  del  código  (o  por  lo  menos  el  más  crí6co)  de  nuestra  aplicación.  Una  prueba  unitaria  sera  tan  buena  como  su  cobertura  de  código.  La  cobertura  de  código  marca  la  canLdad  de  código  de  la  aplicación  que  está  someLdo  a  una  prueba.  Por  tanto,  si  la  cobertura  es  baja,  significará  que  gran  parte  de  nuestro  código  está  sin  probar.  

Independientes.  La  ejecución  de  una  prueba  no  debe  afectar  a  la  ejecución  de  otra.  Después  de  la  ejecución  de  una  prueba  el  entorno  debería  quedar  igual  que  estaba  antes  de  realizar  la  prueba.      Profesionales.  Cualquier  desarrollador  debería  poder  conocer  claramente  cuál  es  el  objeLvo  de  la  prueba  y  su  funcionamiento.  Esto  sólo  se  consigue  si  se  trata  el  código  de  pruebas  como  el  código  de  la  aplicación,  con  la  misma  profesionalidad,  documentación,  etc.  

Tests  unitarios  Caracterís6cas  de  una  buena  prueba  unitaria  

Automa6zable.  Las  pruebas  unitarias  se  Lenen  que  poder  ejecutar  sin  necesidad  de  intervención  manual.  Esta  caracterísLca  posibilita  que  podamos  automaLzar  su  ejecución,  siendo  muy  úLl  en  integración  conLnua.  

 Tienen  que  poder  repe6rse  tantas  veces  como  uno  quiera.  Por  este  moLvo,  la  rapidez  de  las  pruebas  Lene  un  factor  clave.  Si  pasar  las  pruebas  es  un  proceso  lento  no  se  pasarán  de  forma  habitual,  por  lo  que  se  perderán  los  beneficios  que  éstas  nos  ofrecen.  

Deben  poder  cubrir  casi  la  totalidad  del  código  (o  por  lo  menos  el  más  crí6co)  de  nuestra  aplicación.  Una  prueba  unitaria  sera  tan  buena  como  su  cobertura  de  código.  La  cobertura  de  código  marca  la  canLdad  de  código  de  la  aplicación  que  está  someLdo  a  una  prueba.  Por  tanto,  si  la  cobertura  es  baja,  significará  que  gran  parte  de  nuestro  código  está  sin  probar.  

Independientes.  La  ejecución  de  una  prueba  no  debe  afectar  a  la  ejecución  de  otra.  Después  de  la  ejecución  de  una  prueba  el  entorno  debería  quedar  igual  que  estaba  antes  de  realizar  la  prueba.      Profesionales.  Cualquier  desarrollador  debería  poder  conocer  claramente  cuál  es  el  objeLvo  de  la  prueba  y  su  funcionamiento.  Esto  sólo  se  consigue  si  se  trata  el  código  de  pruebas  como  el  código  de  la  aplicación,  con  la  misma  profesionalidad,  documentación,  etc.  

Tests  unitarios  Caracterís6cas  de  una  buena  prueba  unitaria  

Automa6zable.  Las  pruebas  unitarias  se  Lenen  que  poder  ejecutar  sin  necesidad  de  intervención  manual.  Esta  caracterísLca  posibilita  que  podamos  automaLzar  su  ejecución,  siendo  muy  úLl  en  integración  conLnua.  

 Tienen  que  poder  repe6rse  tantas  veces  como  uno  quiera.  Por  este  moLvo,  la  rapidez  de  las  pruebas  Lene  un  factor  clave.  Si  pasar  las  pruebas  es  un  proceso  lento  no  se  pasarán  de  forma  habitual,  por  lo  que  se  perderán  los  beneficios  que  éstas  nos  ofrecen.  

Deben  poder  cubrir  casi  la  totalidad  del  código  (o  por  lo  menos  el  más  crí6co)  de  nuestra  aplicación.  Una  prueba  unitaria  sera  tan  buena  como  su  cobertura  de  código.  La  cobertura  de  código  marca  la  canLdad  de  código  de  la  aplicación  que  está  someLdo  a  una  prueba.  Por  tanto,  si  la  cobertura  es  baja,  significará  que  gran  parte  de  nuestro  código  está  sin  probar.  

Independientes.  La  ejecución  de  una  prueba  no  debe  afectar  a  la  ejecución  de  otra.  Después  de  la  ejecución  de  una  prueba  el  entorno  debería  quedar  igual  que  estaba  antes  de  realizar  la  prueba.      Profesionales.  Cualquier  desarrollador  debería  poder  conocer  claramente  cuál  es  el  objeLvo  de  la  prueba  y  su  funcionamiento.  Esto  sólo  se  consigue  si  se  trata  el  código  de  pruebas  como  el  código  de  la  aplicación,  con  la  misma  profesionalidad,  documentación,  etc.  

Tests  unitarios  Aunque  los  beneficios  de  las  pruebas  unitarias  puedan  parecer  claros,  todavía  existen  hoy  en  día  proyectos  que  carecen  de  éstas.  Pero  sin  son  tan  buenas,  ¿por  qué  hay  desarrolladores  que  no  las  usan?  La  razón  principal  es  que  existe  bastante  desconocimiento  en  esta  materia,  poca  tradición  y  algunos  falsos  mitos.  

Mitos  de  las  pruebas  unitarias  

Creer  que  escribir  pruebas  unitarias  es  escribir  el  doble  de  código.  Escribir  una  prueba  nunca  es  escribir  el  doble  de  código,  aunque  lógicamente  sí  es  escribir  más  código.  El  mito  es  totalmente  falso.  Debes  estar  convencido  de  que  el  uso  de  pruebas  unitarias  es  el  enfoque  correcto  y  no  ser  flexible;  las  pruebas  unitarias  no  son  opcionales  y  deben  realizarse  a  medida  que  se  desarrolla.  

Desarrollar  pruebas  incrementan  los  6empos  de  desarrollo,  incrementando  los  costes  del  proyecto.  Entre  desarrollar  y  no  probar  y  desarrollar  haciendo  pruebas  unitarias,  reconoceremos  que  es  más  rápido  desarrollar  sin  probar.  Si  no  desarrollamos  código  de  calidad  y  no  realizamos  pruebas,  los  Lempos  de  desarrollo  se  podrán  disparar  enormemente:  Lempo  de  integración,  Lempo  de  depuración,  Lempo  de  incidencias,  etc.  y  existe  un  problema  mayor:  la  confianza  del  cliente.  Un  producto  de  baja  calidad,  lleno  de  incidencias,  es  la  peor  tarjeta  de  presentación.        

Tests  unitarios  Mitos  de  las  pruebas  unitarias  

Creer  que  escribir  pruebas  unitarias  es  escribir  el  doble  de  código.  Escribir  una  prueba  nunca  es  escribir  el  doble  de  código,  aunque  lógicamente  sí  es  escribir  más  código.  El  mito  es  totalmente  falso.  Debes  estar  convencido  de  que  el  uso  de  pruebas  unitarias  es  el  enfoque  correcto  y  no  ser  flexible;  las  pruebas  unitarias  no  son  opcionales  y  deben  realizarse  a  medida  que  se  desarrolla.  

Desarrollar  pruebas  incrementan  los  6empos  de  desarrollo,  incrementando  los  costes  del  proyecto.  Entre  desarrollar  y  no  probar  y  desarrollar  haciendo  pruebas  unitarias,  reconoceremos  que  es  más  rápido  desarrollar  sin  probar.  Si  no  desarrollamos  código  de  calidad  y  no  realizamos  pruebas,  los  Lempos  de  desarrollo  se  podrán  disparar  enormemente:  Lempo  de  integración,  Lempo  de  depuración,  Lempo  de  incidencias,  etc.  y  existe  un  problema  mayor:  la  confianza  del  cliente.  Un  producto  de  baja  calidad,  lleno  de  incidencias,  es  la  peor  tarjeta  de  presentación.        

Aunque  los  beneficios  de  las  pruebas  unitarias  puedan  parecer  claros,  todavía  existen  hoy  en  día  proyectos  que  carecen  de  éstas.  Pero  sin  son  tan  buenas,  ¿por  qué  hay  desarrolladores  que  no  las  usan?  La  razón  principal  es  que  existe  bastante  desconocimiento  en  esta  materia,  poca  tradición  y  algunos  falsos  mitos.  

Tests  unitarios  Nos  proporciona  un  sistema  sencillo  para  poder  crear  nuestras  pruebas  unitarias.  Nos  facilita  la  creación  de  los  proyectos  de  pruebas  y  nos  genera  la  estructura  básica  que  Lenen  que  tener  las  pruebas.      

Visual  Studio  

Visual  Studio  Unit  TesLng  Framework  

MSTest Una  de  las  herramientas  más  poderosas  que  tenemos  los  desarrolladores  actualmente.  

Tests  unitarios  

hsps://msdn.microsoR.com/es-­‐es/library/ms182532.aspx#bkmk_create_a_unit_test_project      

Ejemplo  prácLco  

Visual  Studio  Unit  TesLng  Framework  

MSTest

Anatomía:  sección  superior  Tests  unitarios  

using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BankAccountTests { [TestClass] public class BankAccountTests { private TestContext testContextInstance; public TestContext TestContext {

get { return testContextInstance; } set { testContextInstance = value; }

} ... } }

Microsoft.VisualStudio.TestTools.UnitTesting

al  crear  una  prueba  unitaria,  se  agrega  al  proyecto  de  prueba  una  referencia  al  espacio  de  nombres  Microsoft.VisualStudio.TestTools.UnitTesting.  El  espacio  de  nombres  Lene  muchas  clases  para  ayudarnos  con  las  pruebas  unitarias:  Clases  Assert  que  se  pueden  uLlizar  para  comprobar  las  condiciones  en  las  pruebas  unitarias,  Atributos  de  inicialización  y  limpieza  para  ejecutar  código  antes  o  después  de  ejecutar  las  pruebas  unitarias,  a  fin  de  asegurarse  un  estado  inicial  y  final  concretos,  la  clase  TestContext  que  almacena  la  información  que  se  proporciona  a  las  pruebas  unitarias,  como  la  conexión  de  datos  para  las  pruebas  controladas  por  datos,  etc.  

TestClassAttribute

indica  que  esta  clase  determinada  puede  contener  métodos  marcados  con  el  atributo  [TestMethod()].  Sin  TestClassAttribute  los  métodos  de  prueba  se  omiten.  

TestContext

se  incluye  una  variable  denominada  testContextInstance  para  cada  clase  de  prueba.  Las  propiedades  de  la  clase  TestContext  almacenan  información  referente  a  la  prueba  actual.  

Tests  unitarios  

using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BankAccountTests { [TestClass] public class BankAccountTests { private TestContext testContextInstance; public TestContext TestContext {

get { return testContextInstance; } set { testContextInstance = value; }

} ... } }

TestClassAttribute

indica  que  esta  clase  determinada  puede  contener  métodos  marcados  con  el  atributo  [TestMethod()].  Sin  TestClassAttribute  los  métodos  de  prueba  se  omiten.  

TestContext

se  incluye  una  variable  denominada  testContextInstance  para  cada  clase  de  prueba.  Las  propiedades  de  la  clase  TestContext  almacenan  información  referente  a  la  prueba  actual.  

Microsoft.VisualStudio.TestTools.UnitTesting

al  crear  una  prueba  unitaria,  se  agrega  al  proyecto  de  prueba  una  referencia  al  espacio  de  nombres  Microsoft.VisualStudio.TestTools.UnitTesting.  El  espacio  de  nombres  Lene  muchas  clases  para  ayudarnos  con  las  pruebas  unitarias:  Clases  Assert  que  se  pueden  uLlizar  para  comprobar  las  condiciones  en  las  pruebas  unitarias,  Atributos  de  inicialización  y  limpieza  para  ejecutar  código  antes  o  después  de  ejecutar  las  pruebas  unitarias,  a  fin  de  asegurarse  un  estado  inicial  y  final  concretos,  la  clase  TestContext  que  almacena  la  información  que  se  proporciona  a  las  pruebas  unitarias,  como  la  conexión  de  datos  para  las  pruebas  controladas  por  datos,  etc.  

Anatomía:  sección  superior  

Tests  unitarios  

using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BankAccountTests { [TestClass] public class BankAccountTests { private TestContext testContextInstance; public TestContext TestContext {

get { return testContextInstance; } set { testContextInstance = value; }

} ... } }

Microsoft.VisualStudio.TestTools.UnitTesting

al  crear  una  prueba  unitaria,  se  agrega  al  proyecto  de  prueba  una  referencia  al  espacio  de  nombres  Microsoft.VisualStudio.TestTools.UnitTesting.  El  espacio  de  nombres  Lene  muchas  clases  para  ayudarnos  con  las  pruebas  unitarias:  Clases  Assert  que  se  pueden  uLlizar  para  comprobar  las  condiciones  en  las  pruebas  unitarias,  Atributos  de  inicialización  y  limpieza  para  ejecutar  código  antes  o  después  de  ejecutar  las  pruebas  unitarias,  a  fin  de  asegurarse  un  estado  inicial  y  final  concretos,  la  clase  TestContext  que  almacena  la  información  que  se  proporciona  a  las  pruebas  unitarias,  como  la  conexión  de  datos  para  las  pruebas  controladas  por  datos,  etc.  

TestClassAttribute

indica  que  esta  clase  determinada  puede  contener  métodos  marcados  con  el  atributo  [TestMethod()].  Sin  TestClassAttribute  los  métodos  de  prueba  se  omiten.  

TestContext

se  incluye  una  variable  denominada  testContextInstance  para  cada  clase  de  prueba.  Las  propiedades  de  la  clase  TestContext  almacenan  información  referente  a  la  prueba  actual.  

Anatomía:  sección  superior  

Tests  unitarios  

using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BankAccountTests { [TestClass] public class BankAccountTests { private TestContext testContextInstance; public TestContext TestContext {

get { return testContextInstance; } set { testContextInstance = value; }

} ... } }

Microsoft.VisualStudio.TestTools.UnitTesting

al  crear  una  prueba  unitaria,  se  agrega  al  proyecto  de  prueba  una  referencia  al  espacio  de  nombres  Microsoft.VisualStudio.TestTools.UnitTesting.  El  espacio  de  nombres  Lene  muchas  clases  para  ayudarnos  con  las  pruebas  unitarias:  Clases  Assert  que  se  pueden  uLlizar  para  comprobar  las  condiciones  en  las  pruebas  unitarias,  Atributos  de  inicialización  y  limpieza  para  ejecutar  código  antes  o  después  de  ejecutar  las  pruebas  unitarias,  a  fin  de  asegurarse  un  estado  inicial  y  final  concretos,  la  clase  TestContext  que  almacena  la  información  que  se  proporciona  a  las  pruebas  unitarias,  como  la  conexión  de  datos  para  las  pruebas  controladas  por  datos,  etc.  

TestClassAttribute

indica  que  esta  clase  determinada  puede  contener  métodos  marcados  con  el  atributo  [TestMethod()].  Sin  TestClassAttribute  los  métodos  de  prueba  se  omiten.  

TestContext

se  incluye  una  variable  denominada  testContextInstance  para  cada  clase  de  prueba.  Las  propiedades  de  la  clase  TestContext  almacenan  información  referente  a  la  prueba  actual.  

Anatomía:  sección  superior  

[TestMethod] public void Debit_WithValidAmount_UpdatesBalance() { // arrange double beginningBalance = 11.99; double debitAmount = 4.55; double expected = 7.44; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); // act account.Debit(debitAmount); // assert double actual = account.Balance; Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly"); }

Tests  unitarios  

Additional test attribute

Anatomía:  sección  inferior  

[TestMethod] public void Debit_WithValidAmount_UpdatesBalance() { // arrange double beginningBalance = 11.99; double debitAmount = 4.55; double expected = 7.44; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); // act account.Debit(debitAmount); // assert double actual = account.Balance; Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly"); }

Tests  unitarios  

Additional test attribute

Atributos de prueba adicionales

[ClassInitialize] para  ejecutar  código  antes  de  la  primera  prueba  de  la  clase.    [ClassCleanUp]

para  ejecutar  código  cuando  todas  las  pruebas  de  una  clase  se  hayan  ejecutado.    [TestInitialize] para  ejecutar  código  antes  de  hacer  cada  prueba.    [TestCleanUp]

para  ejecutar  código  cuando  cada  prueba  se  haya  ejecutado.          

Anatomía:  sección  inferior  

[TestMethod] public void Debit_WithValidAmount_UpdatesBalance() { // arrange double beginningBalance = 11.99; double debitAmount = 4.55; double expected = 7.44; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); // act account.Debit(debitAmount); // assert double actual = account.Balance; Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly"); }

Tests  unitarios  

Additional test attribute

Atributos de prueba adicionales

[ClassInitialize] para  ejecutar  código  antes  de  la  primera  prueba  de  la  clase.    [ClassCleanUp]

para  ejecutar  código  cuando  todas  las  pruebas  de  una  clase  se  hayan  ejecutado.    [TestInitialize] para  ejecutar  código  antes  de  hacer  cada  prueba.    [TestCleanUp]

para  ejecutar  código  cuando  cada  prueba  se  haya  ejecutado.          

TestMethodAttribute

cada  método  de  prueba  unitaria  se  marca  con  el  atributo  [TestMethod].  Sin  este  atributo,  la  prueba  unitaria  no  se  ejecuta.  

Anatomía:  sección  inferior  

[TestMethod] public void Debit_WithValidAmount_UpdatesBalance() { // arrange double beginningBalance = 11.99; double debitAmount = 4.55; double expected = 7.44; BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance); // act account.Debit(debitAmount); // assert double actual = account.Balance; Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly"); }

Tests  unitarios  

Additional test attribute

Atributos de prueba adicionales

[ClassInitialize] para  ejecutar  código  antes  de  la  primera  prueba  de  la  clase.    [ClassCleanUp]

para  ejecutar  código  cuando  todas  las  pruebas  de  una  clase  se  hayan  ejecutado.    [TestInitialize] para  ejecutar  código  antes  de  hacer  cada  prueba.    [TestCleanUp]

para  ejecutar  código  cuando  cada  prueba  se  haya  ejecutado.          

TestMethodAttribute

cada  método  de  prueba  unitaria  se  marca  con  el  atributo  [TestMethod].  Sin  este  atributo,  la  prueba  unitaria  no  se  ejecuta.  

Lógica del método de prueba

El  contenido  de  los  métodos  de  prueba  varía  dependiendo  del  Lpo  de  prueba  unitaria  y  de  la  naturaleza  del  método  que  se  prueba.  

Anatomía:  sección  inferior  

Consumo  de  librerías  Consumo  de  librerías  de  terceros  de  

código  administrado  y  no  administrado  

Interoperabilidad Cómo  u6lizar  clases  de  código  no  administrado  desde  

aplicaciones  .NET  y  viceversa  

Consumo  de  librerías  Código  administrado  y  no  administrado  

Assembly  manifest  Type  metadata  

CIL  code  Resources  

Platform invoke

C#  

C  L  R  

Managed  source  code  

Compiler  

DLL  

func6on  DLL  

U  n  m  a  n  a  g  e  d   M    a    n    a    g    e    d  

Consumo  de  librerías  Es  el  código  que  ha  sido  creado  con  lenguajes  de  .NET,  por  ejemplo  Visual  Basic  .NET,  y  que  es  uLlizado  desde  otro  lenguaje,  también  de  .NET,  por  ejemplo  C#.  

Código  administrado  

Es  código  que  se  ejecuta  bajo  el  control  de  CLR  (Common  Language  Run6me)  

Consumo  de  librerías  Para  poder  uLlizar  las  librerías  creadas  en  cualquier  lenguaje  de  .NET  desde  nuestro  proyecto,  tendremos  que  seguir  los  mismos  pasos  que  para  añadir  referencias  de  cualquier  otra  librería:  por  medio  de  la  opción  “Add  Reference…”  en  la  pestaña  “SoluIon  Explorer”.  

Código  administrado  en  Visual  Studio  

Si  la  librería  ya  está  compilada  tendremos  que  pulsar  en  el  botón  “Browse”  y  localizar  el  ensamblado  (que  ya  debe  estar  compilado  como  .dll),  seleccionarlo  y  agregarlo.  Si  esa  librería  que  queremos  referenciar  es  un  proyecto  creado  (desarrollado)  por  nosotros,  podemos  añadirlo  a  la  solución  actual  y  agregar  la  referencia  indicando  el  proyecto,  desde  la  pestaña  “Projects”,  de  esta  forma  tendremos  oportunidad  de  depurar  la  librería  junto  a  nuestra  aplicación  cliente.    

 

Consumo  de  librerías  Es  el  código  que  se  ejecuta  fuera  del  control  de  Common  Language  RunLme  (CLR).  Los  componentes  COM,  COM+,  C++,  los  componentes  de  AcLveX  y  la  API  de  MicrosoR  Win32  son  ejemplos  de  código  no  administrado.  

Código  no  administrado  

Interoperabilidad  COM  Proporciona  compaLbilidad  con  versiones  anteriores  para  permiLr  el  acceso  a  componentes  COM,  también  conocidos  como  componentes  de  automaLzación  OLE  o  simplemente  AcLveX,  existentes  sin  necesidad  de  modificar  el  componente  original.  Este  Lpo  de  componentes  los  podemos  generar  con  lenguajes  capaces  de  crear  controles  o  librerías  AcLveX,  como  Visual  Basic  6.0.  Esta  forma  de  comunicación  la  podemos  realizar  en  dos  direcciones,  una  para  poder  acceder  desde  .NET  a  componentes  COM,  y  la  otra  para  acceder  a  componentes  creados  en  .NET  desde  lenguajes  capaces  de  uLlizar  COM.    

Invocación  de  plataforma  -­‐  PInvoke Posibilidad  de  llamar  a  funciones  no  administradas  implementadas  en  bibliotecas  de  vínculos  dinámicos  (DLL),  como  las  que  se  encuentran  en  la  API  de  MicrosoR  Win32.  

1

2

Consumo  de  librerías  Es  el  código  que  se  ejecuta  fuera  del  control  de  Common  Language  RunLme  (CLR).  Los  componentes  COM,  COM+,  C++,  los  componentes  de  AcLveX  y  la  API  de  MicrosoR  Win32  son  ejemplos  de  código  no  administrado.  

Código  no  administrado  

Interoperabilidad  COM  Proporciona  compaLbilidad  con  versiones  anteriores  para  permiLr  el  acceso  a  componentes  COM,  también  conocidos  como  componentes  de  automaLzación  OLE  o  simplemente  AcLveX,  existentes  sin  necesidad  de  modificar  el  componente  original.  Este  Lpo  de  componentes  los  podemos  generar  con  lenguajes  capaces  de  crear  controles  o  librerías  AcLveX,  como  Visual  Basic  6.0.  Esta  forma  de  comunicación  la  podemos  realizar  en  dos  direcciones,  una  para  poder  acceder  desde  .NET  a  componentes  COM,  y  la  otra  para  acceder  a  componentes  creados  en  .NET  desde  lenguajes  capaces  de  uLlizar  COM.    

Invocación  de  plataforma  -­‐  PInvoke Posibilidad  de  llamar  a  funciones  no  administradas  implementadas  en  bibliotecas  de  vínculos  dinámicos  (DLL),  como  las  que  se  encuentran  en  la  API  de  MicrosoR  Win32.  

1

2

Consumo  de  librerías  Es  el  código  que  se  ejecuta  fuera  del  control  de  Common  Language  RunLme  (CLR).  Los  componentes  COM,  COM+,  C++,  los  componentes  de  AcLveX  y  la  API  de  MicrosoR  Win32  son  ejemplos  de  código  no  administrado.  

Código  no  administrado  

Interoperabilidad  COM  Proporciona  compaLbilidad  con  versiones  anteriores  para  permiLr  el  acceso  a  componentes  COM,  también  conocidos  como  componentes  de  automaLzación  OLE  o  simplemente  AcLveX,  existentes  sin  necesidad  de  modificar  el  componente  original.  Este  Lpo  de  componentes  los  podemos  generar  con  lenguajes  capaces  de  crear  controles  o  librerías  AcLveX,  como  Visual  Basic  6.0.  Esta  forma  de  comunicación  la  podemos  realizar  en  dos  direcciones,  una  para  poder  acceder  desde  .NET  a  componentes  COM,  y  la  otra  para  acceder  a  componentes  creados  en  .NET  desde  lenguajes  capaces  de  uLlizar  COM.    

System.Runtime.InteropServices

.NET  Framework  proporciona  un  espacio  de  nombres  dedicado  que  habilita  la  interoperabilidad  con  el  código  no  administrado  a  través  de  los  servicios  de  invocación  de  plataforma:      

Invocación  de  plataforma  -­‐  PInvoke Posibilidad  de  llamar  a  funciones  no  administradas  implementadas  en  bibliotecas  de  vínculos  dinámicos  (DLL),  como  las  que  se  encuentran  en  la  API  de  MicrosoR  Win32.  

1

2

1   Interoperabilidad  COM  Cómo  hacer  uso  de  componentes  COM  desde  aplicaciones  .NET  en  Visual  Studio.  

Trabajar  con  componentes  COM  (o  componentes  AcLveX)  desde  Visual  Studio  .NET  es  relaLvamente  fácil  y  no  requiere  hacer  nada  especial  por  nuestra  parte,  ya  que  el  proceso  es  el  mismo  que  el  indicado  cuando  hacemos  uso  de  código  administrado:  agregar  una  referencia  en  nuestro  proyecto  al  componente  COM  (ya  sea  una  DLL  un  control  OCX  e  incluso  un  EXE),  que  queramos  usar.    De  forma  predeterminada,  y  tal  como  funciona  COM,  todos  los  controles  (OCX)  y  las  librerías  (DLL)  deben  estar  previamente  registrados  en  el  sistema,  por  tanto  esos  componentes  registrados  serán  los  que  se  muestren  en  la  pestaña  COM  del  cuadro  de  diálogo  de  agregar  referencias.  Seleccionamos  el  que  nos  interese  y  sera  el  propio  Visual  Studio  el  que  se  encargue  de  los  “pormenores”  para  que  podamos  usar  ese  componente  en  nuestro  proyecto  de  Visual  Studio.          

2   Invocación  de  plataforma  -­‐  PInvoke Cómo  hacer  uso  de  funciones  definidas  en  librerías  creadas  con  lenguajes  que  no  están  amparados  bajo  las  tecnologías  expuestas  por  .NET  Framework.  Un  ejemplo  de  estas  librerías  pueden  ser  librerías  implementadas  en  lenguajes  como  C/C++  o  Delphi.  El  caso  más  habitual  es  el  uso  de  las  funciones  del  API  de  Windows.  

Atributo  que  permite  invocar  funciones  de  código  no  administrado  desde  una  aplicación  administrada.  Debemos  aplicarlo  a  la  declaración  de  una  función  que  nos  servirá  de  puente  para  acceder  a  la  función  original  del  API.  

[DllImport]

DWORD GetLongPathName( LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer );  

2   Invocación  de  plataforma  -­‐  PInvoke Por  ejemplo,  si  tenemos  esta  declaración  del  API  de  Windows:  

En  C#  la  podríamos  declarar  de  esta  otra:      

System.Runtime.InteropServices.DllImport("kernel32.dll")] private extern static int GetLongPathName( string lpszShortPath, StringBuilder lpszLongPath, int cchBuffer );  

DWORD GetLongPathName( LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer );  

2   Invocación  de  plataforma  -­‐  PInvoke Por  ejemplo,  si  tenemos  esta  declaración  del  API  de  Windows:  

En  C#  la  podríamos  declarar  de  esta  otra:      

System.Runtime.InteropServices.DllImport("kernel32.dll")] private extern static int GetLongPathName( string lpszShortPath, StringBuilder lpszLongPath, int cchBuffer );  

DWORD GetLongPathName( LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer );  

2   Invocación  de  plataforma  -­‐  PInvoke Por  ejemplo,  si  tenemos  esta  declaración  del  API  de  Windows:  

indicamos  que  la  función  se  encuentra  en  la  librería  “kernel32.dll”  

En  C#  la  podríamos  declarar  de  esta  otra:      

System.Runtime.InteropServices.DllImport("kernel32.dll")] private extern static int GetLongPathName( string lpszShortPath, StringBuilder lpszLongPath, int cchBuffer );  

DWORD GetLongPathName( LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer );  

2   Invocación  de  plataforma  -­‐  PInvoke Por  ejemplo,  si  tenemos  esta  declaración  del  API  de  Windows:  

indicamos  que  la  función  se  encuentra  en  la  librería  “kernel32.dll”  

siempre  debemos  declarar  los  métodos  como  extern static

En  C#  la  podríamos  declarar  de  esta  otra:      

System.Runtime.InteropServices.DllImport("kernel32.dll")] private extern static int GetLongPathName( string lpszShortPath, StringBuilder lpszLongPath, int cchBuffer );  

DWORD GetLongPathName( LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer );  

2   Invocación  de  plataforma  -­‐  PInvoke Por  ejemplo,  si  tenemos  esta  declaración  del  API  de  Windows:  

indicamos  que  la  función  se  encuentra  en  la  librería  “kernel32.dll”  

siempre  debemos  declarar  los  métodos  como  extern static

Parámetros  adecuados  a  los  Lpos  que  .NET  uLliza.  Cuando  el  API  espera  una  cadena,  podemos  declararla  tanto  usando  el  Lpo  string  como  StringBuilder.    

Servicios  Windows  Aplicaciones  ejecutables    

de  larga  duración  

Servicios  Windows  Aplicaciones  ejecutables  de  larga  duración  

Se  ejecutan  en  sus  propias  sesiones  de  Windows.  

Pueden  iniciarse  automá6camente  cuando  el  equipo  arranca.  

Se  pueden  pausar  y  reiniciar.  

No  muestran  ningún  interfaz  de  usuario.  

Servicios  Windows  Aplicaciones  ejecutables  de  larga  duración  

Se  ejecutan  en  sus  propias  sesiones  de  Windows.  

Pueden  iniciarse  automá6camente  cuando  el  equipo  arranca.  

Se  pueden  pausar  y  reiniciar.  

No  muestran  ningún  interfaz  de  usuario.  

Servicios  Windows  Aplicaciones  ejecutables  de  larga  duración  

Se  ejecutan  en  sus  propias  sesiones  de  Windows.  

Pueden  iniciarse  automá6camente  cuando  el  equipo  arranca.  

Se  pueden  pausar  y  reiniciar.  

No  muestran  ningún  interfaz  de  usuario.  

Servicios  Windows  Aplicaciones  ejecutables  de  larga  duración  

Se  ejecutan  en  sus  propias  sesiones  de  Windows.  

Pueden  iniciarse  automá6camente  cuando  el  equipo  arranca.  

Se  pueden  pausar  y  reiniciar.  

No  muestran  ningún  interfaz  de  usuario.  

Servicios  Windows  Aplicaciones  ejecutables  de  larga  duración  

Se  ejecutan  en  sus  propias  sesiones  de  Windows.  

Pueden  iniciarse  automá6camente  cuando  el  equipo  arranca.  

Se  pueden  pausar  y  reiniciar.  

No  muestran  ningún  interfaz  de  usuario.  

Perfectos  para  ejecutarse  en  un  servidor  o  donde  se  necesite  una  funcionalidad  de  ejecución  larga  que  no  interfiera  con  los  demás  usuarios  que  trabajen  en  el  mismo  equipo.  

Cómo  crear  un  Servicio  Windows  Fase  1:  creación  del  servicio  

En  Visual  Studio,  seleccionar  la  opción  File  -­‐>  New  Project…  

En  la  lista  de  planLllas  C#  seleccionar  Windows  Service,  y  nombrar  el  proyecto  MyNewService.  Al  crear  un  servicio,  podemos  usar  una  planLlla  de  proyecto  de  Visual  Studio  denominada  Servicio  de  Windows.  Esta  planLlla  realiza  automáLcamente  gran  parte  del  trabajo:  hace  referencia  a  las  clases  y  los  espacios  de  nombres  correctos,  configura  la  herencia  de  la  clase  base  para  los  servicios  y  reemplaza  algunos  de  los  métodos  que  es  probable  que  deseemos  reemplazar.  

En  el  menú  Edit,  elegimos  Find  and  replace,  Find  in  files  (teclado:  Ctrl+Mayús+F).  Cambiamos  todas  las  apariciones  de  Service1  por  MyNewService.  Encontraremos  casos  en  Service1.cs,  Program.cs  y  Service1.Designer.cs.

12

3

En  la  ventana  Proper6es,  establecemos  las  propiedades  ServiceName  y  Name  en  MyNewService,  si  todavía  no  están  establecidas.  

4

En  el  explorador  de  soluciones  (Solu6on  Explorer),  cambiamos  el  nombre  de  Service1.cs a  MyNewService.cs.

5

Cómo  crear  un  Servicio  Windows  Fase  2:  agregar  caracterís6cas  al  servicio  

Establecemos  cualquiera  de  las  siguientes  propiedades  para  determinar  cómo  funcionará  el  servicio.  

Cómo  crear  un  Servicio  Windows  Fase  2:  agregar  caracterís6cas  al  servicio  

Para  agregar  caracterís6cas  al  servicio,  veamos  un  ejemplo  en  donde  vamos  a  agregar  un  registro  de  eventos  personalizado  al  servicio  Windows:  

public MyNewService() { InitializeComponent(); if (!System.Diagnostics.EventLog.SourceExists("MySource")) { System.Diagnostics.EventLog.CreateEventSource("MySource", "MyNewLog"); } eventLog1.Source = "MySource"; eventLog1.Log = "MyNewLog"; }

1 Añadimos  al  constructor de MyNewService.cs un  registro  de  eventos  personalizado:  

protected override void OnStart(string[] args) { eventLog1.WriteEntry("In OnStart"); }

2 En  el  método  OnStart  logueamos  en  el  registro  de  eventos  creado  en  el  paso  anterior  el  inicio  del  servicio:  

Una  aplicación  de  servicio  está  diseñada  para  ejecutarse  de  forma  prolongada.  Por  lo  tanto,  normalmente  sondea  o  supervisa  algún  elemento  del  sistema.  La  supervisión  se  puede  establecer  en  el  método  OnStart.  Sin  embargo,  OnStart  no  lleva  a  cabo  realmente  la  supervisión.  El  método  OnStart  debe  volver  al  sistema  operaLvo  después  de  que  haya  comenzado  el  funcionamiento  del  servicio.  No  debe  bloquearse  ni  ejecutar  un  bucle  infinito.  Para  establecer  un  mecanismo  de  sondeo  sencillo,  uLlice  el  componente  System.Timers.Timer.  En  el  método  OnStart,  debería  establecer  los  parámetros  en  el  componente  y,  a  conLnuación,  establecer  la  propiedad  Enabled  en  true.  El  temporizador  acLvaría  entonces  los  eventos  periódicamente  en  el  código  y,  en  esos  instantes,  el  servicio  podría  realizar  su  control.  

Añadimos  un  Timer  al  servicio  para  que  la  ejecución  del  mismo  no  termine  inmediatamente:  

public partial class MyNewService : ServiceBase { private System.Timers.Timer timer; public MyNewService() { ... this.timer = new System.Timers.Timer(); this.timer.Interval = 5000; this.timer.Elapsed += new ElapsedEventHandler(OnTimedEvent); this.timer.Enabled = true; this.timer.Start(); } }

private OnTimedEvent(object source, ElapsedEventArgs e) { eventLog1.WriteEntry("The Elapsed event was raised at {0}", e.SignalTime); }

protected override void OnStop() { this.timer.Enabled = false; }

protected override void OnStop() { ... eventLog1.WriteEntry("In OnStop"); }

3 En  el  método  OnStop  logueamos  en  el  registro  de  eventos  creado  el  parado  del  servicio:  

Cómo  crear  un  Servicio  Windows  Fase  3:  configurar  el  estado  del  servicio  

Los  servicios  informan  de  su  estado  al  Administrador  de  control  de  servicios,  para  que  los  usuarios  puedan  saber  si  un  servicio  funciona  correctamente.  De  manera  predeterminada,  los  servicios  que  heredan  de  ServiceBase  informan  de  un  conjunto   limitado  de  parámetros  de  estado,   incluidos  Detenido,  En  pausa  y  En  ejecución.   Si  un   servicio   tarda  un  poco  en  iniciarse,  puede  ser  úLl  informar  de  un  estado  Inicio  pendiente.    También   podemos   implementar   la   configuración   de   estado   Inicio   pendiente   y   Detención   pendiente   si   agregamos  código  que  llama  a  la  función  SetServiceStatus  de  Windows.  

Para  implementar  el  estado  pendiente  del  servicio,  veamos  un  ejemplo:  

Añadimos  la  instrucción  using  al  espacio  de  nombres  System.Runtime.InteropServices  en  el  archivo  MyNewService.cs.  

1

Con6núa  en  la  siguiente  página…  

Agregamos  el  código  siguiente  a  MyNewService.cs  para  declarar  los  valores  de  ServiceState  y  agregamos  una  estructura  (struct)  para  el  estado,  que  se  uLlizará  en  una  llamada  de  a  código  no  manejado  mediante  pInvoke:  

2 public enum ServiceState { SERVICE_STOPPED = 0x00000001, SERVICE_START_PENDING = 0x00000002, SERVICE_STOP_PENDING = 0x00000003, SERVICE_RUNNING = 0x00000004, SERVICE_CONTINUE_PENDING = 0x00000005, SERVICE_PAUSE_PENDING = 0x00000006, SERVICE_PAUSED = 0x00000007, } [StructLayout(LayoutKind.Sequential)] public struct ServiceStatus { public long dwServiceType; public ServiceState dwCurrentState; public long dwControlsAccepted; public long dwWin32ExitCode; public long dwServiceSpecificExitCode; public long dwCheckPoint; public long dwWaitHint; };

En  la  clase  MyNewService.cs,  declaramos  la  función  SetServiceStatus  mediante  pInvoke:  3 [DllImport(“advapi32.dll”, SetLastError=true)] private static extern bool SetServiceStatus(IntPtr handle, ref ServiceStatus serviceStatus);

Con6núa  en  la  siguiente  página…  

Para  implementar  el  estado  Inicio  pendiente,  agregamos  el  siguiente  código  al  principio  del  método  OnStart:  4 // Update the service state to Start Pending. ServiceStatus serviceStatus = new ServiceStatus(); serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING; serviceStatus.dwWaitHint = 100000; SetServiceStatus(this.ServiceHandle, ref serviceStatus);

Agregamos  el  siguiente  código  para  establecer  el  estado  En  ejecución  al  final  del  método  OnStart:  5// Update the service state to Running. serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; SetServiceStatus(this.ServiceHandle, ref serviceStatus);;

Cómo  crear  un  Servicio  Windows  Fase  4:  agregar  instaladores  al  servicio  

En  Visual  Studio,  en  el  explorador  de  soluciones  (Solu6on  Explorer),  abrir  el  menú  contextual  de  MyNewService.cs  y  seleccionar  Vista  de  Diseño  (Design  view).  

Hacemos   click   en   el   fondo   del   diseñador   para   seleccionar   el   propio   servicio,   en   vez   de   cualquier   elemento   de   su  contenido.  

Abrir  el  menú  contextual  de  la  ventana  del  diseñador  y  a  conLnuación  elegimos  Agregar  instalador  (Add  installer).  

123

Para   poder   ejecutar   un   servicio  Windows,   antes   debemos   instalarlo,   el   cuál   será   registrado   por   el   Administrador   de  control  de  servicios.  Podemos  agregar  instaladores  al  proyecto  que  controlen  los  detalles  del  registro.  

De  forma  predeterminada,  se  agrega  al  proyecto  una  clase  de  componente  que  conLene  dos   instaladores.  El  componente  se  denomina  ProjectInstaller,  y  los  instaladores  que  conLene  son  el  instalador  para  el  servicio  y  el  instalador  para  el  proceso  asociado  al  servicio.  

En  la  vista  Diseño  de  ProjectInstaller,  elegimos  serviceInstaller1.  4En  la  ventana  Propiedades  nos  aseguramos  de  que  la  propiedad  ServiceName  esté  establecida  en  MyNewService.  5

Con6núa  en  la  siguiente  página…  

Establecemos   texto   en   la   propiedad  Descripción,   como   "Servicio   de   ejemplo".   Este   texto   aparece   en   la   ventana  Servicios  y  ayuda  al  usuario  a  idenLficar  el  servicio  y  comprender  para  qué  se  usa.  

Establecemos   la   propiedad   DisplayName   en   el   texto   que   deseemos   que   aparezca   en   la   ventana   Servicios   en   la  columna  Nombre.  Por  ejemplo,  podemos  escribir  "Nombre  para  mostrar  de  MyNewService”.  

Establecemos  la  propiedad  StartType  en  Automa6c.  

6

7

8

Este  nombre  puede  ser  diferente  de  la  propiedad  ServiceName,  que  es  el  nombre  usado  por  el  sistema  (por  ejemplo,  al  usar  el  comando  net start  para  iniciar  el  servicio).  

En  el  diseñador,  elegimos  serviceProcessInstaller1  y  establecemos  la  propiedad  Account  en  LocalSystem.  9Esto  hará  que  se  instale  el  servicio  y  se  ejecute  con  una  cuenta  de  servicio  local.  

La  cuenta  LocalSystem  Lene  amplios  permisos,  incluida  la  capacidad  para  escribir  en  el  registro  de  eventos.  ULlice  esta  cuenta  con  precaución  porque  podría  aumentar  el  riesgo  de  ataques  por  parte  de  soRware  malintencionado.  Para  otras  tareas,  considere  la  posibilidad  de  usar  la  cuenta  LocalService,  que  actúa  como  un  usuario  sin  privilegios  en  el  equipo  local  y  presenta  credenciales  anónimas  a  cualquier  servidor  remoto.  En  este  ejemplo  se  produce  un  error  si  intenta  usar  la  cuenta  LocalService,  ya  que  necesita  permiso  de  escritura  en  el  registro  de  eventos.  

Cómo  crear  un  Servicio  Windows  Fase  5:  establecer  parámetros  de  inicio  Un  servicio  de  Windows,  al  igual  que  cualquier  otro  archivo  ejecutable,  puede  aceptar  argumentos  de  línea  de  comandos  o  parámetros  de  inicio.  

En  el  método  Main  de  Program.cs  agregamos  un  argumento  para  la  línea  de  comandos:  1static void Main(string[] args) {

ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new MyNewService(args) }; ServiceBase.Run(ServicesToRun);

}

Con6núa  en  la  siguiente  página…  

Modificamos  el  constructor  MyNewService  de  la  siguiente  forma:  2

public MyNewService(string[] args) { InitializeComponent(); string eventSourceName = "MySource"; string logName = "MyNewLog"; if (args.Count() > 0) { eventSourceName = args[0]; } if (args.Count() > 1) { logName = args[1]; } eventLog1 = new System.Diagnostics.EventLog(); if (!System.Diagnostics.EventLog.SourceExists(eventSourceName)) { System.Diagnostics.EventLog.CreateEventSource(eventSourceName, logName); } eventLog1.Source = eventSourceName; eventLog1.Log = logName; }

Este  código  establece  el  nombre  de  registro  y  el  origen  de  eventos  según  los  parámetros  de  inicio  proporcionados,  o  bien,  usa  los  valores  predeterminados  si  no  se  proporcionan  argumentos.  

Para  especificar  los  argumentos  de  línea  de  comandos,  agregamos  el  código  siguiente  a  la  clase  ProjectInstaller  en  ProjectInstaller.cs:  

3protected override void OnBeforeInstall(IDictionary savedState) { string parameter = "MySource1\" \"MyLogFile1”; Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\""; base.OnBeforeInstall(savedState); }

Cómo  crear  un  Servicio  Windows  Fase  6:  compilar  el  servicio  

En   el   explorador   de   soluciones   (Solu6on   Explorer),   abrimos   el   menú   contextual   del   proyecto   y,   a  conLnuación,  elegimos  Proper6es.  

1

En  la  pestaña  Applica6on,  en  la  lista  objeto  de  inicio,  elegimos  MyNewService.Program.  2

En   el   explorador   de   soluciones   (Solu6on   Explorer),   abrimos   el   menú   contextual   del   proyecto   y,   a  conLnuación,  elegimos  Build  para  compilar  el  proyecto  (teclado:  Ctrl+Mayús+B).  

3

Cómo  crear  un  Servicio  Windows  Fase  7:  instalar  el  servicio  

En  Windows  7  y  Windows  Server,  abrimos  la   línea  de  comandos  para  desarrolladores  en  Visual  Studio  Tools  en  el  menú  Inicio.  En  Windows  8  o  Windows  8.1,  elegimos  el  icono  de  Visual  Studio  Tools  en  la  pantalla  Inicio  y  ejecutamos  la  línea  de  comandos  para  desarrolladores  con  credenciales  administraLvas.  

1

Ahora  que  ha  compilado  el  servicio  Windows,  podemos  instalarlo.  Para  instalar  un  servicio  de  Windows,  debemos  tener  credenciales  administraLvas  en  el  equipo  en  el  que  lo  vamos  a  instalar.  

En   la   ventana   de   símbolo   del   sistema,  nos   desplazamos   hasta   la   carpeta   que   con6ene   la   salida   del   proyecto.   Por  ejemplo,  en  la  carpeta  Mis  documentos,  nos  desplazamos  hasta  Visual  Studio  2013\Projects\MyNewService\bin\Debug.  

2

Escribimos  el  siguiente  comando:  3installutil.exe MyNewService.exe

Cómo  crear  un  Servicio  Windows  Fase  8:  iniciar  y  ejecutar  el  servicio  

En  Windows,  abrimos  la  pantalla  Inicio  o  el  menú  Inicio  y  escribimos  services.msc.  1En   la   ventana   Servicios,   abrimos   el   menú   contextual   del   servicio   y,   a   conLnuación,   seleccionamos  Iniciar.  

2Abrimos  el  menú  contextual  del  servicio  y,  a  conLnuación,  elegimos  Detener.  3

Para  comprobar  si  el  servicio  se  ha  ejecutado  correctamente,  podemos  ir  al  visor  de  eventos  de  Windows  y  ver  si  se  ha  generado  el  fichero  de  log  MyLogFile1.  En  él  deberíamos  ver  las  2  acciones  (iniciar  y  detener)  que  ha  realizado  el  servicio.  

Aplicaciones  cliente  Generación  de  aplicaciones  cliente  

para  el  consumo  de  servicios  remotos  

Aplicaciones  cliente  Qué  son?  

Las  aplicaciones  cliente,  como  un  navegador  web  o  una  aplicación  de  escritorio,    se  ejecutan  en  el  ordenador  o  estación  de  trabajo  local  de  un  usuario  y  se  conectan  a  un  servidor  cuando  lo  requieren.  

Cómo  crear  un  Servicio  Web  Implementación  de  un  servicio  WCF  

En  Visual  Studio,  seleccionar  la  opción  File  -­‐>  New  Project…  

En  la  lista  de  planLllas  C#  seleccionar  Class  Library,  y  nombrar  el  proyecto  WCFService.  

Crear  2  clases:  IMathService.cs  y  MathService.cs  

123

Decorar  el  interfaz  IMathService  con  el  atributo  [ServiceContract] 4El   atributo   ServiceContract   indica   que   un   interfaz   o   una   clase   define   un   contrato   de   servicio   en   una   aplicación   Windows  CommunicaLon  FoundaLon  (WCF).  

[ServiceContract] public interface IMathService { }

Cómo  crear  un  Servicio  Web  Implementación  de  un  servicio  WCF  

public int Sum(int a, int b);

Declarar  los  métodos  a  publicar  en  el  servicio  WCF  en  el  interfaz  IMathService. 5En  nuestro  ejemplo,  definiremos  solamente  un  método  que  realizará  la  operación  de  suma.  

[OperationContract] public int Sum(int a, int b);

Decorar  los  métodos  declarados  en  el  interfaz  IMathService  con  el  atributo  [OperationContract]. 6Debemos   decorar   con   el   atributo   OperationContract   aquellos   métodos   que   deseemos   sean   públicos   en   el   servicio  WCF.   Puede  interesar   que   todos   los   métodos   de   un   interfaz   no   sean   publicados   en   el   servicio   y   por   tanto   no   necesitaríamos   decorarlos   con  OperationContract.  

Implementar  en  la  clase  MathService.cs  el  método  Sum  definido  en  el  interfaz  IMathService.  7Hospedar  y  ejecutar  un  servicio  WCF 8En  nuestro  ejemplo,  vamos  a  hospedar  el  servicio  WCF  en  una  aplicación  de  Consola.  Veamos  la  siguiente  documentación:  

hsps://msdn.microsoR.com/es-­‐es/library/ms730935(v=vs.110).aspx  

class Program { static void Main(string[] args) { // Step 1 Create a URI to serve as the base address. Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/"); // Step 2 Create a ServiceHost instance ServiceHost selfHost = new ServiceHost(typeof(MathService), baseAddress); try { // Step 3 Add a service endpoint. selfHost.AddServiceEndpoint(typeof(IMathService), new WSHttpBinding(), "MathService"); // Step 4 Enable metadata exchange. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb); // Step 5 Start the service. selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close(); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); } } }

class Program { static void Main(string[] args) { // Step 1 Create a URI to serve as the base address. Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/"); // Step 2 Create a ServiceHost instance ServiceHost selfHost = new ServiceHost(typeof(MathService), baseAddress); try { // Step 3 Add a service endpoint. selfHost.AddServiceEndpoint(typeof(IMathService), new WSHttpBinding(), "MathService"); // Step 4 Enable metadata exchange. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb); // Step 5 Start the service. selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close(); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); } } }

Los  servicios  se  idenLfican  mediante  una  dirección  URL  que  conLene  una  dirección  base  y  una  URI  opcional.  La  dirección  base  para  nuestro  servicio  usa  el  transporte  HTTP,  localhost,  el  puerto  8000  y  el  segmento  de  URI  “Ge�ngStarted”.  

class Program { static void Main(string[] args) { // Step 1 Create a URI to serve as the base address. Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/"); // Step 2 Create a ServiceHost instance ServiceHost selfHost = new ServiceHost(typeof(MathService), baseAddress); try { // Step 3 Add a service endpoint. selfHost.AddServiceEndpoint(typeof(IMathService), new WSHttpBinding(), "MathService"); // Step 4 Enable metadata exchange. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb); // Step 5 Start the service. selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close(); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); } } }

Los  servicios  se  idenLfican  mediante  una  dirección  URL  que  conLene  una  dirección  base  y  una  URI  opcional.  La  dirección  base  para  nuestro  servicio  usa  el  transporte  HTTP,  localhost,  el  puerto  8000  y  el  segmento  de  URI  “Ge�ngStarted”.  

Crear  una  instancia  de  la  clase  ServiceHost  para  hospedar  el  servicio.  

class Program { static void Main(string[] args) { // Step 1 Create a URI to serve as the base address. Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/"); // Step 2 Create a ServiceHost instance ServiceHost selfHost = new ServiceHost(typeof(MathService), baseAddress); try { // Step 3 Add a service endpoint. selfHost.AddServiceEndpoint(typeof(IMathService), new WSHttpBinding(), "MathService"); // Step 4 Enable metadata exchange. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb); // Step 5 Start the service. selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close(); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); } } }

Los  servicios  se  idenLfican  mediante  una  dirección  URL  que  conLene  una  dirección  base  y  una  URI  opcional.  La  dirección  base  para  nuestro  servicio  usa  el  transporte  HTTP,  localhost,  el  puerto  8000  y  el  segmento  de  URI  “Ge�ngStarted”.  

Crear  una  instancia  de  la  clase  ServiceHost  para  hospedar  el  servicio.  

Crear  una  nueva  instancia  de  ServiceEndpoint.Un  extremo  de  servicio  consta  de  una  dirección,  un  enlace  y  un  contrato  de  servicio.  Por  tanto,  el  constructor  ServiceEndpoint  toma  el  Lpo  de  interfaz  del  contrato  de  servicio,  un  enlace  y  una  dirección.    El  contrato  de  servicio  es  IMathService.    El  enlace  uLlizado  en  este  ejemplo  es  WSHspBinding,  que  es  un  enlace  integrado  que  se  emplea  para  conectarse  a  extremos  que  son  conformes  a  las  especificaciones  de  WS-­‐*.    La  dirección  se  anexa  a  la  dirección  base  para  idenLficar  el  extremo.La  dirección  especificada  en  este  código  es  “Calculator”,  por  lo  que  la  dirección  completa  del  extremo  es  “hsp://localhost:8000/Ge�ngStartedService/Calculator”  

class Program { static void Main(string[] args) { // Step 1 Create a URI to serve as the base address. Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/"); // Step 2 Create a ServiceHost instance ServiceHost selfHost = new ServiceHost(typeof(MathService), baseAddress); try { // Step 3 Add a service endpoint. selfHost.AddServiceEndpoint(typeof(IMathService), new WSHttpBinding(), "MathService"); // Step 4 Enable metadata exchange. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb); // Step 5 Start the service. selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close(); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); } } }

Los  servicios  se  idenLfican  mediante  una  dirección  URL  que  conLene  una  dirección  base  y  una  URI  opcional.  La  dirección  base  para  nuestro  servicio  usa  el  transporte  HTTP,  localhost,  el  puerto  8000  y  el  segmento  de  URI  “Ge�ngStarted”.  

Crear  una  instancia  de  la  clase  ServiceHost  para  hospedar  el  servicio.  

Crear  una  nueva  instancia  de  ServiceEndpoint.Un  extremo  de  servicio  consta  de  una  dirección,  un  enlace  y  un  contrato  de  servicio.  Por  tanto,  el  constructor  ServiceEndpoint  toma  el  Lpo  de  interfaz  del  contrato  de  servicio,  un  enlace  y  una  dirección.    El  contrato  de  servicio  es  IMathService.    El  enlace  uLlizado  en  este  ejemplo  es  WSHspBinding,  que  es  un  enlace  integrado  que  se  emplea  para  conectarse  a  extremos  que  son  conformes  a  las  especificaciones  de  WS-­‐*.    La  dirección  se  anexa  a  la  dirección  base  para  idenLficar  el  extremo.La  dirección  especificada  en  este  código  es  “Calculator”,  por  lo  que  la  dirección  completa  del  extremo  es  “hsp://localhost:8000/Ge�ngStartedService/Calculator”  

Habilitar  el  intercambio  de  metadatos  para  poder  generar  los  proxies  en  las  aplicaciones  cliente.  

class Program { static void Main(string[] args) { // Step 1 Create a URI to serve as the base address. Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/"); // Step 2 Create a ServiceHost instance ServiceHost selfHost = new ServiceHost(typeof(MathService), baseAddress); try { // Step 3 Add a service endpoint. selfHost.AddServiceEndpoint(typeof(IMathService), new WSHttpBinding(), "MathService"); // Step 4 Enable metadata exchange. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb); // Step 5 Start the service. selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close(); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); } } }

Los  servicios  se  idenLfican  mediante  una  dirección  URL  que  conLene  una  dirección  base  y  una  URI  opcional.  La  dirección  base  para  nuestro  servicio  usa  el  transporte  HTTP,  localhost,  el  puerto  8000  y  el  segmento  de  URI  “Ge�ngStarted”.  

Crear  una  instancia  de  la  clase  ServiceHost  para  hospedar  el  servicio.  

Crear  una  nueva  instancia  de  ServiceEndpoint.Un  extremo  de  servicio  consta  de  una  dirección,  un  enlace  y  un  contrato  de  servicio.  Por  tanto,  el  constructor  ServiceEndpoint  toma  el  Lpo  de  interfaz  del  contrato  de  servicio,  un  enlace  y  una  dirección.    El  contrato  de  servicio  es  IMathService.    El  enlace  uLlizado  en  este  ejemplo  es  WSHspBinding,  que  es  un  enlace  integrado  que  se  emplea  para  conectarse  a  extremos  que  son  conformes  a  las  especificaciones  de  WS-­‐*.    La  dirección  se  anexa  a  la  dirección  base  para  idenLficar  el  extremo.La  dirección  especificada  en  este  código  es  “Calculator”,  por  lo  que  la  dirección  completa  del  extremo  es  “hsp://localhost:8000/Ge�ngStartedService/Calculator”  

Habilitar  el  intercambio  de  metadatos  para  poder  generar  los  proxies  en  las  aplicaciones  cliente.  

Abrir  ServiceHost  para  escuchar  los  mensajes  entrantes  

Cómo  consumir  un  Servicio  Web  Implementación  de  una  aplicación  cliente  Windows  Forms  

En  Visual  Studio,  seleccionar  la  opción  File  -­‐>  New  Project…  

En  la  lista  de  planLllas  C#  seleccionar  Applica6on  Windows  Forms,  y  nombrar  el  proyecto  por  WCFServiceConsumer.UI.WinForms.  

Añadir  un  1  botón  y  2  controles  de  Lpo  numeric  up  down.

123

Añadir  una  referencia  al  servicio  web  publicado  anteriormente. 4En   el   menú   contextual   del   proyecto  WebServiceConsumer.UI.WinForms   seleccionar  Add   Service   Reference…   y   escribir   la   url  http://localhost:8000/GettingStarted/.  

Invocar  al  servicio  web  haciendo  uso  del  proxy  creado  por  Visual  Studio  en  el  paso  anterior. 5Al  pulsar  el  botón  debemos  invocar  al  método  Sum  del  servicio  web.  

Otros  puntos  de  interés  Herramientas  de  profiling,  gesLón  de  librerías  mediante  Nuget,  librerías  para  

logging,  etc.  

MicrosoR  dispone  de  un  conjunto  de  librerías  que  facilitan  el  desarrollo  de  aplicaciones  empresariales  en  .NET.  Implementan  funcionalidad  que  �picamente  debe  incorporarse  a  las  aplicaciones  empresariales.  

Librerías  que  facilitan  el  desarrollo  del  día  a  día  

Microso|  Enterprise  Library  Está  desarrollada  por  el  equipo  Paserns  &  PracLces  de  MicrosoR.  Este  equipo  Lene  como  misión  entregar  orientación  sobre  las  mejores  pracLcas  para  el  desarrollo  de  aplicaciones  empresariales  en  .NET.  

Nos  permiten  instalar  y  actualizar  librerías  y  herramientas  en  Visual  Studio  de  forma  sencilla.  Gestores  de  paquetes  

Nuget  Es  una  extensión  de  Visual  Studio  que  permite  la  administración,  de  una  forma  muy  sencilla,  de  las  referencias  a  otras  librerías.  Del  mismo  modo  que  se  pueden  agregar  o  quitar  referencias,  Nuget  es  capaz  de  detectar  si  existen  nuevas  versiones  en  el  repositorio  y  descargar  la  nueva  versión  previa  aceptación  del  usuario.  

El  objeLvo  es  averiguar  el  Lempo  dedicado  a  la  ejecución  de  diferentes  partes  del  programa  para  detectar  los  puntos  problemáLcos  y  las  áreas  dónde  sea  posible  llevar  a  cabo  una  opLmización  del  rendimiento  (ya  sea  en  velocidad  o  en  consumo  de  recursos).  

Análisis  de  rendimiento  de  so|ware  

ANTS  Performance  Profiler  Profile  and  boost  the  performance  of  your  .NET  applicaLons  

ANTS  Memory  Profiler  Profile  .NET  applicaLon  memory  usage  

Permiten  que  nuestra  aplicación  muestre  mensajes  de  información  de  lo  que  está  sucediendo  en  ella,  lo  que  habitualmente  se  conoce  como  un  log.  Tienen  la  ventaja  de  ser  dinámicas  y,  por  tanto,  configurables.  

Librerías  para  logging  

Apache  log4net  Tool  to  help  the  programmer  output  log  statements  to  a  variety  of  output  targets  

Referencias  u6lizadas  en  este  curso  

Head  First  C#,  3rd  edi6on  by  Jennifer  Greene,  Andrew  

Stellman  

Design  Pa}erns  by  Erich  Gamma,  Richard  Helm,  Ralph  Johson,  John  Vlissides  

Framework  Design  Guidelines  by  Krzysztof  Cwalina,  Brad  Abrams  

ESKERRIK  ASKO  gorkavicente.com  

@gorkavicente  

hsps://es.linkedin.com/in/gorkavicente