visual c# 2005: ide enhancements dan fernandez c# product manager [email protected]
TRANSCRIPT
Visual C# 2005: IDE Enhancements
Dan FernandezC# Product [email protected]://blogs.msdn.com/danielfe/
2
Agenda
• Generics• Anonymous methods• Nullable types• Iterators• Partial types• and many more…• 100% backwards compatible
3
Generics
• What are they?– Code that allows you to pass the data type as a
parameter. – Rather then explicitly declaring the data type (int,
string) when writing code, you use a generic data type instead
• Benefits– Code reusability– Type checking, no boxing, no downcasts– Reduced code bloat (typed collections)
4
Generic Basics
• T can be used for any numerical type
public struct Point<T> {public struct Point<T> { public T X;public T X; public T Y;public T Y;}}
Point<int> point;Point<int> point;point.X = 10;point.X = 10;point.Y = 20;point.Y = 20;
Point<float> point;Point<float> point;point.X = 1.2f;point.X = 1.2f;point.Y = 3.4f;point.Y = 3.4f;
public struct Point {public struct Point { public int X;public int X; public int Y;public int Y;}}
public struct Point {public struct Point { public float X;public float X; public float Y;public float Y;}}
public struct Point {public struct Point { public long X;public long X; public long Y;public long Y;}}
5
public class Listpublic class List{{ private object[] elements;private object[] elements; private int count;private int count;
public void Add(object element) {public void Add(object element) { if (count == elements.Length) if (count == elements.Length) Resize(count * 2);Resize(count * 2); elements[count++] = element;elements[count++] = element; }}
public object this[int index] {public object this[int index] { get { return elements[index]; }get { return elements[index]; } set { elements[index] = value; }set { elements[index] = value; } }}
public int Count {public int Count { get { return count; }get { return count; } }}}}
Genericspublic class Listpublic class List<<TT>>{{ private private TT[] elements;[] elements; private int count;private int count;
public void Add(public void Add(TT element) { element) { if (count == elements.Length) if (count == elements.Length) Resize(count * 2);Resize(count * 2); elements[count++] = element;elements[count++] = element; }}
public public TT this[int index] { this[int index] { get { return elements[index]; }get { return elements[index]; } set { elements[index] = value; }set { elements[index] = value; } }}
public int Count {public int Count { get { return count; }get { return count; } }}}}
List intList = new List();List intList = new List();
intList.Add(1);intList.Add(1);intList.Add(2);intList.Add(2);intList.Add("Three");intList.Add("Three");
int i = (int)intList[0];int i = (int)intList[0];
List intList = new List();List intList = new List();
intList.Add(1);intList.Add(1); // Argument is // Argument is boxedboxedintList.Add(2);intList.Add(2); // Argument is // Argument is boxedboxedintList.Add("Three");intList.Add("Three"); // Should be an // Should be an errorerror
int i = (int)intList[0];int i = (int)intList[0]; // Cast required// Cast required
ListList<int><int> intList = new List intList = new List<int><int>();();
intList.Add(1);intList.Add(1); // No boxing// No boxingintList.Add(2);intList.Add(2); // No boxing// No boxingintList.Add("Three");intList.Add("Three"); // Compile-time // Compile-time errorerror
int i = intList[0];int i = intList[0]; // No cast required// No cast required
6
Generics
• How are C# generics implemented?– Instantiated at run-time, not compile-time– Checked at declaration, not instantiation– Work for both reference and value types– Complete run-time type information through reflection– JIT compiler replaces generic IL with object references– Specific to App Domain
• Value types– Compiler will create one version for each value type (one for int,
one for long, etc)– Reused for same value type
• Reference types– Compiler will create one version for all reference types
• Ex: Customer class, DataSet, Orders class– Reused in all further encounters of all other reference
types
7
Generics
• Type parameters can be applied to– Class, struct, interface, and delegate types
class Dictionary<K,V> {…}class Dictionary<K,V> {…}
struct HashBucket<K,V> {…}struct HashBucket<K,V> {…}
interface IComparer<T> {…}interface IComparer<T> {…}
delegate R Function<A,R>(A arg);delegate R Function<A,R>(A arg);
Dictionary<string,Customer> Dictionary<string,Customer> customerLookupTable;customerLookupTable;
Dictionary<string,List<Order>> Dictionary<string,List<Order>> orderLookupTable;orderLookupTable;
Dictionary<int,string> numberSpellings;Dictionary<int,string> numberSpellings;
8
Generics
• Type parameters can be applied to– Class, struct, interface, and delegate types– Methods
class Utilsclass Utils{{ public static T[] CreateArray<T>(int public static T[] CreateArray<T>(int size) {size) { return new T[size];return new T[size]; }}
public static void SortArray<T>(T[] public static void SortArray<T>(T[] array) {array) { … … }}}}
string[] names = string[] names = Utils.CreateArray<string>(3);Utils.CreateArray<string>(3);names[0] = "Jones";names[0] = "Jones";names[1] = "Anderson";names[1] = "Anderson";names[2] = "Williams";names[2] = "Williams";Utils.SortArray(names);Utils.SortArray(names);
9
Generics
• Type parameters can be applied to– Class, struct, interface, and delegate types– Methods
• Type parameters can have constraints– One base class, multiple interfaces, new()
class Dictionary<K,V>class Dictionary<K,V>{{ public void Add(K key, V value) {public void Add(K key, V value) { … … if (if (((IComparable)key).CompareTo(x) == 0((IComparable)key).CompareTo(x) == 0) ) {…}{…} … … }}}}
class Dictionary<K,V> class Dictionary<K,V> where K: IComparablewhere K: IComparable{{ public void Add(K key, V value) {public void Add(K key, V value) { … … if (if (key.CompareTo(x) == 0key.CompareTo(x) == 0) {…}) {…} … … }}}}
class Dictionary<K,V>: IDictionary<K,V>class Dictionary<K,V>: IDictionary<K,V> where K: IComparable<K>where K: IComparable<K> where V: IKeyProvider<K>, IPersistable, new()where V: IKeyProvider<K>, IPersistable, new(){{ public void Add(K key, V value) { public void Add(K key, V value) { … … }}}}
10
Generic Constraints
• Zero or one primary constraint– Actual class, class, or struct
• Zero or more secondary constraints– Interface or type parameter
• Zero or one constructor constraint– new()
public struct Point<T> public struct Point<T> : struct: struct{{ public T X;public T X; public T Y;public T Y;}}Point<float> point;Point<float> point;point.X = 1.2f;point.X = 1.2f;point.Y = 3.4f;point.Y = 3.4f;
11
Generics
• T.default
• Null checks
• Type casts
void Foo<T>() {void Foo<T>() { T x = null;T x = null; // Error// Error T y = T.default;T y = T.default; // Ok// Ok}}
void Foo<T>(T x) {void Foo<T>(T x) { if (x == null) {if (x == null) { throw new throw new FooException();FooException(); } …} …}}
void Foo<T>(T x) {void Foo<T>(T x) { int i = (int)x;int i = (int)x; // // ErrorError int j = (int)(object)x;int j = (int)(object)x; // // OkOk}}
12
Generics in the .NET Framework
• Collection classes
• Collection interfaces
• Collection base classes
• Utility classes
• Reflection
LinkedList<T>LinkedList<T>List<T>List<T>Dictionary<K,V>Dictionary<K,V>SortedDictionary<K,V>SortedDictionary<K,V>Stack<T>Stack<T>Queue<T>Queue<T>
IList<T>IList<T>IDictionary<K,V>IDictionary<K,V>ICollection<T>ICollection<T>IEnumerable<T>IEnumerable<T>IEnumerator<T>IEnumerator<T>IComparable<T>IComparable<T>IComparer<T>IComparer<T>
Collection<T>Collection<T>KeyedCollection<T>KeyedCollection<T>ReadOnlyCollection<T>ReadOnlyCollection<T>
Nullable<T>Nullable<T>EventHandler<T>EventHandler<T>Comparer<T>Comparer<T>
Native support in IL and CLR
Generics Performance
14
What’s wrong with this code?
SqlCommand cmd = new SqlCommand();SqlCommand cmd = new SqlCommand(); using (SqlDataReader rs = cmd.ExecuteReader())using (SqlDataReader rs = cmd.ExecuteReader()) {{ while (rs.Read())while (rs.Read()) {{ int Age;int Age; Age = (int)rs["Age"];Age = (int)rs["Age"]; Console.WriteLine(Age);Console.WriteLine(Age); }} }}
AgeAge------------------30305050nullnull2121
15
Nullable Types
• System.Nullable<T>– Provides nullability for any value type– Struct that combines a T and a bool
public struct Nullable<T> where T: structpublic struct Nullable<T> where T: struct{{ public Nullable(T value) {...}public Nullable(T value) {...} public T Value { get {...} }public T Value { get {...} } public bool HasValue { get {...} }public bool HasValue { get {...} } ......}}
Nullable<int> x = new Nullable<int>(123);Nullable<int> x = new Nullable<int>(123);......if (x.HasValue) if (x.HasValue) {{ Console.WriteLine(x.Value);Console.WriteLine(x.Value);}}
16
Nullable Types
• T? same as System.Nullable<T>
• null literal conversions
• Nullable conversions
int? x = 123;int? x = 123;double? y = 1.25;double? y = 1.25;
int? x = null;int? x = null;double? y = null;double? y = null;
int i = 123;int i = 123;int? x = i;int? x = i; // int --> int?// int --> int?double? y = x;double? y = x; // int? --> double?// int? --> double?
17
Anonymous Methods
class MyForm : Formclass MyForm : Form{{ ListBox listBox;ListBox listBox; TextBox textBox;TextBox textBox; Button addButton;Button addButton;
public MyForm() {public MyForm() { listBox = new ListBox(...);listBox = new ListBox(...); textBox = new TextBox(...);textBox = new TextBox(...); addButton = new Button(...);addButton = new Button(...); addButton.Click += addButton.Click += new new EventHandler(AddClick);EventHandler(AddClick); }}
void AddClick(object sender, EventArgs e) {void AddClick(object sender, EventArgs e) { listBox.Items.Add(textBox.Text);listBox.Items.Add(textBox.Text); }}}}
class MyForm : Formclass MyForm : Form{{ ListBox listBox;ListBox listBox; TextBox textBox;TextBox textBox; Button addButton;Button addButton;
public MyForm() {public MyForm() { listBox = new ListBox(...);listBox = new ListBox(...); textBox = new TextBox(...);textBox = new TextBox(...); addButton = new Button(...);addButton = new Button(...); addButton.Click += addButton.Click += delegate {delegate { listBox.Items.Add(textBox.Text);listBox.Items.Add(textBox.Text); };}; }}}}
18
Anonymous Methods
• Allows code block in place of delegate• Delegate type automatically inferred
– Code block can be parameterless– Or code block can have parameters– Return types must match
button.Click += delegate button.Click += delegate { MessageBox.Show("Hello"); };{ MessageBox.Show("Hello"); };
button.Click += delegate(object sender, EventArgs button.Click += delegate(object sender, EventArgs e) e) {{ MessageBox.Show(((Button)sender).Text); MessageBox.Show(((Button)sender).Text);};};
19
Generic Delegates in the .NET Framework
• Action - Performs an action on the specified object
• Predicate - Defines a set of criteria data must meet
• Converter - Converts from one type to another type
• Comparison - Compares two objects of the same type
public sealed delegate void Action<T>( T obj ); public sealed delegate void Action<T>( T obj );
public sealed delegate bool Predicate<T>( T obj ); public sealed delegate bool Predicate<T>( T obj );
public sealed delegate U Converter<T, U>( T from );public sealed delegate U Converter<T, U>( T from );
public sealed delegate int Comparison<T>( T x, T y ); public sealed delegate int Comparison<T>( T x, T y );
20
List<T> Methods that use Generic Delegates
• ForEach - Performs specified action on each element
• Find/FindIndex/FindAll/FindLast – Filters data based on condition
• ConvertAll - Converts all to another type
• TrueForAll - Determines whether every element meets criteria in predicate
public List<T> FindAll( Predicate<T> match ); public List<T> FindAll( Predicate<T> match );
public void ForEach( Action<T> action ); public void ForEach( Action<T> action );
public List<U> ConvertAll<U>( Converter<T, U> converter ); public List<U> ConvertAll<U>( Converter<T, U> converter );
public bool TrueForAll( Predicate<T> match ); public bool TrueForAll( Predicate<T> match );
21
Using Anonymous MethodsLList<int> numbers = new List<int>();ist<int> numbers = new List<int>();numbers.Add(1);numbers.Add(1);numbers.Add(1);numbers.Add(1);numbers.Add(numbers.Add(66););numbers.Add(numbers.Add(22););
int sum = 0;int sum = 0;numbers.numbers.ForEachForEach(delegate(int i)(delegate(int i) { sum += i; });{ sum += i; });Console.WriteLine(sum); //Print 10Console.WriteLine(sum); //Print 10
int match = numbers.int match = numbers.FindIndexFindIndex(delegate(int i)(delegate(int i) { return i == 6; });{ return i == 6; });Console.WriteLine(match); //Print 2Console.WriteLine(match); //Print 2
bool check = numbers.bool check = numbers.TrueForAllTrueForAll(delegate(int i)(delegate(int i) { return i > 0; }); { return i > 0; }); Console.WriteLine(check); //Print TrueConsole.WriteLine(check); //Print True
ForEachForEach
FindIndexFindIndex
TrueForAllTrueForAll
Generic ListGeneric List
Anonymous Methods
23
Iterators
• foreach relies on “enumerator pattern”– GetEnumerator() method
• foreach makes enumerating easy– But enumerators are hard to write!
foreach (object obj in list) {foreach (object obj in list) { DoSomething(obj);DoSomething(obj);}}
Enumerator e = Enumerator e = list.GetEnumerator();list.GetEnumerator();while (e.MoveNext()) {while (e.MoveNext()) { object obj = e.Current;object obj = e.Current; DoSomething(obj);DoSomething(obj);}}
24
Iterators
public class Listpublic class List{{ internal object[] elements;internal object[] elements; internal int count;internal int count;
public ListEnumerator public ListEnumerator GetEnumerator() {GetEnumerator() { return new ListEnumerator(this); return new ListEnumerator(this); }}}}
public class ListEnumerator : IEnumeratorpublic class ListEnumerator : IEnumerator{{ List list;List list; int index;int index;
internal ListEnumerator(List list) {internal ListEnumerator(List list) { this.list = list;this.list = list; index = -1;index = -1; }}
public bool MoveNext() {public bool MoveNext() { int i = index + 1;int i = index + 1; if (i >= list.count) return false;if (i >= list.count) return false; index = i;index = i; return true;return true; }}
public object Current {public object Current { get { return list.elements[index]; }get { return list.elements[index]; } }}}}
25
public class Listpublic class List{{ public IEnumerator public IEnumerator GetEnumerator() {GetEnumerator() { for (int i = 0; i < count; i++) {for (int i = 0; i < count; i++) { yield return elements[i];yield return elements[i]; }} }}}}
Iterators
• Method that incrementally computes and returns a sequence of values– yield return and yield break– Must return IEnumerator or IEnumerable
public IEnumerator public IEnumerator GetEnumerator() {GetEnumerator() { return new __Enumerator(this);return new __Enumerator(this);}}
private class __Enumerator: private class __Enumerator: IEnumeratorIEnumerator{{ object current;object current; int state;int state;
public bool MoveNext() {public bool MoveNext() { switch (state) {switch (state) { case 0: …case 0: … case 1: …case 1: … case 2: …case 2: … … … }} }}
public object Current {public object Current { get { return current; }get { return current; } }}}}
26
public class List<T>public class List<T>{{ public IEnumerator<T> GetEnumerator() {public IEnumerator<T> GetEnumerator() { for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
yield return elements[i];yield return elements[i]; }}
public IEnumerable<T> Descending() {public IEnumerable<T> Descending() { for (int i = count - 1; i >= 0; i--) for (int i = count - 1; i >= 0; i--)
yield return elements[i];yield return elements[i]; }}
public IEnumerable<T> Subrange(int index, int n) {public IEnumerable<T> Subrange(int index, int n) { for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
yield return elements[index + i];yield return elements[index + i]; }}}}
Iterators
List<Item> items = GetItemList();List<Item> items = GetItemList();foreach (Item x in items) {…}foreach (Item x in items) {…}foreach (Item x in items.Descending()) {…}foreach (Item x in items.Descending()) {…}foreach (Item x in Items.Subrange(10, 20)) {…}foreach (Item x in Items.Subrange(10, 20)) {…}
Iterators
28
Partial Typespublic partial class Customerpublic partial class Customer{{ private int id;private int id; private string name;private string name; private string address;private string address; private List<Orders> orders;private List<Orders> orders;}}
public partial class Customerpublic partial class Customer{{ public void SubmitOrder(Order order) public void SubmitOrder(Order order) {{ orders.Add(order);orders.Add(order); }}
public bool HasOutstandingOrders() {public bool HasOutstandingOrders() { return orders.Count > 0;return orders.Count > 0; }}}}
public class Customerpublic class Customer{{ private int id;private int id; private string name;private string name; private string address;private string address; private List<Orders> orders;private List<Orders> orders;
public void SubmitOrder(Order order) public void SubmitOrder(Order order) {{ orders.Add(order);orders.Add(order); }}
public bool HasOutstandingOrders() public bool HasOutstandingOrders() {{ return orders.Count > 0;return orders.Count > 0; }}}}
29
Partial Types• Break source code into multiple source files
– IDE generated vs custom code
• IL emitted as if it is one file• No messy linking
– csc customer1.cs customer2.cs
• Can provide overloads in different classes – Signature must be different
• Customer.Sell()• Customer.Sell(currency)
• Both Web and Windows Forms use partial classes for Designer Generated code
30
Static Classes
• Only static members• Cannot be used as type of variable, parameter,
field, property, …• Examples include System.Console,
System.Environment
public public staticstatic class Math class Math{{ public static double Sin(double x) {...}public static double Sin(double x) {...} public static double Cos(double x) {...}public static double Cos(double x) {...} ......}}
31
Property Accessors
• Property accessor accessibility– Allows one accessor to be restricted further– Typically set {…} more restricted than get {…}
public class Customerpublic class Customer{{ private string _CustomerID;private string _CustomerID;
public string CustomerID {public string CustomerID { get { return id; }get { return id; } internalinternal set { id = value; } set { id = value; } }}}}
32
External Aliases
• Enables use of identically named types in different assemblies
namespace Stuffnamespace Stuff{{ public class Utilspublic class Utils {{ public static void F() {...}public static void F() {...} }}}}
namespace Stuffnamespace Stuff{{ public class Utilspublic class Utils {{ public static void F() {...}public static void F() {...} }}}}
foo.dllfoo.dll
bar.dllbar.dll
extern alias Foo;extern alias Foo;extern alias Bar;extern alias Bar;
class Programclass Program{{ static void Main() {static void Main() { Foo.Stuff.Utils.F();Foo.Stuff.Utils.F(); Bar.Stuff.Utils.F();Bar.Stuff.Utils.F(); }}}}
C:\>csc /r:Foo=foo.dll /r:Bar=bar.dll test.csC:\>csc /r:Foo=foo.dll /r:Bar=bar.dll test.cs
33
Inline Warning Control
• #pragma warning
using System;using System;
class Programclass Program{{ [Obsolete][Obsolete] static void Foo() {}static void Foo() {}
static void Main() {static void Main() {#pragma warning disable 612#pragma warning disable 612 Foo();Foo();#pragma warning restore 612#pragma warning restore 612 }}}}
34
Fixed Size Buffers
• C style arrays in unsafe code
public struct OFSTRUCTpublic struct OFSTRUCT{{ public byte cBytes;public byte cBytes; public byte fFixedDisk;public byte fFixedDisk; public short nErrCode;public short nErrCode; private int Reserved;private int Reserved; public fixed char szPathName[128];public fixed char szPathName[128];}}
35
Resources
• Visual C# Developer Center– http://msdn.microsoft.com/vcsharp/
• MSDN Forums– http://forums.msdn.com
• Email– [email protected]
36© 2005 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only.
MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.