C# Training

2,314 views

Published on

http://www.intertech.com/Courses/Course.aspx?CourseID=99303

This is a slide deck from a C# training session held at Microsoft.

Published in: Technology
  • Be the first to comment

C# Training

  1. 1. A Preview of C# 3.0 Andrew Troelsen, Microsoft C# MVP Intertech Training 2006
  2. 2. C# 3.0 Preview Overview of Presentation: Overall design goals of C# 3.0 Interacting with the C# 3.0 compiler Understanding Implicitly Typed Local Variables Working with Extension Methods The role of Object Initializers Anonymous Types Introduction to Lambda Expressions Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 2
  3. 3. C# 3.0 Preview In this industry, the only constant is change. Just when we were feeling comfortable with generics, partial types, anonymous methods (et.al.), word of C# 3.0 hits the streets. C# 3.0 is currently in its beta cycle, however the bits we now have are much more stable than those released at the PDC. The final release of C# 3.0 is not scheduled to ship until Summer 07, however the core language constructs shown here seem to be quite solid. Of course, since this is beta technology, things may change a tad from what we see here. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 3
  4. 4. C# 3.0 Preview Of all the .NET programming languages, C# has always incorporated some ‘obscure’ features which set it apart from others (such as VB): Support for pointer arithmetic (unsafe code). Anonymous methods (inline event handling). Operating overloading (now supported in VB, but still ;-) Using these features, C# is well suited not only to business development (bind data to grids) but academic development as well (build a finite state machine). C# 3.0 adds a slew of new features which at first glance might seem more academic than practical. However, once you get comfortable with these new constructs, you’ll wonder how you lived without them. This is especially true when you dig into LINQ technologies (DLinq, XLinq). Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 4
  5. 5. C# 3.0 Preview The new C# 3.0 features move the language into the realm of other functional languages such as LISP, ADA, Haskell and the experimental F#. In a nutshell, functional programming is a paradigm that treats computation as the evaluation of mathematical functions. As well, such languages are heavily influenced by the lambda calculus. Thankfully, you do not need a degree is mathematical logic or experience with the gory details of lambdas. However, if this is the case, all the better. If this is not the case, no problems. The syntax is not that bad ;-) Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 5
  6. 6. C# 3.0 Preview While many people assume C# 3.0 is only about LINQ technologies (XLinq, DLinq), this is not the case. C# has many language enhancements that work as independent entities. However, these same techniques certainly enable the LINQ project. I’ll be speaking on LINQ tomorrow @ 9:00am. To being playing around with C# 3.0, your first step is to download the LINQ CTP: http://msdn.microsoft.com/data/ref/linq Once you have done so, you will find the C# 3.0 compiler, sample code, (some) documentation. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 6
  7. 7. C# 3.0 Preview Better yet, VS 2005 will now have a set of project templates which are LINQ specific. While this talk does not examine the LINQ namespaces or assemblies, choosing a LINQ console application will allow us to interact with the C# 3.0 compiler. The other option is to directly make use of the C# 3.0 compiler and your editor of choice. By default, this will be installed under: C:Program FilesLINQ PreviewBin Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 7
  8. 8. C# 3.0 Preview There is a known bug which will cripple IntelliSense! When you install the LINQ CTP, code snippets, refactoring-right- clicking and other helpful features are now broken. To fix this locate the following key using regedit.exe: HKEY_LOCAL_MACHINESoftwareMicrosoftVisualStudio8.0Packages{A06 6E284-DCAB-11D2-B551-00C04F68D4DB}SatelliteDLL Change quot;C:Program FilesMicrosoft Visual Studio 8VC#VCSPackages1033quot; to quot;C:Program FilesMicrosoft Visual Studio 8VC#VCSPackagesquot;. Finally, run devenv /setup /resetuserdata /resetsettings at a command prompt. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 8
  9. 9. C# 3.0 Preview As you know, declaring a local variable in C# is a very predictable process: static void Main() { // Local variables are declared as so: // dataType variableName = initialValue; int myInt = 0; bool myBool = true; string myString = quot;Time, marches on…quot;; } C# 3.0 introduces implicit typing of local variables. This allows you to declare local variables without specifying the ‘type of type’. This is accomplished using the new var keyword. static void Main() The initial value must be assigned at the time the { value is declared, much like a const. // Implicitly typed local variables. var myInt = 0; var myBool = true; Initial assignment of null to a var type is also illegal. var myString = quot;Time, marches on…quot;; } The var keyword is not legal for member variables, params or return values. Local variables only! Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 9
  10. 10. C# 3.0 Preview At compile time, the underlying type is correctly inferred based on the initial value assignment. Here, myInt is a System.Int32, myString is a System.String and myBool is a System.Boolean. static void Main() { Console.WriteLine(quot;***** Fun with Implicit Typing *****nquot;); // Implicitly typed local variables. var myInt = 0; var myBool = true; var myString = quot;Time, marches on…quot;; // Print out the underlying type. Console.WriteLine(quot;myInt is a: {0}quot;, myInt.GetType().Name); Console.WriteLine(quot;myBool is a: {0}quot;, myBool.GetType().Name); Console.WriteLine(quot;myString is a: {0}quot;, myString.GetType().Name); } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 10
  11. 11. C# 3.0 Preview Of course, this implicit typing can work with any type, not just CLR primitives: var myIntArray = new int[] {10, 20, 30}; var myDictionary = new Dictionary<int,string>(); var myCar = new SportsCar(); As well, var can be used as an index within a foreach loop: // Use 'var' in a standard for each loop. var myIntArray = new int[] {10, 20, 30}; // Here, var is representing a System.Int32. foreach (var item in myIntArray) { Console.WriteLine(quot;Item value: {0}quot;, item); } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 11
  12. 12. C# 3.0 Preview At this point, you may be having a panic attack: Scripting code in C#!?? Is this the evil VARIANT again??!! Are they making C# into VB? Thankfully, the answer is no on all accounts. Implicitly typed local variables cannot change their underlying type once assigned: Therefore we still have type safety. // The compiler knows myVar is a string, not an integer! var s = quot;This variable can only hold string data!quot;; s = quot;This is fine…quot;; s = 44; // This is an error! Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 12
  13. 13. C# 3.0 Preview OK, but why? Using implicit typing ‘just for the heck of it’ is bad style. Don’t be a scripter ;-) However, many query expressions in the LINQ APIs can return back a vast number of data types, created dynamically at runtime. In these cases, implicit typing is extremely helpful, as we do not need to explicitly define all of the types that the queries might return, saving a lot of tedious typing time. Remember however, it is strickly optional. Here, silverCars is of type // Query expressions can return a ton of types. var silverCars = db.Inventory DataQuery<Inventory>. .Where(s => s.Color == quot;Silverquot;) .OrderBy(s => s.PetName) To this end, ‘var’ is much simpler. .Select(s => s); Console.WriteLine(silverCars.GetType().FullName); Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 13
  14. 14. C# 3.0 Preview C# 3.0 introduces the notion of extension methods. This language feature makes it possible to extend the functionality of a type after compile time. This allows you to increase the functionality to a type to which you do not have the source code. Using extension methods, you can add functionality to precompiled types, while providing the illusion these extensions were there all along. This feature can be very helpful when a third party library has a type which needs to be incorporated into your code in a polymorphic manner. This technique also make it possible for third parties to integrate with existing Microsoft APIs (such as LINQ). Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 14
  15. 15. C# 3.0 Preview When you define extension methods, the first restriction is that they must be defined within a static class. Therefore, each method must also be static. The second point is that all extension methods are marked as such by using the this keyword as a modifier on the first parameter. And only the first… The third point is that every extension method can either be called from the correct instance in memory, or statically via the defining static class Sound strange? Let’s see a full example. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 15
  16. 16. C# 3.0 Preview static class MyExtensions This method allows any { object to display the assembly public static void DisplayDefiningAssembly(this object obj) { it is defined in. Console.WriteLine(quot;{0} lives here:nt->{1}nquot;, obj.GetType().Name, Assembly.GetAssembly(obj.GetType())); } public static int ReverseDigits(this int i) { // Translate int into a string, and then // get all the characters. This method allows any integer char[] digits = i.ToString().ToCharArray(); to reverse its digits. for example, 56 would return 65. // Now reverse items in the array. Array.Reverse(digits); // Put back into string. string newDigits = new string(digits); // Finally, return the modified string back as an int. return int.Parse(newDigits); } } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 16
  17. 17. C# 3.0 Preview Understand of course that a given extension method could have multiple parameters, however only the first parameter can be qualified with this. static class TesterUtilClass { // Every Int32 now has a Foo() method… public static void Foo(this int i) { Console.WriteLine(quot;{0} called the Foo() method.quot;, i); } // …which has been overloaded to take a string! public static void Foo(this int i, string msg) { Console.WriteLine(quot;{0} called Foo() and told me: {1}quot;, i, msg); } } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 17
  18. 18. C# 3.0 Preview static void Main(string[] args) { Console.WriteLine(quot;***** Fun with Extension Methods *****nquot;); // The int has assumed a new identity! int myInt = 12345678; myInt.DisplayDefiningAssembly(); More details in the demo… // So has the DataSet! System.Data.DataSet d = new System.Data.DataSet(); d.DisplayDefiningAssembly(); // And the MediaPlayer! System.Media.SoundPlayer sp = new System.Media.SoundPlayer(); sp.DisplayDefiningAssembly(); // Use new integer functionality. Console.WriteLine(quot;Value of myInt: {0}quot;, myInt); Console.WriteLine(quot;Reversed digits of myInt: {0}quot;, myInt.ReverseDigits()); myInt.Foo(); myInt.Foo(quot;Ints that Foo? Who would have thought it!quot;); // Error! Booleans don’t have the Foo() method! bool b2 = true; b2.Foo(); Console.ReadLine(); } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 18
  19. 19. C# 3.0 Preview C# 3.0 introduces the use of object initializer syntax. This feature allows you hydrate an object using a set of name/value pairs. This is similar to the concept of named properties when assigning values to .NET attributes. // Apply an attribute using named property syntax. [AttributeUsage(AttributeTargets.Class, Inherited=false, AllowMultiple = false)] public sealed class SomeInterestingAttribute: Attribute {…} However, unlike named properties, object init syntax can be applied to any object that supports properties (or public fields). This can be a huge timesaver as a massive amount of properties can be set with a few lines of code. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 19
  20. 20. C# 3.0 Preview // A simple Point with (X,Y) values. public struct Point static void Main(string[] args) { { private int xPos, yPos; // Make a Point by setting each property manually. public Point(int x, int y) Point firstPoint = new Point(); { xPos = x; yPos = y; } firstPoint.X = 10; firstPoint.Y = 10; public int X { // Make a Point via custom constructor. get { return xPos; } Point anotherPoint = new Point(20, 20); set { xPos = value; } } // Make a Point using object init syntax (3.0 only). public int Y var yetAnotherPoint = new Point { X = 30, Y = 30 }; { Point finalPoint = new Point { X = 30, Y = 30 }; get { return yPos; } } set { yPos = value; } } public override string ToString() More details in the demo… { return string.Format(quot;[{0}, {1}]quot;, xPos, yPos); } } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 20
  21. 21. C# 3.0 Preview C#3.0 introduces the concept of anonymous types. Recall that C# 2.0 provided support for anonymous methods. This syntax makes it possible to specify a block of code statements anywhere a delegate is required. Helpful for ‘in-lining’ event handlers. An anonymous type is similar, in that we can specify a set of name/value pairs to represent an entire class. We don’t need to define the class whatsoever. The compiler generates the class definition as a strongly typed data structure. However, we never see the underlying class type, thus we must use var. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 21
  22. 22. C# 3.0 Preview This technique can be very helpful when: You need to quickly model a custom UDT, but the type is fairly expendable. You need to model a custom UDT for structure, not for typing. Again, many LINQ technologies require you to define UDTs on the fly. Using anonymous types, you can do so without needing to define an entire class definition. The compiler generated class will: Be sealed (for security purposes). Extend System.Object. Override GetHashCode(), ToString(), Equals(). Define fields and properties for each specified field. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 22
  23. 23. C# 3.0 Preview // Make an anonymous type representing a car. var myCar = new {Color = quot;Bright Pinkquot;, Make = quot;Saabquot;, CurrentSpeed = 55}; // We can now get and set each value using property syntax. myCar.Color = quot;Blackquot;; Console.WriteLine(quot;My car is the color {0}.quot;, myCar.Color); [CompilerGenerated] public sealed class <Projection>f__0 Notice how each name/value pair { is mapped to a property with // Methods public <Projection>f__0(); backing field. public override bool Equals(object); public override int GetHashCode(); public override string ToString(); • Equals() is based of reference semantics. // Properties • ToString() prints the state of the object. public string Color { get; set; } public int CurrentSpeed { get; set; } • GetHashCode() is appropriate public string Make { get; set; } placement in a Hashtable. // Fields private string _Color; private int _CurrentSpeed; private string _Make; More details in the demo… } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 23
  24. 24. C# 3.0 Preview The final C# 3.0 topic we will examine here is the use of lambda expressions. Those who have a background in mathematics may recall that lambda expressions are based on the lambda calculus. A full examination of the lambda calculus is beyond the scope of this chat. If you are very new to the topic, look up the topic on wikipedia.com. This can provide some helpful context. In C# 3.0, lambda expressions are used as a better anonymous method. That is the big appeal. Using lambdas, you are able to clean up the (slightly clunky) syntax used under 2.0 with a simple, clear lambda statement. Well, simple and clear once you stomach the => token ;-) Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 24
  25. 25. C# 3.0 Preview Assume you wish to call the List<T>.FindAll() method to determine which of a set of integers are even or odd. The FindAll() method requires a generic delegate of type Predicate<>. Using ‘normal’ delegate syntax, we might author the following C# code. class Program { static void Main(string[] args) { // Make a list of integers using C# 3.0 // collection initialization syntax. List<int> list = new List<int>() {20, 1, 4, 8, 9, 44}; // Call FindAll() using traditional delegate syntax. Predicate<int> callback = new Predicate<int>(CallMeHere); list.FindAll(callback); This is OK, but now we have a foreach (int evenNumber in evenNumbers) { method which is only called by one Console.WriteLine(evenNumber); specific method in the code base… } } // Is it an even number? Neither elegant nor functional! static bool CallMeHere(int i) { return (i % 2) == 0; } } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 25
  26. 26. C# 3.0 Preview Using a C# 2.0 anonymous method, things can clean up a bit. Notice that now we are passing in a block of code statements via the delegate keyword. Also notice we no longer need a separate delegate handler. static void Main(string[] args) { List<int> list = new List<int>() {20, 1, 4, 8, 9, 44}; // Now, use an anonymous method. List<int> evenNumbers = list.FindAll(delegate(int i) { return (i % 2) == 0; } ); foreach (int evenNumber in evenNumbers) { Console.WriteLine(evenNumber); } Better, but the required use of the } delegate, and the strong typing of the parameters is less than ideal. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 26
  27. 27. C# 3.0 Preview Using a C# 3.0 lambda expression, things clean up a huge deal: Recall! A lambda can be used anywhere you used to use an anonymous method as delegate substitution! Best! static void Main(string[] args) { List<int> list = new List<int>() {20, 1, 4, 8, 9, 44}; The data on the left of the => token is a set of parameters to be processed. // Now, use a C# 3.0 lambda expression. List<int> evenNumbers = list.FindAll(i => (i % 2) == 0); The => token is the lambda operator. foreach (int evenNumber in evenNumbers) { On the right of the => token is the Console.WriteLine(evenNumber); } code used to process the parameters. } This could either be a simple expression or a block of code! Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 27
  28. 28. C# 3.0 Preview The previous lambda expression made use of implicit typing of the parameter set. If you wish, you can specify the underlying type, however the compiler will infer this passed on the expression statements. As well, parameters can be placed in parens. This is optional when you have a single parameter, however mandatory when you have multiple arguments. // Now, explicitly state what the parameter type. var evenNumbers = list.FindAll((int i) => (i % 2) == 0); Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 28
  29. 29. C# 3.0 Preview As mentioned, lambdas can also process a set of arguments within a scope of code statements. Obviously, many delegate targets have to do more than make simple statement evaluations. // This time the lambda expression is build with a statement // block. var justATest = list.FindAll(i => { Console.WriteLine(quot;Called by FindAll()!quot;); Console.WriteLine(quot;value of i is currently: {0}quot;, i); bool isEven = ((i % 2) == 0); return isEven; } ); foreach (var evenNumber in justATest) { Console.WriteLine(evenNumber); More details in the demo… } Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 29
  30. 30. C# 3.0 Preview Wrap up! C# 3.0 brings a number of new language features which bring us closer to a functional language. Implicitly typed local variables. Extension methods. Object init syntax. Anonymous types Support for lambda expressions. C# 3.0 supports Expression Trees which allow you to treat a lambda expression as an object model. While not covered here, this allows others to extend and manipulate existing lambdas. As mentioned, many of these features are most helpful when working with LINQ technologies. Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 30
  31. 31. C# 3.0 Preview Copyright © Intertech, Inc. 2006 • www.Intertech.com • 800-866-9884 • Slide 31

×