320 likes | 335 Views
DEV 331 深度探索 Microsoft Visual C# 2.0. 付仲恺 微软特邀开发专家. C# 2.0 增强. 范型( Generics ) 匿名方法( Anonymous methods ) 可为空类型( Nullable types ) 迭代器( Iterators ) 局部类型( Partial types ) 等等 100% 向后兼容. 范型( Generics ). public class List { private object[] elements; private int count;
E N D
DEV 331深度探索 Microsoft Visual C# 2.0 付仲恺 微软特邀开发专家
C# 2.0增强 • 范型(Generics) • 匿名方法(Anonymous methods) • 可为空类型(Nullable types) • 迭代器(Iterators) • 局部类型(Partial types) • 等等 • 100%向后兼容
范型(Generics) 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
范型(Generics) • 为什么需要范型? • 类型检查,不进行拆箱和类型强制转换 • 增加了代码重用机会(类型集合) • C#如何实现范型? • 在运行时实例化,而不是编译时 • 类型检查在声明时,而不是实例化时进行 • 同时支持引用和值类型 • 完整的运行时类型信息
范型(Generics) • 类型参数能够被应用于: • 类,结构体,接口,委托类型 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;
范型(Generics) • 类型参数能够被应用于: • 类,结构体,接口,委托类型 • 方法 class Utils{ public static T[] CreateArray<T>(T value, int size) { T[] result = new T[size]; for (int i = 0; i < size; i++) result[i] = value; return result; } } string[] names = Utils.CreateArray<string>("", 10); int[] numbers = Utils.CreateArray<int>(-1, 100); string[] names = Utils.CreateArray("", 10); int[] numbers = Utils.CreateArray(-1, 100); 类型推断!
范型(Generics) • 类型参数能够被应用于: • 类,结构体,接口,委托类型 • 方法 • 类型参数能够具有约束 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) { ... } }
范型(Generics) • 只允许有一个基本约束 • 实际类,或者结构体 • 可以有多个次要约束 • 接口或者类型参数 • 可以有一个构造约束 • new() class Link<T> where T: class {...} class Nullable<T> where T: struct {...} class Relation<T,U> where T: class where U: T {...}
范型(Generics) void Foo<T>() { T x = null; // Error T y = default(T); // Ok } • default(T) • 类型转换 • Null检查 void Foo<T>(T x) { int i = (int)x; // Error int j = (int)(object)x; // Ok } void Foo<T>(T x) { if ((object)x == null) {...} }
范型(Generics) List<T> Dictionary<K,V> SortedDictionary<K,V> Stack<T> Queue<T> • 集合类 • 集合接口 • 集合基本类 • 工具类 • 反射 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>
匿名方法(Anonymous Methods) 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; } } public class Bank { List<Account> accounts; List<Account> GetOverdrawnAccounts() { return accounts.FindAll( new Predicate<Account>(IsOverdrawn) ); } static bool IsOwerdrawn(Account a) { return a.Balance < 0; } } public class Bank { List<Account> accounts; List<Account> GetOverdrawnAccounts() { return accounts.FindAll( delegate(Account a) { return a.Balance < 0; } ); } }
匿名方法(Anonymous Methods) • 代码块替代委托方法 • 自动推断委托类型 • 代码块可以忽略参数列表 button.Click += delegate { MessageBox.Show("Hello"); }; button.Click += delegate(object sender, EventArgs e) { MessageBox.Show(((Button)sender).Text);};
匿名方法(Anonymous Methods) • 支持Closures public class Bank { List<Account> accounts; List<Account> GetOverdrawnAccounts() { return accounts.FindAll( delegate(Account a) { return a.Balance < 0; } ); } } public class Bank { List<Account> accounts; List<Account> GetOverdrawnAccounts() { return accounts.FindAll( delegate(Account a) { return a.Balance < 0; } ); } List<Account> GetLargeAccounts(double minBal) { return accounts.FindAll( delegate(Account a) { return a.Balance >= minBal; } ); } } public class Bank { List<Account> GetLargeAccounts(double minBal) { Helper helper = new Helper(); helper.minBal = minBal; return accounts.FindAll(helper.Matches); } internal class Helper { internal double minBal; internal bool Matches(Account a) { return a.Balance >= minBal; } }}
匿名方法(Anonymous Methods) • 方法组转换 • 在可能的情况下,推断出委托类型 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(); } }
可为空类型(Nullable Types) • System.Nullable<T> • 为所有值类型提供可为空的能力 • 具有类型T和布尔值的结构体 int 123 public struct Nullable<T> where T: struct { private T value; private bool hasValue; public T Value { get { … } } public bool HasValue { get { … } } } Nullable<int> 123 ??? true false Non-null Null
Nullable Types int? x = 123; double? y = 1.0; • T? 语法 • null 赋值 • 不同类型转换 • Lifted操作符 • Null结合运算符 int? x = null; double? y = null; int i = 123; int? x = i; // T T? implicitint j = (int)x; // T? T explicit int? x = GetNullableInt(); int? y = GetNullableInt(); int? z = x + y; int? x = GetNullableInt(); int i = x ?? 0;
迭代器(Iterators) • foreach依赖于“枚举模式” • GetEnumerator() 方法 • foreach使得枚举变得更加方便 • 但是枚举器的实现难度加大了! 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 IEnumerator GetEnumerator() { return new ListEnumerator(this); } } public class List { internal object[] elements; internal int count; public IEnumerator GetEnumerator() { for (int i = 0; i < count; i++) { yield return elements[i]; } } }
迭代器(Iterators) public IEnumerator GetEnumerator() { return new __Enumerator(this); } private class __Enumerator : IEnumerator{ object current; int state; public bool MoveNext() { switch (state) { case 0: current = "Hello"; state = 1; return true; case 1: current = "World"; state = 2; return true; default: return false; } } public object Current { get { return current; } } } • 方法递增计算并且返回一系列数值 • yield return和yield break • 必须返回IEnumerator或者IEnumerable public class Test { public IEnumerator GetEnumerator() { yield return "Hello"; yield return "World"; } }
迭代器(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)) {...}
局部类型(Partial Types) 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; } }
静态类(Static Classes) • 只有静态成员 • 不能被用于变量,参数,域,属性等类型 • 例如:System.Console,System.Environment public static class Math { public static double Sin(double x) {...} public static double Cos(double x) {...} ... }
属性访问器(Property Accessors) • 不同的访问器访问权限 • 访问器能够被严格限制 • 一般来说,set{…}的权限更加严格 public class Customer { private string id; public string CustomerId { get { return id; } internal set { id = value; } } }
外部别名(External Aliases) • 在不同的程序集中使用相同的命名类型 namespace Stuff { public class Utils { public static void F() {...} } } foo.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() {...} } } bar.dll C:\>csc /r:Foo=foo.dll /r:Bar=bar.dll test.cs
命名空间别名修饰符(Namespace Alias Qualifiers) • 版本上更加有弹性的代码 • A::B仅将A作为别名 • global::X作为全局命名空间 using IO = System.IO; class Program { static void Main() { IO::Stream s = new IO::File.OpenRead("foo.txt"); global::System.Console.WriteLine("Hello"); } }
内联警告控制(Inline Warning Control) • #pragma warning using System; class Program { [Obsolete] static void Foo() {} static void Main() { #pragma warning disable 612 Foo(); #pragma warning restore 612 } }
固定大小缓冲区(Fixed Size Buffers) • 在非安全代码中的C语言风格数组 public struct OFSTRUCT { public byte cBytes; public byte fFixedDisk; public short nErrCode; private int Reserved; public fixed char szPathName[128]; }