340 likes | 431 Views
C# e Programa ção Genérica. Joel Pereira (joelcdp@microsoft.com) Software Design Engineer WinFS API Team Microsoft Corporation. Conteúdo. Baseado na versão Visual Studio 2005, Community Release – Maio de 2004 Material disponibilizado pelo time C# Anders Hejlsberg Eric Gunnerson.
E N D
C# e Programação Genérica Joel Pereira (joelcdp@microsoft.com) Software Design Engineer WinFS API Team Microsoft Corporation
Conteúdo • Baseado na versão Visual Studio 2005, Community Release – Maio de 2004 • Material disponibilizado pelo time C# • Anders Hejlsberg • Eric Gunnerson
Novidades da Linguagem C# • Programação Genérica • Tipos Nullable • Métodos Anonimos • Iterators • Tipos Parciais • Classe Estática • Entre outras…
Programação Genérica public class List { private object[] elements; private int count; public void Add(object element) { if (count == elements.Length) Resize(count * 2); elements[count++] = element; } public object this[int index] { get { return elements[index]; } set { elements[index] = value; } } public int Count { get { return count; } } } public class List<T> { private T[] elements; private int count; public void Add(T element) { if (count == elements.Length) Resize(count * 2); elements[count++] = element; } public T this[int index] { get { return elements[index]; } set { elements[index] = value; } } public int Count { get { return count; } } } List intList = new List(); intList.Add(1); intList.Add(2); intList.Add("Three"); int i = (int)intList[0]; List intList = new List(); intList.Add(1); // Argument is boxed intList.Add(2); // Argument is boxed intList.Add("Three"); // Should be an error int i = (int)intList[0]; // Cast required List<int> intList = new List<int>(); intList.Add(1); // No boxing intList.Add(2); // No boxing intList.Add("Three"); // Compile-time error int i = intList[0]; // No cast required
Programação Genérica • Porque? • Verificação de tipos em tempo de compilação • Desempenho • Redução de código • Como é implementado? • Instanciado em tempo de execução, não compilação • Verificação na declaração, não na instanciação • Funciona para tipos referências e valores • Informação em tempo de execução
Programação Genérica • Parametros tipo podem ser especificados para • Class, struct, interface, e delegate class Dictionary<K,V> {…} struct HashBucket<K,V> {…} interface IComparer<T> {…} delegate R Function<A,R>(A arg); Dictionary<string,Customer> customerLookupTable; Dictionary<string,List<Order>> orderLookupTable; Dictionary<string,int> wordCount;
Programação Genérica • Parametros tipo podem ser especificados para • Class, struct, interface, e delegate • Métodos class Utils{ public static T[] CreateArray<T>(int size) { return new T[size]; } public static void SortArray<T>(T[] array) { … } } string[] names = Utils.CreateArray<string>(10); names[0] = "Jones"; … Utils.SortArray(names);
Programação Genérica • Parametros tipo podem ser especificados para • Class, struct, interface, e delegate • Métodos • Parametros tipo podem ter constraints class Dictionary<K,V> { public void Add(K key, V value) { … if (((IComparable)key).CompareTo(x) == 0) {…} … } } class Dictionary<K,V> where K: IComparable { public void Add(K key, V value) { … if (key.CompareTo(x) == 0) {…} … } } class Dictionary<K,V>: IDictionary<K,V> where K: IComparable<K> where V: IKeyProvider<K>, IPersistable, new() { public void Add(K key, V value) { … } }
Programação Genérica • Constraint Primaria • "class", or "struct" • Constraint Secondaria • Interface ou parametro tipo • Constraint de instanciação • "new()" class Link<T> where T: class {…} class Nullable<T> where T: struct {…} class Relation<T,U> where T: class where U: T {…}
Programação Genérica List<T> Dictionary<K,V> SortedDictionary<K,V> Stack<T> Queue<T> • Collection classes • Collection interfaces • Collection base classes • Utility classes • Reflection IList<T> IDictionary<K,V> ICollection<T> IEnumerable<T> IEnumerator<T> IComparable<T> IComparer<T> Collection<T> KeyedCollection<T> ReadOnlyCollection<T> Nullable<T> EventHandler<T> Comparer<T>
Demo • Programação Genérica
Tipo Nullable • System.Nullable<T> • Possibilita que um tipo valor seja null • É uma struct que associa um T e um bool public struct Nullable<T> where T: struct { public Nullable(T value) {…} public T Value { get {…} } public bool HasValue { get {…} } … } Nullable<int> x = new Nullable<int>(123); … if (x.HasValue) Console.WriteLine(x.Value);
Tipo Nullable int? x = 123; double? y = 1.0; • Síntaxe T? • Literal null • Lifted conversions • Lifted operators • Operador ?? int? x = null; double? y = null; int i = 123; int? x = i;double? y = x; int? z = (int?)y; int j = (int)z; int? x = GetNullableInt(); int? y = GetNullableInt(); int? z = x + y; int? x = GetNullableInt(); int? y = GetNullableInt(); int z = (x + y) / (x – y) ?? 0;
Métodos Anonimos class MyForm : Form { ListBox listBox; TextBox textBox; Button addButton; public MyForm() { listBox = new ListBox(...); textBox = new TextBox(...); addButton = new Button(...); addButton.Click += new EventHandler(AddClick); } void AddClick(object sender, EventArgs e) { listBox.Items.Add(textBox.Text); } } class MyForm : Form { ListBox listBox; TextBox textBox; Button addButton; public MyForm() { listBox = new ListBox(...); textBox = new TextBox(...); addButton = new Button(...); addButton.Click += delegate { listBox.Items.Add(textBox.Text); }; } }
Métodos Anonimos • Permite bloco de código ao inves do delegate • Infêrencia automatica do tipo de delegate • Bloco de código sem uso de parametros • Ou com parametros • Em ambos os casos, tipo de retorno deve ser igual button.Click += delegate { MessageBox.Show("Hello"); }; button.Click += delegate(object sender, EventArgs e) { MessageBox.Show(((Button)sender).Text);};
Métodos Anonimos • Bloco de código pode acessar variáveis locais public class Bank { List<Account> GetLargeAccounts(double minBalance) { Helper helper = new Helper(); helper.minBalance = minBalance; return accounts.FindAll(helper.Matches); } internal class Helper { internal double minBalance; internal bool Matches(Account a) { return a.Balance >= minBalance; } }} public class Bank { List<Account> accounts; List<Account> GetOverdrawnAccounts() { return accounts.FindAll(delegate(Account a) { return a.Balance < 0; }); } List<Account> GetLargeAccounts(double minBalance) { return accounts.FindAll(delegate(Account a) { return a.Balance >= minBalance; }); } } delegate bool Predicate<T>(T item); public class List<T> { public List<T> FindAll(Predicate<T> filter) { List<T> result = new List<T>(); foreach (T item in this) { if (filter(item)) result.Add(item); } return result; } }
Métodos Anonimos • Converção de métodos • Tipo inferido quando possivel using System; using System.Threading; class Program { static void Work() {…} static void Main() { Thread t = new Thread(new ThreadStart(Work)); t.Start(); } } using System; using System.Threading; class Program { static void Work() {…} static void Main() { Thread t = new Thread(Work); t.Start(); } }
Iterators • foreach depende “enumerator pattern” • Método GetEnumerator() • foreach faz uma enumeração ficar fácil • Mas enumeradores são dificeis de escrever! foreach (object obj in list) { DoSomething(obj); } Enumerator e = list.GetEnumerator(); while (e.MoveNext()) { object obj = e.Current; DoSomething(obj); }
Iterators public class ListEnumerator : IEnumerator { List list; int index; internal ListEnumerator(List list) { this.list = list; index = -1; } public bool MoveNext() { int i = index + 1; if (i >= list.count) return false; index = i; return true; } public object Current { get { return list.elements[index]; } } } public class List { internal object[] elements; internal int count; public ListEnumerator GetEnumerator() { return new ListEnumerator(this); } }
Iterators • Método que computa e retorna uma sequência de valores incrementalmente • yield return e yield break • Deve retornar um IEnumerator ou IEnumerable public IEnumerator GetEnumerator() { return new __Enumerator(this); } private class __Enumerator: IEnumerator{ object current; int state; public bool MoveNext() { switch (state) { case 0: … case 1: … case 2: … … } } public object Current { get { return current; } } } public class List { public IEnumerator GetEnumerator() { for (int i = 0; i < count; i++) {yield return elements[i]; } } }
Iterators public class List<T> { public IEnumerator<T> GetEnumerator() { for (int i = 0; i < count; i++) yield return elements[i]; } public IEnumerable<T> Descending() { for (int i = count - 1; i >= 0; i--) yield return elements[i]; } public IEnumerable<T> Subrange(int index, int n) { for (int i = 0; i < n; i++) yield return elements[index + i]; } } List<Item> items = GetItemList(); foreach (Item x in items) {…} foreach (Item x in items.Descending()) {…} foreach (Item x in Items.Subrange(10, 20)) {…}
Tipos Parciais public partial class Customer { private int id; private string name; private string address; private List<Orders> orders; } public class Customer { private int id; private string name; private string address; private List<Orders> orders; public void SubmitOrder(Order order) { orders.Add(order); } public bool HasOutstandingOrders() { return orders.Count > 0; } } public partial class Customer { public void SubmitOrder(Order order) { orders.Add(order); } public bool HasOutstandingOrders() { return orders.Count > 0; } }
Classes Estáticas • Pode conter apenas membros estáticos • Não pode ser tipo de variável, parâmetro, … • System.Console, System.Environment, … public static class Math { public static double Sin(double x) {…} public static double Cos(double x) {…} … }
Acesso à Propriedades • Diferentes níveis de acesso para Get/Set • Típica configuração set {…} mais restrito que get {…} public class Customer { private string id; public string CustomerId { get { return id; } internal set { id = value; } } }
Aliases Externos • Assemblies com nomes de tipo idênticos • Versões diferentes do mesmo assembly foo.dll bar.dll extern alias Foo; extern alias Bar; class Program { static void Main() { Foo.Stuff.Utils.F(); Bar.Stuff.Utils.F(); } } namespace Stuff { public class Utils { public static void F() {…} } } namespace Stuff { public class Utils { public static void F() {…} } } C:\>csc /r:Foo=foo.dll /r:Bar=bar.dll test.cs
Namespace Alias Qualifiers • A::B procura por A como namespace alias • global::X procura X no namespace global using IO = System.IO; class Program { static void Main() { IO::Stream s = new IO::File.OpenRead("foo.txt"); global::System.Console.WriteLine("Hello"); } }
Controle de Warning • #pragma warning using System; class Program { [Obsolete] static void Foo() {} static void Main() { #pragma warning disable 612 Foo(); #pragma warning restore 612 } }
ThreadingSemaphore • Resource counting for mutex’s // construct a semaphore with a count of 3 Semaphore sem = new Semaphore(3); private void UseResource { // Wait until a count is available… sem.WaitOne(); // the sem count is reduced by one // other code … // Release the count: sem.Release(); // the count is incremented by one
ThreadingNamed Events V1.0 and V1.1: Events can only signal the same process Whidbey: Named Events allow cross process communication Public Class EventWaitHandle Inherits WaitHandle PublicSub New EventWaitHandle(initialState As Boolean, type As EventType, name As String )
Longhorn and WinFX: Re-Invigorating the Virtuous Cycle • Applies .NET Framework goodness to core OS • Consistent, object oriented • Secure, reliable platform • Modern library and language designs • Enables new class of applications all built on managed code • Fuels ecosystems for the next decade of growth
For More Information • Applied Microsoft .NET Framework Programming (Richter) • NET Framework Standard Library Annotated Reference, Vol. 1 (Abrams) • http://blogs.msdn.com/brada
© 2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.