• Increased developer productivity – Implicit typing, initializers, automatic properties, anonymous types • Extensibility concepts – Extension methods, partial methods • Functional prog
Trang 1LINQ via C# 3.0
Chapter 2 – C# 3.0 Language Features
Trang 2New C# 3.0 Language Features
• Why more language features?
• Increased developer productivity
– Implicit typing, initializers, automatic properties,
anonymous types
• Extensibility concepts
– Extension methods, partial methods
• Functional programming concepts
– Lambda expressions, expression trees
• Support for integrated queries (LINQ)
– Language query operators
Trang 3Automatic Properties
public class Person {
private int id;
private string name;
public int Id {
get { return id; }
set { id = value; }
}
public string Name {
get { return name; }
get; set;
} public int Id { get; set;
} }
Becomes
Trang 4Where’s The Magic
? Where’s The Magic
?
• Compiler generated code (from Reflector: http://
tinyurl.com/9hwl7)
public class Person {
private int <Id>k BackingField;
private string <Name>k BackingField;
public int Id {
get { return this.<Id>k BackingField; }
set { this.<Id>k BackingField = value; }
}
public string Name {
get { return this.<Name>k BackingField; } set { this.<Name>k BackingField =
value; }
Trang 5Feature Notes
• Read-only properties can be emulated by specifying private set;
– This is not the equivalent of a readonly field!
– It can be modified from within the class
• The backing field is inaccessible directly
• Property logic cannot be customized for
one of the accessors
Trang 6p.Name = “John Doe”;
Person p = new Person {
Id = 2, Name = “John Doe”
};
Becomes
Trang 7Where’s The Magic
? Where’s The Magic
Trang 8Feature Notes
• Non default constructors can be called
new Person(“John Doe”) { Id = 2 }
• Why an excessive local variable?
– Emulate atomic construction and assignment
– Other threads can’t see a partially assigned object
• Some properties have severe side effects
– E.g., FileSystemWatcher.Enabled
Trang 95, 3, 20
};
Dictionary<string,int> dict = new
Dictionary<string,int> {
{ “A”, 1 }, { “B”, 2 }
};
Becomes
Becomes
Trang 10What’s The Magic
? What’s The Magic
List<int> nums = <>g initLocal1;
Dictionary<string, int> <>g initLocal2 =
new Dictionary<string, int>();
<>g initLocal2.Add("A", 1);
<>g initLocal2.Add("B", 2);
Trang 11Feature Notes
• The pattern works for any
ICollection<T>
– It calls Add(T) for each element
• It also works for any IEnumerable that
also has an Add method
• Performance: If you have a range
List<int> list = new
List<int>(myEvenNums);
list.AddRange(myOddNums);
Trang 12var e = new Employee();
var dict = new Dictionary<string,List<string>> ();
Becomes
Trang 13Where’s The Magic
? Where’s The Magic
?
• Compiler generated code: (Boring…)
int i = 5;
string s = "Hello";
Employee e = new Employee();
Dictionary<int, List<string>> dict =
new Dictionary<int, List<string>>();
Trang 14Feature Notes
• This is not Microsoft Visual Basic® 6 Dim
• This is not VB6 Variant
• This is not System.Object
• The variable is strongly typed
– But you don’t have to say the type
• Variable must be initialized
– null is not a valid initializer (what type?)
Trang 15Feature Notes
• Adds confusion
– This is not weak typing
• using is a feasible alternative
using Dict = Dictionary<int,
List<string>>;
Dict dict = new Dict();
• Easy to abuse and difficult to understand
var x = a.DoIt(); //What does DoIt
return?
Trang 16Review So Far
Review So Far
• Developer productivity features
• Automatic Properties – Cool, Useful
• Object Initializers – Cool, Useful
• Collection Initializers – Cool, Useful
• Implicit Typing –
Trang 17public string Name;
public int Pay;
Becomes
Trang 18Where’s The Magic
? Where’s The Magic
?
• Compiler-generated code (edited):
internal class AnonymousType0<TName, TPay> {
private readonly TName NameField;
private readonly TPay PayField;
public AnonymousType0(TName Name, TPay Pay) public TName Name { get { return NameField; } } public TPay Pay { get { return PayField; } }
public override string ToString()
public override bool Equals(object o)
public override int GetHashCode()
}
//Continued on the following slide
Trang 19Where’s The Magic
? Where’s The Magic
• ToString renders {Name = …, Pay = …}
– There’s also a [DebuggerDisplay] attribute
• The Equals and GetHashCode implementation
use EqualityComparer<T>.Default for
each field
Trang 20Anonymous From Existing
• Anonymous types can be generated using existing types’ properties:
var partialDetails = new {
Name = person.Name, Age =
person.Age
};
Trang 21Feature Notes
• The generated type is immutable
– Typical for data-holders, and thread-safe
• The generated type is generic
– The same generic type can be reused:
var x = new { Name = “A”, Pay = 15};
var y = new { Name = 5, Pay = 20};
• Provides value semantics
– Equals compares contents (like value types)
– GetHashCode depends on contents (like value types)
Trang 22Feature Notes
• That’s why we need implicit typing!
– var is the only way to access the type
• Passing anonymous types around is hard
– Only through System.Object
– Reflection can reveal properties:
object o = new { … };
foreach (PropertyInfo p in o.GetType()
GetProperties()) { Console.WriteLine(p.GetValue(o));
}
Trang 23• Implicit Typing – Cool, Useful
• Anonymous Types – Cool, Useful
Trang 24Extension Methods
• Challenges:
– How do you add functionality to a sealed class?
– How do you add functionality to an interface without
changing it or its implementors?
• Static methods are the canonical solution
static int ToInt(string
Trang 25What’s The Difference
? What’s The Difference
Becomes
Trang 26Where’s The Magic
? Where’s The Magic
Trang 28Extending” an Interface
//In System.dll
public interface IComparable {
int CompareTo(object obj);
}
//In MyExtensions.dll
namespace MyExtensions {
static class ComparableExtensions {
public static bool IsGreater( this IComparable obj, object other) {
Trang 29using MyExtensions; //Import extensions
BigInt b1 = new BigInt(10000000);
BigInt b2 = new BigInt(10000001);
b1.IsEqual(b2); //CompareExtensions.IsEqual
b1.IsGreater(b2);
//CompareExtensions.IsGreater
Trang 31Partial Methods
• Design Pattern: Template Method
– Provide a protected abstract method
– Call it from the base class
– Derived classes provide implementation
public abstract class Button {
public void Click() {
OnClicking();
//Do some work
OnClicked();
}
protected abstract void OnClicking();
protected abstract void OnClicked();
}
Trang 32Partial Methods
• Design Pattern: Events
– Provide an event (delegate)
– Call subscribers when the event occurs
– Subscribers register, not derive
public sealed class Button {
public void Click() {
Trang 33Partial Methods
• Working with designer-generated classes
– Designer (e.g Visual Studio) spits out a class
– We can’t modify it – changes will be lost
– We don’t want to derive from it – too expensive
– If we don’t extend it – we want zero cost
• This suggests a compile-time mechanism
Trang 34Partial Methods
//In Button.generated.cs
public sealed partial class Button {
public void Click() {
OnClicking();
//Do some work
OnClicked();
}
partial void OnClicking();
partial void OnClicked();
}
//In Button.mycode.cs
partial class Button {
partial void OnClicking() {
//My customized work
}
Trang 35Where’s The Magic
? Where’s The Magic
?
• Only if a partial method implementation is present, the call to it is compiled
public sealed class Button_Partial {
public void Click() {
OnClicking();
Console.WriteLine("Button.Click work"); }
private void OnClicking() {
Console.WriteLine("Button.OnClicking"); }
}
Trang 36Feature Notes
• Partial methods are always private and
cannot return values
• This is an intra -assembly mechanism
– Partial methods can’t be defined in another assembly
• Best performance:
– No virtual call, no derivation, no delegates
• Weak customization:
Trang 38Lambda Expressions
• C# 2.0 Anonymous Methods are a step
towards Lambda Expressions
• Anonymous Methods: Review
Trang 39C# 1.0 – Delegates and Methods
• C# 1.0 is very explicit about delegates:
public delegate string MyConverter(int
Trang 40C# 2.0 – Method Type Inference
• C# 2.0 is less explicit, and generics help:
public delegate TOut MyConverter <TIn,
Trang 42Where’s The Magic
? Where’s The Magic
?
• Compiler-generated code (edited):
private static string Converter (int i) { return i.ToString();
Trang 43Captured Variables
• Interesting patterns arise when we have
closures, including captured variables:
void Foo() {
bool stop = false; //Should be volatile
Thread t = new Thread( delegate() {
while(! stop ) //Do some work
Trang 44Where’s The Magic
? Where’s The Magic
?
• How can the variable be shared?
– Through a class! Compiler generated code (edited):
private sealed class TheClass {
public bool stop ; //=false
public void TheMethod () {
while (! stop ) //Do some work
}
}
//My code:
TheClass c = new TheClass();
Thread t = new Thread( c. TheMethod );
t.Start();
Console.ReadKey();
c.stop = true;
Trang 46Func<int,int> mulByFive = x => mul(x,5);
Func<int,int> square = x => mul(x,x);
//More explicit:
Func<int,int,int> add = (int x,int y) =>
x+y;
Trang 48Lambdas Simplify Code
static class Extensions {
public static List<int> Filter(
this List<int> list,
Trang 49© Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202 Israel
• Beware of capturing side-effects:
for (int i = 0; i < 100; ++i) {
Trang 51Where’s The Magic
? Where’s The Magic
Trang 52The Expression Tree
• At runtime, the tree appears as follows:
ParameterExpressi
on Name=x,
ParameterExpressi
on Name=y,
ParameterExpressi
on Name=y,
BinaryExpression ExpressionType=Multipl
y Type=Int32
BinaryExpression ExpressionType=Multipl
y Type=Int32
Trang 53Feature Notes
• Expression trees turn code into data
• They can be used to dynamically analyze expressions and provide different behavior – LINQ Providers use this extensively
• Expression Tree Visualizer (MSDN®
sample)
– http://tinyurl.com/ExpTreeVis
Trang 55© Copyright SELA Software & Education Labs Ltd 14-18 Baruch Hirsch St Bnei Brak 51202
Language Query Operators
• C# 3.0 includes language query operators
– Facilitate integrated queries on all kinds of data
– Remember the LINQ challenge:
Accessing and integrating non-OO information, while abstracting away its source
– Query operators form the abstraction
– More on this in the LINQ chapters (3-7)
var query = from cust in customers //The source
Trang 56Chapter Summary
• Increased developer productivity
– Implicit typing, initializers, automatic properties,
anonymous types
• Extensibility concepts
– Extension methods, partial methods
• Functional programming concepts
– Lambda expressions, expression trees
• Support for integrated queries (LINQ)
– Language query operators
• C# 3.0 Language Specification: http://tinyurl.com/baoh8