36
Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager [email protected] http://blogs.msdn.com/danielfe/

Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager [email protected]

Embed Size (px)

Citation preview

Page 1: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

Visual C# 2005: IDE Enhancements

Dan FernandezC# Product [email protected]://blogs.msdn.com/danielfe/

Page 2: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

2

Agenda

• Generics• Anonymous methods• Nullable types• Iterators• Partial types• and many more…• 100% backwards compatible

Page 3: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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)

Page 4: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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;}}

Page 5: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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

Page 6: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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

Page 7: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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;

Page 8: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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);

Page 9: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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) { … … }}}}

Page 10: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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;

Page 11: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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}}

Page 12: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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

Page 13: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

Generics Performance

Page 14: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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

Page 15: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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);}}

Page 16: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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?

Page 17: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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); };}; }}}}

Page 18: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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);};};

Page 19: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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 );

Page 20: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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 );

Page 21: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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

Page 22: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

Anonymous Methods

Page 23: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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);}}

Page 24: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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]; } }}}}

Page 25: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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; } }}}}

Page 26: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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)) {…}

Page 27: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

Iterators

Page 28: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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; }}}}

Page 29: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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

Page 30: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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) {...} ......}}

Page 31: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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; } }}}}

Page 32: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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

Page 33: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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 }}}}

Page 34: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

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];}}

Page 35: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

35

Resources

• Visual C# Developer Center– http://msdn.microsoft.com/vcsharp/

• MSDN Forums– http://forums.msdn.com

• Email– [email protected]

Page 36: Visual C# 2005: IDE Enhancements Dan Fernandez C# Product Manager danielfe@microsoft.com

36© 2005 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only.

MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.