|
Novedades en C# 2005 |
|
|
Autor: Unai Zorrilla Actualizado: 20/Ago/2004 |
Novedades en C# 2005
Modificadores de Acceso de Acceso a Propiedades
La sintaxis para el acceso a propiedades e indexadores en c# 2005 ha cambiado para permitir modificadores de acceso. El uso de modificadores de acceso esta restringido por :
Modificadores de Acceso:
- El uso de modificadores de acceso no se puede usar en una interface o en la implementación explícita de miembros de la inteface
- Los modificadores de acceso solamente se permite en propiedades o indexadores con los accesos get y set, y se permite únicamente en uno de estos accesos.
Lo mejor es verlo con un ejemplo :
- protected
- internal
- private
- protected internal
- internal protected
#region Using directives using System; using System.Collections.Generic; using System.Text; #endregion namespace Ejemlo1 { class A { public string Text { get { return "Hola Mundo!"; } set { } } public int Count { get { return 5; } set { } } public A() { } [STAThread] static void Main(string[] args) { B b = new B(); b.Count = 12; // Llama a A.Count Set int j = b.Count; //Llama a A.Count Get, el valor de j es 5 y no 12 // b.Text = "ElGuille.info"; // Error no accesible string s = b.Text; // Llama a B.Text Get elvalor de s es Adiós Console.WriteLine(s); Console.ReadLine(); } } class B : A { public B() { } private string _text = "Adiós"; private int _count = 0; new public string Text { get { return _text; } protected set { _text = value; } } new protected int Count { get { return _count; } set { _count = value; } } } }
Cuando tipos o NameSpace son añadidos a un ensamblado, los nombres de los tipos o namespace pueden estar en conflicto con nombres ya existentes en uso. Por ejemplo consideremos, los siguientes ensamblados:
Assembly A1.dll namespace System.IO { public class Stream {...} public class FileStream: Stream { ... } ... } Assembly A2.dll namespace EnsambladoGuille { public class GuilleStream : Stream {...} } y el siguiente trozo de código: using System.IO; using EnsambladoGuille; class Program { static void Main() { Stream s = new GuilleStream(); ... } }Si en un futuro los desarrolladores de Microsft incluyeran GuilleStream a System.IOf ( cosa bastante probable :-) ) no encontraríamos con un problema de referencias ambiguas y el compilador no daría error. Este pequeño gran problema en c# 2005 se puede resolver fácilmente usando cualificadores para espacios de nombre de la siguiente forma
using SIO = System.IO; using GUIO = EnsambladoGuille; class Program { static void Main() { SIO::Stream s = new GUIO::GuilleStream(); ... } }Seguramente alguno está pensando, va esto ya se podía resolver antes escribiendo SIO.Stream... , ciertamente es verdad pero el cualificador de ámbito :: permite garantizar que las operaciones de búsqueda del tipo no se vean afectadas por la introducción de nuevos miembros o tipos.
Un aspecto a destacar es que si en el lado izquierdo del operador :: se coloca global entonces la búsqueda de tipo comienza por el del lado derecho.
Junto con Generics, el tema de métodos anónimos es a mi parecer el tema más fuerte en cuanto a las novedades que trae c# 2.0. Como hasta ahora para ver todas estas nuevas cosas no hay mejor cosa que poner ejemplillos..... Todos los que hemos trabajado con la anterior versión de c# sabemos que a la hora de implementar un manejador para un evento, tenemos que hacerlo con un método pasado explícitamente cuando se crea el delegado. Por el contrario en c# se pueden escribir métodos 'inline' para usarlos con delegados.
En el siguiente ejemplo veremos como implementábamos un método para el evento Click de un botón:
#region Using directives using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Windows.Forms; #endregion namespace ElGuilleMetodosAnonimos { partial class Form1 : Form { public Form1() { InitializeComponent(); this.button1.Click += new EventHandler(ElClick); } private void ElClick(object sender, EventArgs e) { MessageBox.Show("Has hecho click"); } } }Veremos como ahora en c#, la implementación de los manejadores se pude hacer en linea ( ' inline' ) y pasaremos a explicar un poco más todo el tema:
#region Using directives using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Windows.Forms; #endregion namespace ElGuilleMetodosAnonimos { partial class Form1 : Form { public Form1() { InitializeComponent(); this.button1.Click += delegate { MessageBox.Show("Has hecho click eh?"); }; } } }Un método anonimo consiste en la palabra clave delegate, y opcionalmente en una lista de parametros junto con un statmet entre '{' y '}' . El método anónimo en el anterior ejemplo no lleva parámetros ya que son proporcionados por el delegado. Este hecho nos imposibilita hacer uso de los parámetros pasados object y e, aunque podemos hacer una pequeña modificación en el código para tener acceso.
#region Using directives using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Windows.Forms; #endregion namespace ElGuilleMetodosAnonimos { partial class Form1 : Form { public Form1() { InitializeComponent(); this.button1.Click += delegate(object sender,EventArgs e) { MessageBox.Show("Has hecho click eh?" + sender.ToString() ); }; } } }La lista de parámetros de un delegado es compatible con un método anónimo si una de las siguientes opciones es cierta:
El retorno de un delegado es compatible con un método anónimo su una de las siguientes opciones en cierta
- El método anónimo no tiene parámetros y el delegado no tiene parámetros out
- El método anónimo contiene exanctamente la misma lista de parámetros que el método
- El retorno del delegado es void y el método anónimo no devuelve valor
- El retorno del delegado es distinto de void entonces el statment del método anónimo tiene que devolver el mismo tipo de valor
Como hemos visto hasta ahora el método anónimo se convierte en un delegado compatible de forma implícita. Entonces ¿ Podríamos omitir delegate cuando instanciamos un delegado de forma explícita, es decir ¿ Funcionará lo siguiente ?
#region Using directives using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Windows.Forms; #endregion namespace ElGuilleMetodosAnonimos { partial class Form1 : Form { public Form1() { InitializeComponent(); this.button1.Click += Click; } private void Click(object sender, EventArgs e) { MessageBox.Show("Ey"); } } }La Respuesta es SÍ
Tipado Parcial (Partial Types)
El nuevo modificador partial se usa cuando queremos definir un tipo en múltiples partes. partial no es una palabra clave y debe de aparecer antes de las palabras clave class,struct o interface.
En Atributos:
Los atributos de tipo parcial son determinados por combinación, sin un orden específico. Si un atributo es puesto en múltiples partes, es equivalente a especificar los tiempos múltiples, por ejemplo.
[Attributo1,Attributo2("Hola")]
partial class A {}[Attributo3,Attributo4("Adios")]
partial class A {}es equivalente a la declaración
[Attributo1,Attributo2("Hola"),Attributo3,Attributo4("Adios")]
partial class A {}Parial en Generics:
También se pueden declarar genéricos parciales, un ejemplo de ello es :
partial class Dictionary<K,V>
where K : IComparable<k>
where V:IKeyProvider<k>,Ipersistablepartial class Dictionary<K,V>
where K :IKeyProvider<k>,Ipersistable
where V:IComparable<k>En Declaraciones de Clase :
También es posible utilizar partial en las declaraciones de clase, podemos ver un ejemplo sencillo de esto:
partial Class TEST :IA,IB { ... }
partial Class TEST: IC,ID { ... }