Академический Документы
Профессиональный Документы
Культура Документы
2007-2010
____________________________________________________________________________________________________________________________
LINQ
# C++ .
Anders Hejlsberg' ( #), Microsoft .
LINQ, . LINQ
C# ( VB), ,
Intellisense . : LINQ
,
- .
LINQ (Language Integrated Queries) .
(, ) ,
. , LINQ,
SQL, XQuery, , . ,
: C++, C#, Java, PL/I, Ruby, Python . ,
.
, .
: A = <R, O>, R
, O . , = <R, O>, R
, O : { +, , / , }.
, - ,
: C = <D, M>, D , M ,
.
(, ,
). (,
, , ).
( , -)
, . ,
,
, -.
, , . , C#, , . LINQ
- (Lambda Expressions) (Expression Trees) ,
.
. (Expression),
, C#. ,
-,
.
LINQ : (), Web-service,
XML-, . , LINQ ,
IEnumerable<T>. LINQ. ,
LINQ , .
IEnumerable<T> : IEnumerator<T> GetEnumerator(),
50- , ,
extension methods (). Enumerable
. :
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
All<T> , - - .
Cast<T> .
Concat<T> (concatenates) .
Contains<T> , - .
ElementAt<T> .
Except<T> , .
GroupBy<TSource,TKey> .
Intersect<T> , .
Join<TOuter, TInner, TKey, TResult> (correlates)
.
OrderBy<TSource, TKey> .
Range(int start, int count) .
Select<TSource, TResult> .
ToArray<T> .
ToDictionary<TSource, TKey> , .
ToList<T> generic- .
Where<T> .
Union<T> .
: T-SQL, PL/SQL . .
LINQ-, (LINQ queries)
(native) SQL. , LINQ-
. , LINQ, LINQ to SQL LINQ TSQL, , ,
SQL.
IQueryable<T>, IEnumerable<T>.
LINQ , . <T>
. , ,
. IQueryable<T> . ,
Person : Student Professor,
T Person, Student Professor.
C#
LINQ C#, C#, 3.0.
(.NET Framework 3.5) LINQ . Visual Studio 2008
, C#
. (.Net Framework 1.0) C# 77 . .
abstract
as
base
bool
break
byte
case
catch
char
checked
class
const
continue
decimal
default
delegate
do
double
else
enum
event
explicit
extern
false
finally
fixed
float
for
foreach
goto
if
implicit
in
int
interface
internal
is
lock
long
namespace
new
null
object
operator
out
override
params
private
protected
public
readonly
ref
return
sbyte
sealed
short
sizeof
stackalloc
static
string
struct
switch
this
throw
true
try
typeof
uint
ulong
unchecked
unsafe
ushort
using
virtual
volatile
void
while
ascending
by
descending
equals
from
get
global
group
into
join
let
on
orderby
partial (type)
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
partial (method)
remove
select
set
var
yield
value
, . , where
(generic) ,
LINQ ( ) .
?
Nullable, (, decimal?), C#
LINQ, . LINQ- Nullable-
, ,
. .
int? i = null;
C# ( ). null
(value) , .
. , . ,
?? ( ). null.
, ??.
string
s = null,
test = s ?? "String s == null";
Console.WriteLine (test);
s = "Set of C# Keywords";
test = s ?? "String s == null";
Console.WriteLine (test);
C#
, LINQ,
C#, . , .
.
public decimal Salary { get; set; }
(object initializers). , :
public class Person
{
public string Name { get; set; }
public DateTime Birth { get; set; }
public decimal Salary { get; set; }
}
Person, :
Person alex = new Person(){ Name = "Alex", Birth = new DateTime(1994, 2, 26), Salary = 10000m };
, Person .
.
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
.
, ,
, , . :
var s = "This is a string of characters";
var a = new[] { 1, 2, 3, 4 };
s a . string,
int[]. new[]. ,
( managed heap). ( C# 2.0) : int[] a = new int[] { 1, 2, 3, 4 };.
var.
CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
foreach (var v in cultures)
Console.WriteLine("{0,52} {1}", v.EnglishName, v.IetfLanguageTag);
v CultureInfo. :
InstalledFontCollection collection = new InstalledFontCollection();
foreach (var font in collection.Families)
Console.WriteLine(font.Name);
font FontFamily. .
MSDN, , , Google. ,
MSDN .
, :
public string Name
{
get { return name; }
set { name = value; }
}
, ( name
), ,
. , DataBinding .
, nonsense. ,
.
, ,
, .
class Stud
{
public string Name { get; set; }
public List<int> Marks { get; set; }
}
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
. get set
. LINQ,
MSDN, .
: " ?" :
Asymmetric Accessor Accessibility. :
public string Name { get; private set; }
public string Name { get; internal set; }
, Name , ,
. , .
(internal set) , Name ,
() Assembly.
() .
default- .
Person alex = new Person(){ Name = "Alex", Birth = new DateTime(1994, 2, 26), Salary = 10000m };
, :
var persons = new[]
{
new Person(){ Name = "Bale", Birth = new DateTime(1981, 3, 26), Salary = 10000m },
new Person(){ Name = "Dale", Birth = new DateTime(1974, 1, 11), Salary = 15000m },
new Person(){ Name = "Gail", Birth = new DateTime(1964, 6, 12), Salary = 20000m }
};
, . (infered) .
, ( C#). -,
Person . :
Person[] persons =
{
new Person("Alex", new DateTime(1981, 3, 26), 10000m),
. . .
}
:
Person persons;
persons = new Person[]
{
new Person("Alex", new DateTime(1981, 3, 26), 10000m),
. . .
}
Generic-
. (
- ). , delegate,
( ). ( ),
. , .
, :
.
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
// System.Core.dll
void() Action.
. Action.
class Program
{
static void Inform() { Console.WriteLine(Environment.MachineName); }
static void Say() { Console.WriteLine("I am an Action delegate"); }
static void Main()
{
Action a = Inform;
a();
a += Say;
a();
}
}
Action , System.Core.
a Action Inform. , Inform
Action. a Action.
: a(); Inform();.
a += Say; a Say.
a(); : Inform Say. ,
(InvocationList) ( ), :
Inform Say. Action ( ).
( ) :
class TestDelegate
{
public void Test()
{
Action a = new Action(Say);
a += new Action(Do);
Delegate[] dd = a.GetInvocationList();
Console.WriteLine("Testing Delegate's InvocationList\n");
int i = 0;
foreach (var d in dd)
Console.WriteLine("{0}. Method = {1}, CallingConvention = {2}, Target = {3}, Returns = {4}",
(++i).ToString(), d.Method.Name, d.Method.CallingConvention, d.Target,
d.Method.ReturnType.Name);
}
void Say() { Console.WriteLine("Saying"); }
void Do() { Console.WriteLine("Doing"); }
}
class Program { static void Main() { new TestDelegate().Test(); } }
, .
Testing Delegate's InvocationList
1. Method = Say, CallingConvention = Standard, HasThis, Target = Test.TestDelegate, Returns = Void
2. Method = Do, CallingConvention = Standard, HasThis, Target = Test.TestDelegate, Returns = Void
System Action<T>, (,
generic). , , () .
public delegate void Action<T> (T obj); // System.Core.dll
Action<T> , C++.
delegate template. .. generic,
(. http://www.intuit.ru/department/pl/csharp/).
, generic- . Action
T. , Action<int>
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
Action<> ,
.
public delegate void Action<T1, T2> (T1 arg1, T2 arg2);
T1 T2. .
Program SaveImage, Action<string, byte[]>.
static void SaveImage(string file, byte[] data) { File.WriteAllBytes(file, data); }
System.Core.dll Action<>.
void- . , ,
. Action<> void, 0 4 . ,
. Note! 2010 Action<>
void-, 0 16 .
generic- Func<>
System.Core.dll Func<>,
, . Action<>,
. ( , ).
.
public delegate TResult Func <T,TResult> (T arg);
generic- , Func
, , T
TResult. , () (TResult)
, .
() (T TResult),
, , ( ).
( ), (), :
Func<double, double> pFunc = Math.Sin;
// pFunc ,
Console.WriteLine (pFunc(1.5)); // pFunc. : 0,997494986604054
pFunc = Math.Sqrt;
// pFunc ,
Console.WriteLine (pFunc(1.5)); // : 1,22474487139159
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
System Func<>. .
delegate TResult Func <T, U, TResult> (T a, U b);
(T, U).
TResult. ,
(Anders Hejlsberg Don Box) Func<>
. Note! 2010 Func<>
, 0 16 .
, .
. ,
MyFunc<> ( ). :
public delegate TResult MyFunc<T, U, V, W, X, TResult>(T t, U u, V v, W w, X x);
static double StupidFunc(int t, int u, int v, int w, string x)
{
return t + u + v + w + double.Parse(x);
}
.
static float Half (int x) { return x/2.0f; }
static void Main()
{
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
Console.WriteLine (Half (3)); // 1,5
Console.WriteLine (Half (-3)); // 1,5
}
,
. , ,
, ( C# ).
, ( ), .
, PL/I Pascal
. ,
. C#.
( C# 2.0) ().
.
delegate float FuncType (int x);
//
, , . ,
delegate ( ). ,
Main. .
generic- (. Func<>), .
static void Main()
{
Func<int, float> Half = delegate(int x) { return x / 2.0f; };
Console.WriteLine (Half (3));
}
FuncType , Func<>,
System. Func
(int, float).
Lambda Expressions
. :
delegate(int x) { return x / 2.0f; };
:
x => x / 2.0f; // -
. , return.
x . .
static void Main()
{
Func<int, float> Half = x => x / 2.0f;
Console.WriteLine (Half(3));
}
// -
, . , - ,
.
- . ,
.
( ). x => x / 2.0f :
delegate(int x) { return x / 2.0f; };
, -. :
delegate float MyFunc (int x);
static void Main()
//
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
{
MyFunc Half = x => x / 2.0f; // -
Console.WriteLine(Half(3));
}
- . , .
x => x / 2.0f;
(int x) => x / 2.0f;
(int x) => { return x / 2.0f; };
,
Action Func, , .
int n = 0;
Func<int> Go = () => n++;
Console.WriteLine(Go() + ", " + Go() + ", " + Go() + ", " + Go());
__________________________________________________________________
n = 0;
Action Do = () => Console.Write(n+++", ");
Do(); Do(); Do(); Do();
Action , .
Action Do. Do, -,
n, .
,
. Func Action.
( n++).
-.
, , , -,
, .
().
, print Action.
Console.WriteLine("\n\nTest Action<string>");
Action<string> print = c => Console.WriteLine(c);
print("Hi from Action<string>");
___________________________________________________________________________
Console.WriteLine("\n\nEnum strings ");
string[] names = { "Microsoft", "creates", "technologies", "very", "quickly" };
Array.ForEach<string>(names, print);
___________________________________________________________________________
Console.WriteLine("\n\nLooking for code");
string[] codes = {
"Penal code", "Traffic code", "Morse code", "Genetic code",
"Coding rules", "Coding conventions", "Code names",
"Code of behaviour", "Code transmission", "Codex book", "Native code",
"Pseudocode", "Spaghetti code", "Portable code", "Native code",
"Scan code", "Access code", "Bar code", "Character code", "Country code"
};
Array.ForEach<string>(codes.Where(c => c.Contains("code")).ToArray(), print);
.
const string text =
@"Many types implement IEnumerable. Some of these types implement public
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
members that are identical to IEnumerable. For instance, if you have a
type MyList that implements a Where method (as does IEnumerable<T>),
invoking Where on MyList would call MyLists implementation of Where.
By calling the AsEnumerable() method first and then calling Where,
you invoke IEnumerables Where method instead of MyLists.";
List<string> words = new List<string>();
words.AddRange (text.Split());
Console.WriteLine("\n\nTest Query Where:");
var where = words.Where(c => c == "Where");
foreach (var s in where)
Console.Write(s + ", ");
Intellisense Where.
, IEnumerable<string>. ,
, var ( ).
IEnumerable<string> where = words.Where(c => c == "Where");
. , -:
c => c == "Where"
T,
:
var where = words.Where(c => c == "Where");
"" .
Func<string, bool> func = c => c == "Where"; // -
IEnumerable<string> where = words.Where(func); // ( )
Where C#,
extension method ( ). .
, var-
var . , . ,
, , -
.
var song = new { Artist = "Ray Charles", Song = "Alexander's Ragtime Band" };
, ( ) Artist Song.
( ) .
song , var - .
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
. , object[], .
, ToString() .
foreach (var item in songs)
Console.WriteLine(item);
.
{ Artist = Low Rowles, Song = Cheek to cheek }
{ Artist = Ray Charles, Song = Alexander's Ragtime Band }
{ Artist = Frank Sinatra, Song = September In the Rain }
. JSON (Java Scrip Object Notation),
RSS. RSS (Really Simple Syndication)
XML-, Web- ,
: (news headlines), (blog posts).
yield
yield [jild] , ,
.
( ). .
static void Main()
{
string[] words = { "class", "const", "continue", "decimal" };
IEnumerable<string> query = GetWords (words);
foreach (string w in query)
Console.WriteLine (w);
}
static IEnumerable<string> GetWords (string[] words)
{
foreach (string w in words)
yield return w;
}
GetWords ,
IEnumerable<string>. ( ).
query. , ,
, . , . ,
yield.
GetWords, (F5).
F11 ( ) , GetWords.
, query ( , foreach
). , ? , .
IEnumerable List .
yield .
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
, , GetWords ( yield)
, , ,
( query). ,
, .
yield. Program . yield. ,
, .
static IEnumerable<int> Powers (int n)
{
for (int i = 1, d = 0; i < (1<<n); d = i)
yield return i += d;
}
, Powers 10.
Main .
Console.WriteLine ("\n\nPowers\n");
foreach (var v in Powers(10))
Console.Write (v + ", ");
, , , IEnumerable<int>.
yield .
(F11) , Powers , .
Generic-
() .
, ArrayList .
: / - (boxing-unboxing).
. generic- List<type>.
( type) ,
type. -
.
(generic) .
, , . ,
, C++. C#
, -.
-, . ,
List<Person> List<T>. ,
List<Person> System.Collections.Generic.
(generic) BinaryTree<T>.
, .
T BinaryTree<T> , .
generic- Node<T> . Node<T>
, ( T),
( ) , .
BinaryTree<T> root.
public class BinaryTree<T> where T : IComparable<T>
{
public class Node<T> where T : IComparable<T>
{
public T data;
public Node<T> left, right;
public Node(T data) { this.data = data; }
}
Node<T> root;
public IEnumerable<T> OrderedSet { get { return GetAll(root); } }
void Add(T item, ref Node<T> node)
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
{
if (node == null)
node = new Node<T>(item);
else if (item.CompareTo(node.data) < 0)
Add(item, ref node.left);
else
Add(item, ref node.right);
}
IEnumerable<T> GetAll(Node<T> node)
{
if (node.left != null)
{
foreach (T item in GetAll(node.left))
yield return item;
}
yield return node.data;
if (node.right != null)
{
foreach (T item in GetAll(node.right))
yield return item;
}
}
void Print(Node<T> item, int depth, int offset)
{
if (item == null)
return;
Console.CursorLeft = offset;
Console.CursorTop = depth;
Console.Write(item.data);
if (item.left != null)
Print("/", depth + 1, offset - 1);
Print(item.left, depth + 2, offset - 3);
if (item.right != null)
Print("\\", depth + 1, offset + 1);
Print(item.right, depth + 2, offset + 3);
}
void Print(string s, int depth, int offset)
{
Console.CursorLeft = offset;
Console.CursorTop = depth;
Console.Write(s);
}
public void Add(T item) { Add(item, ref root); }
public void AddRange(params T[] items)
{
foreach (var item in items)
Add(item);
}
public void Print() { Print (root, 0, Console.WindowWidth / 2); }
}
where T : IComparable<T> ,
BinaryTree<T>, , IComparable.
,
. ,
, , BinaryTree<T>. ,
T.
, ,
. ,
.
static void TestBinaryTree()
{
Console.Clear ();
string line = new string('\u2500', 22);
Console.WriteLine(line + "Test BinaryTree<int>\nPress any key.");
BinaryTree<int> tree = new BinaryTree<int>();
tree.AddRange(16, 8, 24, 4, 12, 20, 28, 2, 6, 10, 14, 18, 22, 26, 30, 1, 3, 5, 7, 9, 11,
13, 15, 17, 19, 21, 23, 25, 27, 29, 31);
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
tree.Print();
Console.WriteLine("\n\nNot formatted BinaryTree<int>\n");
foreach (var item in tree.OrderedSet)
Console.Write(item + ", ");
}
Print , , .
.
GetAll yield
generic- IEnumerable<T>.
OrderedSet BinaryTree<T>
, .
BinaryTree<T> , ,
, .
. , ,
, .
, yield.
, yield .
generic- List<T>.
, .
. ,
.
public List<T> FindPath (T item)
{
path.Clear ();
FindPath (item, root);
return path;
}
FindPath List<T>,
item.
. , Add,
(. CompareTo).
void FindPath (T item, Node<T> node)
{
if (node != null)
{
path.Add (node.data);
if (item.CompareTo (node.data) < 0)
FindPath (item, node.left);
else
FindPath (item, node.right);
}
}
TestBinaryTree FindPath, .
Console.WriteLine ("\n\nTesting FindPath(21)\n");
foreach (var item in tree.FindPath (21))
Console.Write (item + "->");
(extension methods)
, C# . .
, sealed, ,
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
, String. JScript. ,
Anders Hejlsberg' ( C#), C#.
, Object ,
(public class MyObject : Object {}),
Object. .NET Framework 1.0 .
, . extension-.
Extension method: A static method that can be invoked by using instance method syntax. In effect, extension methods
make it possible to extend existing (and constructed) types with additional methods.
, .
, instance methods, ,
, : obj.Method(). class methods,
, , : Class.Method().
this, , . ,
, (
). .
. this, ( this- ), ,
. extension-, ,
, . , extension
method' ,
, , .
( extension-) ,
.
, , .
String , ,
? , -
.
public static string TrimAll(this string s);
, , (this string s) ,
String. , extension-
String. . .
public static class Extender
//
{
public static string TrimAll(this string s) // this
{
return new Regex(@"\s{2,}").Replace(s.Trim(), " ");
}
}
(,
Program). Extender.
Extender , Program. .
static void TestTrimAll()
{
var text = " This text
has
many
extra
Console.WriteLine(text.TrimAll());
}
static void Main()
{
Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Clear();
TestTrimAll();
}
spaces
";
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
(F11). , ,
. , this .NET Framework 3.5 extension. .
. , char c ( ), .
, Object extension- IsIn,
.
c . Extender .
// ( col)
public static bool IsIn (this object o, IEnumerable col)
{
foreach (var v in col)
{
if (v.Equals(o))
return true;
}
return false;
}
. this , IsIn .
, . object.
, o.
Program
static string line = "\n" + new string('\u2500', 60) + "\n";
Program TestIsIn,
Object, Main .
static void TestIsIn()
{
Console.WriteLine(line + "Test IsIn");
var teams = new string[] { "Spartak", "Zenith", "Locomotive" };
bool b = "Zenith".IsIn(teams);
Console.WriteLine("Zenith is in teams array: " + b);
var ints = new[] { 1, 2, 3, 4 };
Console.WriteLine("3 is in integer array: " + 3.IsIn(ints));
var date = new DateTime(2009, 1, 2);
var date2 = DateTime.Now.AddMilliseconds(-1);
var dates = new[] {
new DateTime(2009, 1, 3), new DateTime(2005, 2, 6),
date, DateTime.Now, date2
};
Console.WriteLine("date {0:d} is dates: {1}", date, date.IsIn(dates));
Console.WriteLine("date {0:d} is in dates: {1}", DateTime.Now, DateTime.Now.IsIn(dates));
Console.WriteLine("date {0:d} is in dates: {1}", date2, date2.IsIn(dates));
}
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
, , IList,
object string.
public static class Dumper
{
// ======= extension- this
public static void Dump(this IList list) // IList
{
foreach (object o in list)
o.Dump();
}
public static void Dump(this object o)
{
PropertyInfo[] properties = o.GetType().GetProperties();
foreach (PropertyInfo p in properties)
{
try
{
Console.WriteLine(string.Format("{0} --> {1}", p.Name, p.GetValue(o, null)));
}
catch
{
Console.WriteLine(string.Format("{0} --> {1}", p.Name, "unknown"));
}
}
}
public static void Show(this string what) { Console.WriteLine(what); }
}
.
string:
Console.WriteLine("\nTest Extension Method");
string s = "Now all the strings are extended with Dump and Show";
s.Dump();
s.Show();
, .NET Framework, .
, . Dump
song.
Console.WriteLine("\nDump object:");
var song = new { Artist = "Ray Charles", Song = "Alexander's Ragtime Band" };
song.Dump();
, Dump, .
Artist --> Ray Charles
Song --> Alexander's Ragtime Band
- Show song?
Dump(this IList) .
, IsIn song.
Console.WriteLine("\nDump array of objects:");
var songs = new[]
{
new { Artist = "Low Rowles", Song = "Cheek to cheek" },
song,
new { Artist = "Frank Sinatra", Song = "September In the Rain" }
};
songs.Dump();
Console.WriteLine ("song.IsIn(songs): " + song.IsIn(songs));
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
public static int? LengthOrNull (this string s) { if (s == null) return null; else return s.Length; }
.
string s = null;
int? len = s.LengthNull();
Console.WriteLine("String: '{0}' has length: {1}", s, len ?? 0);
s = "LengthNull extends class String";
len = s.LengthNull();
Console.WriteLine("String: '{0}' has length: {1}", s, len ?? 0);
? ??. , ,
LINQ. Main .
ArrayList tList = new ArrayList(teams);
var q = from s in teams select s;
Console.WriteLine("\n\nTeams List has {0} items", q.Count<string>());
foreach (string s in q)
Console.Write(s + ", ");
Extension- Enumerable
, , - .
System.Linq (extension methods).
. ,
, IEnumerable<T>.
, , : Array, ArrayList, Stack, Queue,
Hashtable, SortedList IEnumerable. generic-: Stack<T>, Queue<T>, List<T>,
LinkedList<T>, Dictionary <TKey, TValue>, Collection<T>,
generic-, IEnumerable<T>.
.
LINQ extension-,
System.Linq.Enumerable. (this)
IEnummerable<T>,
.
,
,
. , , customers.
var customers = new[]
{
new { FName="Arthur", LName="Conan Doyle", Phone="323-3232", City="Edinburgh", Addr="Stonyhurst 32" },
new { FName="Sherlock", LName="Holmes", Phone="555-5555", City="London", Addr="Baker st 221B" },
new { FName="John", LName="Watson", Phone="555-5555", City="London", Addr="Baker st 221B" }
};
customers.
var query = customers.Select(c => new { c.LName, c.Addr });
.
foreach (var item in query)
Console.WriteLine(item);
LINQ-:
. . . new { c.LName, c.Addr };
. Customer,
. . extension- Select ( ) ,
, , (c.LastName, c.Addr).
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
.
tuple, : . n-tuple.
"n-" ( n ).
<Anonymous Type>.
Autos . ,
(infered) ( query). .
Enumerable.WhereSelectArrayIterator<<>f__AnonymousType1<string,string,string,string,string>,
<>f__AnonymousType2<string,string>> . . .
, C# var.
. , ,
.
.
Generic- print , .
Generic- pred , .
Extension generic- FindAll , (fib),
, print.
Extension generic- ForEach , ,
, pred.
, .
.
pred, Predicate<int> ( ), -.
Fibonacci, extension- FindAll.
print Action<int> -,
, extension- ForEach.
, generic- List<int>. ,
.
Console.WriteLine("\nTest FindAll for List<int>");
List<int> list = new List<int>(fib);
list.FindAll(predicate).ForEach(print);
Enumerable
(, IEnumerable<T>). Queryable
, IQueryable <T>.
() 14 (). .
N
(Filtering)
Where, OfType
(Projection)
Select, SelectMany
(Partitioning)
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
4
(Join)
Join, GroupJoin
(Concatenation)
Concat
(Ordering)
(Grouping)
GroupBy, ToLookup
(Set)
(Conversion)
10
(Equality)
SequenceEqual
11
12
(Generation)
13
(Quantifiers)
14
(Aggregate)
extension- Where,
. IEnumerable<T>
. :
public static IEnumerable<T> Where<T>(this IEnumerable<T> src, Func<T,bool> pred);
Where , IEnumerable<string>.
.
q ( query). - c=>c.Contains("oo") . , c.Contains("oo") .
Func<T,bool>. Contains bool,
. -
, "oo".
extension- Where :
public static IEnumerable<T> Where<T>(this IEnumerable<T> src, Func<T,int,bool> pred);
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
T , string.
(s.Length <= i) bool .
, ,
, .
- ( ).
.
Name: Length: Pos:
____________________
four
4
1
five
4
2
six
3
3
seven
5
4
eight
5
5
nine
4
6
. q. .
Enumerable.WhereIterator<string>, .
var.
, Where Enumerable. ,
, : ,
, , (be enumerated).
foreach. :
var q = digitNames.Where((s, i) => s.Length <= i);
. ()
extension. (lazy evaluation).
, , , , yield return. extension- , ,
. , extension-.
var songs = new[]
{
new { Artist="Low Rowles", Date=new DateTime(1965,3,28), Song="Cheek to cheek" },
new { Artist="Ray Charles", Date=new DateTime(1952,6,11), Song="Alexander's Ragtime Band" },
new { Artist="Frank Sinatra", Date=new DateTime(1958,6,7), Song="Emily" },
new { Artist="Frank Sinatra", Date=new DateTime(1956,3,28), Song="September In the Rain" },
new { Artist="Frank Sinatra", Date=new DateTime(1957,4,12), Song="It started all over again" },
new { Artist="Nat King Cole", Date=new DateTime(1956,11,29), Song="Impossible" },
new { Artist="Dinah Washington", Date=new DateTime(1975,9,21), Song="Call Me Irresponsible" },
new { Artist="Peggy Lee", Date=new DateTime(1978,5,9), Song="As Time Goes By" }
};
var q = songs
.Select(s => new { len = s.Song.Length, s.Song,
.Where(s => s.Date > DateTime.Now.AddYears(-60)
.OrderBy(s => s.len)
.Select(s => new { s.Song, Date = s.Date, s.len
int k = 0;
foreach (var s in q)
Console.WriteLine("{0}. {1}, {2,-2}, {3}", ++k,
s.Artist, s.Date })
)
});
s.Date.ToShortDateString(), s.len, s.Song);
, yield
return break. yield return, ,
.
,
.
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
(Eager Evaluation)
, ( " "),
ToArray()
string[] oo = words.Where(c => c.Contains("oo")).ToArray();
Where , .
. ToArray() ToArray<T>() IEnumerable<T>.
. , .
string[] oo = words.Where(c => c.Contains("oo")).ToArray<string>();
generic-.
extension- ToList() ToList<string>().
List<string> ooList = words.Where(c => c.Contains("oo")).ToList();
Select SelectMany
, Select SelectMany,
. .
Select SelectMany .
(selector)
.
. Where , Select SelectMany .
, , , ,
. SelectMany ,
SelectMany .
. ,
. Stud
.
class Stud
{
public string Name { get; set; }
public int[] Marks { get; set; }
}
.
Stud[] studs =
{
new Stud { Name="John Best", Marks = new[]{ 5, 5, 5, 5, 5 } },
new Stud { Name="Joy Amore", Marks = new[]{ 4, 4, 3, 4 } },
new Stud { Name="Jim Lowson", Marks = new[]{ 3, 3, 2 } },
};
Select.
var q = studs.Select (s => s.Marks); // q - IEnumerable<int[]>
, IEnumerable<int[]>. ,
,
int[]. ( , q)
var. T IEnumerable<T>.
- s => s.Marks , int[].
, q.
, , .
int i=0;
Console.WriteLine ("Student\t\t Mark\n" + new string('\u2500', 31));
foreach (var array in q)
{
Console.Write (studs[i++].Name + ":\t ");
foreach (int m in array)
Console.Write (m + ", ");
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
Console.WriteLine();
}
List<int>.
IEnumerable<List<int>>.
Stud int[] Marks { get; set; } List<int> Marks { get; set; }
: Marks = new[] { 5, 5, 5, 5, 5 } }, Marks = new List<int>{ 5, 5, 5, 5, 5 } }.
.
, Select Stud .
, SelectMany.
, IEnumerable<int>.
() .
var query = studs.SelectMany(s => s.Marks); // q - IEnumerable<int>
Console.Write ("\nAll the Marks: ");
foreach (var m in query)
Console.Write (m + ", ");
, SelectMany , one-to-many.
( ).
Select SelectMany. , , Where,
, Func<T,int,S>. .
static void TestNumbers()
{
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var q = numbers.Select ((n, i) => new { Value = n, InPlace = (n == i) });
Console.WriteLine("Number
In-place?\r\n" + new string('\u2500', 20));
foreach (var v in q)
Console.WriteLine("{0,-10} {1}", v.Value, v.InPlace);
}
Select , .
()
.
: int Value, bool InPlace. InPlace true
, . : 3, 6, 7
(, 5 ). , - (n,
i), Where, .
var q . ,
IEnumerable<<>f__AnonymousType0<int,bool>>.
LINQ, C#, var.
. , .
v = { Value = 5, InPlace = false }
extension-.
Select, . Select
OrderBy, c.
string .
static void TestSelectAnonimous()
{
string[] words = { "abstract", "false", "finally", "null", "for", "if", "object", "Freeloader" };
var q = words.Select((c, i) => new { ID = i + 1, Length = c.Length, Word = c })
.OrderBy(c=>c.Length);
foreach (var v in q)
Console.WriteLine(v);
}
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
, Single SingleOrDefault .
Where, .
.
Console.WriteLine(ia.Where(c => c % 4 == 0).Single());
int? divBy7 = ia.Where(c => c % 7 == 0).SingleOrDefault();
Console.WriteLine(divBy7 == null ? "null" : divBy7.ToString());
Extension- OrderBy , .
public static IOrderedEnumerable<T> OrderBy<T, TKey>(this IEnumerable<T> source,
Func<T, TKey> keySelector);
Program .
static Person[] personList =
{
new Person{Name = "Paul", Birth = DateTime.Now.AddYears(-15), Status = 1 },
new Person{Name = "Alex", Birth = DateTime.Now.AddYears(-45), Status = 17 },
new Person{Name = "Peter", Birth = DateTime.Now.AddYears(-50), Status = 21 },
new Person{Name = "John", Birth = DateTime.Now.AddYears(-35), Status = 8 },
new Person{Name = "Zorro", Birth = DateTime.Now.AddYears(-25), Status = 8 },
new Person{Name = "Alex", Birth = DateTime.Now.AddYears(-15), Status = 12 },
new Person{Name = "Alex", Birth = DateTime.Now.AddYears(-45), Status = 12 }
};
extension- OrderBy .
OrderBy personList -,
.
static void TestOrderBy()
{
var q = personList.OrderBy(c => c.Status);
Console.WriteLine("\nPersons ordered by Status:");
foreach (var p in q)
Console.WriteLine("{0} {1} {2}", p.Name.PadRight(7),
p.Birth.ToShortDateString(), p.Status);
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
}
OrderBy OrderByDescending.
. , OrderBy :
public static IOrderedEnumerable<T> OrderBy<T, TKey>(this IEnumerable<T> source,
Func<T, TKey> keySelector, IComparer<TKey> comparer);
: generic- keySelector
. , generic- IComparer<T>. ,
, .
public class NameComparer : IComparer<Person>
{
public int Compare(Person p, Person q)
{
int n = p.Name.CompareTo(q.Name),
b = p.Birth.CompareTo(q.Birth),
s = p.Status.CompareTo(q.Status);
return n != 0 ? n : b != 0 ? b : s;
}
}
AgeComparer, , ,
. , StatusComparer, , ,
. . , ,
OrderBy .
q = personList.OrderBy (c => c, new NameComparer());
Console.WriteLine("\nPersons ordered by Name, Age, Status:");
foreach (var p in q)
Console.WriteLine("{0} {1} {2}", p.Name.PadRight(7), p.Birth.ToShortDateString(), p.Status);
q = personList.OrderBy (c => c, new AgeComparer());
Console.WriteLine("\nPersons ordered by Age, Name, Status:");
. . . . .
, *Comparer, .
, OrderBy, extension- ThenBy.
q = personList.OrderBy(c=>c.Status).ThenBy(c=>c.Name).ThenBy(c=>c.Birth);
ThenByDescending.
extension- Aggregate,
- .
double[] doubles = { 1, 2, 3, 4, 5 };
double product = doubles.Aggregate((a, b) => a * b);
Console.WriteLine ("5!: " + product);
5, , .
Aggregate ( ). (a, b)
( , doubles),
(a*b) product. Aggregate
,
. :
double sum = 10000;
int[] withdrawals = { 2000, 1000, 4000, 5000 };
double res = withdrawals.Aggregate(sum, (b, s) => s <= b ? b - s : b);
Console.WriteLine("Ending balance: {0}", res);
withdrawals .
-, , ,
, .
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
b ( ).
s - ( withdrawals).
Union () ,
Intersect ,
Except .
Count .
int[] u = { 1, 2, 3, 4, 5, 6 },
v = { 4, 5, 6, 7, 8, 9, 10 };
var both = u.Intersect(v);
Console.WriteLine("\nu.Intersect(v)");
foreach (var n in both)
Console.Write(n + ", ");
var r = both.Except(v.Intersect(u));
Console.WriteLine("\nu.Intersect(v).Except(v.Intersect(u)).Count():
Console.WriteLine("\nu.Union(v).Except(u)");
foreach (var n in u.Union(v).Except(u))
Console.Write(n + ", ");
" + r.Count());
, u.Intersect(v) v.Intersect(u) ,
u.Union(v).Except(u) ,
u v.
- Enumerable,
System.Linq. ,
extension methods,
C#.
, , .
Where,
C#: from, where select. MSDN where select C# (
Where Select) clause ().
- ,
LINQ.
, , , LINQ.
, - , .
Func<>.
, . , :
, Func<T, TResult>,
T,
LINQ-, , , extension- Where (Func<T, TResult>),
IEnumerable<T>, ,
, .
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
. ,
Where, IsLeapYear,
.
static bool IsLeapYear(int y)
{
bool res = y % 4 == 0 && y % 100 != 0 || y % 400 == 0;
return res;
}
static void TestLeapYear()
{
Console.WriteLine("\nTest Verbose version of IsLeapYear Query");
var years = new int[] { 2000, 2001, 2002, 2003, 2004, 2005 };
Func<int, bool> tester = IsLeapYear;
IEnumerable<int> result = years.Where<int>(tester);
IEnumerator<int> en = result.GetEnumerator();
while (en.MoveNext())
Console.WriteLine(en.Current);
}
,
. , ,
. , ,
extension- .
result = years.Where(c => c % 4 == 0 && c % 100 != 0 || c % 400 == 0); //
foreach (var v in result)
Console.WriteLine(v);
, . extension. C , C#
.
from x in , x
( ). (alias)
. , from extension-.
, , SQL-, select from .
, Intellisense.
( from x in ), , ,
. .
. extension-
Select, select.
. :
var q = Enumerable.Range(20,10).Select(n => new { Value = n, Mult3 = n % 3 == 0 });
, - =>. ,
-, select (from in).
q = from n in Enumerable.Range(20, 10)
select new { Value = n, Mult3 = n % 3 == 0 };
.
Console.WriteLine("\nNumber
Mult3?\r\n" + new string('\u2500', 21));
foreach (var v in q)
Console.WriteLine("{0,-10} {1}", v.Value, v.Mult3);
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
Position,
Name. extension- .
q = people.OrderByDescending (p => p.Position).ThenBy (p => p.Name);
, extension-
, , : from, select, orderby, descending,
.
3.
.
Test grouping
Group # 1:
Group # 2:
Group # 0:
1, 4, 7, 10,
2, 5, 8,
3, 6, 9,
, Key.
. gr ( , ).
. var : IEnumerable<IGrouping<int,int>>.
, : Console.WriteLine(gr.GetType().Name);, :
"GroupedEnumerable`3". .
: gr.GetType() == typeof(System.Linq.IGrouping<int, int, int>),
true. .
. g. . IGrouping<int, int>.
, extension- GroupBy.
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
gr = numbers.GroupBy (n => n % 3);
//
, extension- ForEach.
Console.WriteLine("\nTest grouping (Extension)");
Array.ForEach (gr.ToArray(), x =>
{
Console.Write("\n Group # " + x.Key + ": ");
Array.ForEach (x.ToArray(), y => Console.Write(y + ", "));
});
ForEach .
gr, IEnumerable<IGrouping<int,int>>,
Array. extension- ToArray.
g, IGrouping<int,int>,
Array. extension- ToArray.
- ( ) , . ,
, - y => Console.Write(y + ", ").
- . , -
- .
Console.Write("\nTest (x, y) => x + y: ");
Func<int, int, int> lambda = (x, y) => x + y;
Console.WriteLine (lambda(3, 4));
Func<int, Func<int, int>> curry = x => y => x + y;
Console.Write ("Test x => y => x + y: ");
Console.WriteLine (curry(3)(4));
IQueryable <T>
, LINQ- ,
IEnumerable<T>. , IQueryable<T>.
public interface IQueryable<out T> : IEnumerable<T>, IQueryable, IEnumerable
T . , T ,
T. , IQueryable<T>, .
, .
, (expression trees)
, LINQ-.
IQueryable ( IEnumerable) .
IEnumerator GetEnumerator()
IQueryProvider , ,
IQueryable-. IQueryProvider :
IQueryable CreateQuery(Expression expression);
object Execute <TResult>(Expression)
, Execute <TResult>(Expression)
.
, .
.
COM Interop
, C# 4.0 COM
Interop. Microsoft Office (Excel Word).
( ) Office API.
using
using
using
using
System;
System.Collections.Generic;
System.Drawing;
Excel = Microsoft.Office.Interop.Excel;
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
using Word = Microsoft.Office.Interop.Word;
public class Account
{
public int ID { get; set; }
public double Balance { get; set; }
}
public class Program
{
static void Main()
{
var checkAccounts = new List<Account>
{
new Account { ID = 345, Balance = 541.27 },
new Account { ID = 123, Balance = -127.44 }
};
Action<Account, Excel.Range> display = (account, cell) =>
{
cell.Value = account.ID;
cell.Offset[0, 1].Value = account.Balance;
if (account.Balance < 0)
{
cell.Interior.Color = ColorTranslator.ToOle(Color.FromArgb(255,255,200));
cell.Offset[0, 1].Interior.Color = ColorTranslator.ToOle(Color.LightSkyBlue);
}
};
DisplayInExcel(checkAccounts, display);
var word = new Word.Application();
word.Visible = true;
word.Documents.Add();
word.Selection.PasteSpecial(Link: true, DisplayAsIcon: false);
}
public static void DisplayInExcel(IEnumerable<Account> accounts, Action<Account, Excel.Range> display)
{
var xl = new Excel.Application();
xl.Workbooks.Add();
xl.Visible = true;
xl.Cells[1, 1] = "ID";
xl.Cells[1, 2] = " Balance";
xl.Cells[2, 1].Select();
foreach (var ac in accounts)
{
display(ac, xl.ActiveCell);
xl.ActiveCell.Offset[1, 0].Select();
}
xl.Range["A1:B3"].Copy(); // xl.get_Range("A1:B3").Copy();
xl.Columns[1].AutoFit();
xl.Columns[2].AutoFit();
}
}
, ,
PasteSpecial , .
void PasteSpecial(ref object IconIndex = null, ref object Link = null,
ref object Placement = null, ref object DisplayAsIcon = null,
ref object DataType = null, ref object IconFileName = null,
ref object IconLabel = null);
:
X1.Cells[1, 1].Value = "ID";
(Index Properties) :
xl.Cells[1, 1] = "ID";
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
Assistant
Department
Alfreds
Maria
Sales
Alfred
Marketing
Mary
Service
User1 decides to resolve this conflict by having the newer database values overwrite the current values in the object
model. When User1 resolves the conflict by using OverwriteCurrentValues, the result in the database is as follows in
the table:
Manager
Assistant
Department
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
New state after conflict resolution.
Alfreds
(original)
Mary
(from User2)
Service
(from User2)
The following example code shows how to overwrite current values in the object model with the database values. (No
inspection or custom handling of individual member conflicts occurs.)
Northwnd db = new Northwnd("...");
try { db.SubmitChanges(ConflictMode.ContinueOnConflict); }
catch (ChangeConflictException e)
{
Console.WriteLine(e.Message);
foreach (ObjectChangeConflict occ in db.ChangeConflicts)
occ.Resolve(RefreshMode.OverwriteCurrentValues); // All database values overwrite current values
}
Manager
Assistant
Department
Alfred
(from User1)
Maria
(original)
Marketing
(from User1)
The following example code shows how to overwrite database values with the current client member values. (No inspection or custom handling of individual member conflicts occurs.)
try { db.SubmitChanges(ConflictMode.ContinueOnConflict); }
catch (ChangeConflictException e)
{
Console.WriteLine(e.Message);
foreach (ObjectChangeConflict occ in db.ChangeConflicts)
occ.Resolve(RefreshMode.KeepCurrentValues); //No database values are merged into current
}
Manager
Assistant
Department
Alfred
(from User1)
Mary
(from User2)
Marketing
(from User1)
The following example shows how to merge database values with the current client member values (unless the client
has also changed that value). No inspection or custom handling of individual member conflicts occurs.
try { db.SubmitChanges(ConflictMode.ContinueOnConflict); }
catch (ChangeConflictException e)
{
Console.WriteLine(e.Message);
foreach (ObjectChangeConflict occ in db.ChangeConflicts)
occ.Resolve(RefreshMode.KeepChanges); // Automerge database values for members that client has not modified
}
db.SubmitChanges(ConflictMode.FailOnFirstConflict); // Submit succeeds on second try
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
foreach (Customer c in custQuery)
{
Console.WriteLine("CustomerID: {0}", c.CustomerID);
Console.WriteLine("\tOriginal value: {0}", c.City);
c.City = "Paris";
Console.WriteLine("\tUpdated value: {0}", c.City);
}
ChangeSet cs = db.GetChangeSet();
Console.Write("Total changes: {0}", cs);
Console.ReadLine(); // Freeze the console window
db.SubmitChanges();
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
Visitor pattern
In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure upon which it operates. A practical result of this separation is the ability to add new
operations to existing object structures without modifying those structures. Thus, using the visitor pattern helps conformance with the open/closed principle.
In essence, the visitor allows one to add new virtual functions to a family of classes without modifying the classes
themselves; instead, one creates a visitor class that implements all of the appropriate specializations of the virtual function. The visitor takes the instance reference as input, and implements the goal through double dispatch. While powerful, the visitor pattern is more limited than conventional virtual functions. It is not possible to create visitors for objects without adding a small callback method inside each class. In naive implementations, the callback method in each
of the classes is not inheritable.
Details
The idea is to use a structure of element classes, each of which has an accept() method that takes a visitor object as an
argument. Visitor is an interface that has a visit() method for each element class. The accept() method of an element
class calls back the visit() method for its class. Separate concrete visitor classes can then be written that perform some
particular operations, by implementing these operations in their respective visit() methods.
One of these visit() methods of a concrete visitor can be thought of as a method not of a single class, but rather a
method of a pair of classes: the concrete visitor and the particular element class. Thus the visitor pattern simulates
double dispatch in a conventional single-dispatch object-oriented language such as Java, Smalltalk, and C++. For an
explanation of how double dispatch differs from function overloading, see Double dispatch is more than function
overloading in the double dispatch article. In the Java language, two techniques have been documented which use
reflection to simplify the mechanics of double dispatch simulation in the visitor pattern: getting rid of accept() methods (the Walkabout variation), and getting rid of extra visit() methods.
The visitor pattern also specifies how iteration occurs over the object structure. In the simplest version, where each
algorithm needs to iterate in the same way, the accept() method of a container element, in addition to calling back the
visit() method of the visitor, also passes the visitor object to the accept() method of all its constituent child elements.....
Because the Visitor object has one principal function (manifested in a plurality of specialized methods) and that function is called visit(), the Visitor can be readily identified as a potential function object. Likewise, the accept() function
can be identified as a function applicator, a mapper, which knows how to traverse a particular type of object and apply
a function to its elements. Lisp's object system with its multiple dispatch does not replace the Visitor pattern, but
merely provides a more concise implementation of it in which the pattern all but disappears.
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
};
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
-
-,
. C# ,
( ) .
- ( )
. . (functional)
, ,
, . ,
, ,
, , . -
.
- ,
() . ,
, C# 2.0. , - .
- .
.
14.
- . , ,
, . . - . -,
,
, return. - .
- .
System.Linq.Expressions.
, , , .
- , " " .
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
-
-; , .
, -
. - ,
: x => x / 2.
: " x x".
, - . , .
,
, - ,
-.
- ,
. double,
x double:
Func<double, int> expr = x => x / 2; // !!!!
, - int:
Func<double, int> expr = x => (int) x / 2;
- , , ,
out- ref-. - , -
. .
-, :
public class LambdaTest
{
static void Main()
{
int counter = 0;
WriteStream( () => counter++ );
Console.WriteLine( " : {0}", counter );
}
static void WriteStream( Func<int> counter )
{
for( int i = 0; i < 10; ++i )
Console.Write( "{0}, ", counter() );
Console.WriteLine();
}
}
, -
WriteStream. , ,
, counter Main. C# 1.0
:
unsafe public class MyClosure
{
int* counter;
public MyClosure( int* counter )
{
this.counter = counter;
}
public delegate int IncDelegate();
public IncDelegate GetDelegate() { return new IncDelegate( IncrementFunction ); }
int IncrementFunction() { return (*counter)++; }
}
public class LambdaTest
{
unsafe static void Main()
{
int counter = 0;
MyClosure closure = new MyClosure( &counter );
WriteStream( closure.GetDelegate() );
Console.WriteLine( " : {0}", counter );
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
}
static void WriteStream( MyClosure.IncDelegate incrementor )
{
for( int i = 0; i < 10; ++i )
Console.Write( "{0}, ", incrementor() );
Console.WriteLine();
}
}
, , -.
.
. counter Main.
.
MyClass . Main MyClosure
, GetDelegate WriteStream.
! .
C# 2.0 , .
-,
.
. ,
,
-.
public class LambdaTest
{
static void Main()
{
int counter = 0;
WriteStream(delegate () { return counter++;} );
Console.WriteLine( " : {0}", counter );
}
static void WriteStream( Func<int> counter )
{
for( int i = 0; i < 10; ++i )
Console.Write( "{0}, ", counter() );
Console.WriteLine();
}
}
-. , ,
, C# 1.0.
, -. , , C# 3.0
-,
.
, , counter
-. , counter Main,
WriteStream .
10 , .
(closure). , ,
- , .
, . , ,
. , , -,
:
public class LambdaTest
{
static void Main()
{
var teamMembers = new List<string> {"Lou Loomis","Smoke Porterhouse","Danny Noonan","Ty Webb" };
FindByFirstName( teamMembers, "Danny", (x, y) => x.Contains(y) );
}
static void FindByFirstName(List<string> members, string fName, Func<string,string,bool> predicate )
{
foreach( var member in members )
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
{
if (predicate(member, fName))
Console.WriteLine( member );
}
}
}
- ,
string bool. , -
.
14, -
.
-
-, , .
- , -.
- , ,
.
return. -, ,
, , return. ,
-: (x, y) => x * y : (x, y) => { return x * y; }.
.
-.
, , ,
, System.Linq.Expressions.Expression<T>.
.
,
,
. , ,
.
-, . ,
, . , # 3.0
-
System.Linq.Expressions. , " ", , . ,
, - , :
Func<int, int> func1 = n => n+1;
,
int. :
Expression<Func<int, int>> expr = n => n+1;
! -, , ,
, . expr
Expression<T>, T , -.
Expression<Func<int,int>>, , .
, :
public class EntryPoint
{
static void Main()
{
Expression<Func<int, int>> expr = n => n+1;
Func<int, int> func = expr.Compile();
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
. , ,
, .
. ,
, -
Expression<T>. ,
ILDASM , .
-, :
public class EntryPoint
{
static void Main()
{
var par = Expression.Parameter(typeof(int), "n");
var expr = Expression<Func<int, int>>.Lambda<Func<int, int>>(
Expression.Add(par, Expression.Constant(1)), par);
Func<int, int> func = expr.Compile();
for (int i = 0; i < 10; ++i)
Debug.WriteLine(func(i));
}
}
, expr
- n => n+1. , , .
.
.
-. n.
:
var par = Expression.Parameter( typeof(int), "n" );
,
. , .
, .
, par, int. ,
- .
BinaryExpression, , :
Expression.Add(par, Expression.Constant(1))
, BinaryExpression 1
par. , . Abstract
Factory ( ) . ,
BinaryExpression ,
Expression . ,
, , , Expression ,
.
, BinaryExpression, Expression.Lambda<>
( par+1) ( n).
, Lambda<>,
Expression<Func<int,int>>.
, , , ,
.
Expression.Lambda,
LambdaExpression. LambdaExpression Compile;
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
Delegate.
Delegate, , Func<int, int>,
, DynamicInvoke .
,
, , ,
.
, ,
-, .
(n+1) 2*(n+1):
public class EntryPoint
{
static void Main()
{
Expression<Func<int,int>> expr = n => n+1;
// expr , 2.
expr = Expression<Func<int,int>>.Lambda<Func<int,int>>(
Expression.Multiply (expr.Body, Expression.Constant(2)), expr.Parameters);
Func<int, int> func = expr.Compile();
for( int i = 0; i < 10; ++i )
Console.WriteLine( func(i) );
}
}
, , Lambda<>,
, ; .. expr.Parameters. .
Lambda<> ParameterExpression;
, ,
ParameterExpression, , .
, Expression,
. .
MSDN,
System.Linq.Expressions.
- Lisp,
, Lisp .
Lisp ,
. ,
, , .
, , , C# 3.0
LINQ. LINQ 16, : LINQ
, ,
- . ,
LINQ , ( IEnumerable),
, . LINQ
, XML .
C# 3.0 LINQ ( LINQ to SQL, LINQ
to Dataset, LINQ to Entities, LINQ to XML LINQ to Objects),
LINQ , IEnumerable.
? , LINQ to SQL
. ,
. ,
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
LINQ. , ,
.
LINQ ( ), IL ( ),
. , , ,
, . , ,
, , ,
.
. ,
,
LambdaExpression.Compile .
IL, . ,
C# 3.0.
-
, , , -,
. C# 2.0,
. ,
.
, C# 4.
, -
. , ,
, ,
.
9 yield, "
" 14 .
, C++ (STL),
. , std
<algorithm>, .
STL 90- , C++
.
, ,
. ,
.
, ,
, , , .
:
public static class Extender
{
public static IEnumerable<T> MyIterator<TColl, TCursor, T>(this TColl coll, TCursor cursor,
Func<TColl, TCursor, T> GetCurrent, Func<TCursor, bool> IsOver, Func<TCursor, TCursor> Advance)
{
while (!IsOver(cursor))
{
yield return GetCurrent(coll, cursor);
cursor = Advance(cursor);
}
}
}
Console.Write("\nMy Diagonal Iterator\n");
var list2D = new List<List<double>> {
new List<double> { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 },
new List<double> { 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7 },
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
new List<double> { 2.0, 2.1, 2.2, 2.3, 2.4 },
new List<double> { 3.0, 3.1, 3.2, 3.3 }
};
var iter = list2D.MyIterator(
new int[] { 0, 0 },
(a, c) => a[ c[0] ] [ c[1] ],
c => c[0] > 3 || c[1] > 3,
c => new int[] { c[0] + 1, c[1] + 1 });
foreach (var c in iter)
Console.WriteLine("{0:f1}", c);
, MyIterator<>! , ,
-, , ,
, . ,
. TColl ,
List<List<double>>. TCursor ,
,
list2D. T , yield. MyIterator<>
, , .
,
-:
(a, c) => a[ c[0] ] [ c[1] ]
,
-:
(c) => c[0] > 3 || c[1] > 3
, , , , -:
(c) => new int[] { c[0] + 1, c[1] + 1 }
MyIterator<> IEnumerable<T>,
IEnumerable<double>. , , ,
MyIterator <>, IEnumerable<>. list2D IEnumerable<>,
, , IEnumerable<List<double>>.
, , "" 4,
MyIterator<> ,
. , ,
, -,
.
, ,
list2D . ,
2 -, ,
:
(a, c) => a[ c[0] ] [ c[1] ] * 2;
, MyIterator<>
C# 1.0? , , C# 3.0 .
, , , :
0.0
1.1
2.2
3.3
,
, , :
static IEnumerable<T> MyGenerator<T>(T init, Func<T, T> Advance)
{
T current = init;
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
while (true)
{
yield return current;
current = Advance(current);
}
}
MyGenerator.
Console.Write("\nMy Generator\n");
var iter = MyGenerator<double>(1, x => x * 1.2);
var en = iter.GetEnumerator();
for (int i = 0; i < 10; ++i)
{
en.MoveNext();
Console.WriteLine(en.Current);
}
:
1
1.2
1.44
1.728
2.0736
2.48832
2.985984
3.5831808
4.29981696
5.159780352
,
. , ,
, ;
.
, C#.
( )
In computer science, a closure is a first-class function with free variables that are bound in the lexical environment.
Such a function is said to be "closed over" its free variables. A closure is defined within the scope of its free variables,
and the extent of those variables is at least as long as the lifetime of the closure itself. The explicit use of closures is
associated with functional programming and with languages such as ML and Lisp. Closures are used to implement continuation passing style, and in this manner, hide state. Constructs such as objects and control structures can thus be
implemented with closures. The concept of closures was developed in the 1960s and was first fully implemented as a
language feature in the programming language Scheme. Since then, many languages have been designed to support
closures. In some languages, a closure may occur when a function is defined within another function, and the inner
function refers to local variables of the outer function.
" " 10 ,
.
. (closure).
.
http://en.wikipedia.org/wiki/Closure_%28computer_science%29.
Console.Write("\nClosure\n");
int delta = 3;
Func<int, int> f = x => x + delta;
for (int i = 0, n = 0; i < 10; ++i)
Console.WriteLine(n = f(n));
delta f . delta
. ,
.
delta. , , ,
-, ,
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
. , ,
.
C# 3.0
. .
,
.
.
, ,
, . , -
, ,
. ,
. ,
, -:
x => x * 3
x => x + 3.1415
- , :
static Func<T, S> Chain<T,R,S>(Func<T,R> f1, Func<R,S> f2) { return x => f2(f1(x)); }
Console.Write("\n\nChain\n");
Func<int, double> fid = Chain((int x) => x / 2, (int x) => x + Math.E);
Console.WriteLine(fid (6));
Chain<> , . Main
, . ,
Chain<>, ,
- :
x => x / 2 + Math.E
, , ,
. ,
.
n- . ,
, :
, , .. fib.
! , , .
- , , ,
, , 30- 39- !
, .
, , ,
, ,
.
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
,
. ,
, ,
. ,
, .
(memoization). ,
, .
In computing, memoization is an optimization technique used primarily to speed up computer programs by having
function calls avoid repeating the calculation of results for previously-processed inputs. Memoization has also been
used in other contexts (and for purposes other than speed gains), such as in simple mutually-recursive descent parsing
in a general top-down parsing algorithm that accommodates ambiguity and left recursion in polynomial time and
space. Although related to caching, memoization refers to a specific case of this optimization, distinguishing it from
forms of caching such as buffering or page replacement. In the context of some Logic Programming languages, memoization is also known as tabling.
, ,
.
, ,
.
, .
http://en.wikipedia.org/wiki/Memoization. (Wes Dyer)
http://blogs.msdn.com/wesdyer/archive/2007/01/ 26/function-memoization.aspx.
. extension- static- Extender.
public static Func<T, R> Memoize<T, R>(this Func<T, R> func)
{
var cache = new Dictionary<T, R>();
return (x) =>
{
R result = default(R);
if (cache.TryGetValue(x, out result))
return result;
result = func(x);
cache[x] = result;
return result;
};
}
extension- Memoize.
fib = x => x > 1 ? fib(x - 1) + fib(x - 2) : x;
fib = fib.Memoize();
Console.WriteLine("\nFibonacchi Memoization\n");
for (int i = 30; i < 40; ++i)
Console.WriteLine(fib(i));
, , Main ,
Memoize , . ,
. Memoize ,
func , Dictionary<>
func. Memoize
, . , ,
, .
, ,
, . ,
.
.
, Main :
Func<ulong, ulong> fib = null;
fib = (x) => x > 1 ? fib(x-1) + fib(x-2) : x;
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
fib = fib.Memoize();
Func<ulong, decimal> fibConstant = null;
fibConstant = (x) =>
{
if( x == 1 )
return 1 / (decimal)fib(x);
else
return 1 / ((decimal)fib(x)) + fibConstant(x-1);
};
fibConstant = fibConstant.Memoize();
Console.WriteLine( "\n{0}\t{1}\t{2}\t{3}\n","", "".PadRight(24),
"1/ ".PadRight(24), " ".PadRight(24) );
for( ulong i = 1; i <= 93; ++i )
Console.WriteLine("{0:D5}\t{1:D24}\t{2:F24}\t{3:F24}",i,fib(i),1/(decimal)fib(i),fibConstant(i));
, n- .
x, ,
. ,
fibConstant. , - ,
fibConstant x. ,
.
, .
, 93. , ulong 94-
. , BigInteger System.Numeric.
, 93- , ,
.
3.359885666243177553039387
. , , .
,
, .
http://www.research.att.com/~njas/sequences/A079586.
, , , ,
, , .
, , .
(currying),
(, ), (, )
.
http://en.wikipedia.org/wiki/Currying. C++,
STL, , , ,
Bind1st Bind2nd.
, -, : (x, y) => x + y. ,
, -
, .
-,
. , , STL C++,
. , :
public static class Extender
{
public static Func<T1, TResult> Bind2nd<T1, T2, TResult>(
this Func<T1, T2, TResult> func, T2 constant ) { return x => func(x, constant); }
}
Main.
var mylist = new List<double> { 1.0, 3.4, 5.4, 6.54 };
var newlist = new List<double>();
Func<double, double, double> sum = (x, y) => x + y;
var funcBound = sum.Bind2nd(3.2); // -
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
Console.WriteLine("\n\nOriginal List<double>");
foreach (var item in mylist)
{
Console.Write("{0}, ", item);
newlist.Add(funcBound(item));
}
Console.WriteLine("\n\nCurried List<double>");
foreach (var item in newlist)
Console.Write("{0}, ", item);
Bind2nd<>, . ,
, . ,
, ,
. myList,
, newList, ,
3.2 .
,
:
public static class Extender
{
public static Func<T2, Func<T1, TResult>> Bind2nd<T1, T2, TResult>( this Func<T1, T2, TResult> func)
{
return y => x => func(x, y);
}
}
Main.
var mylist = new List<double> { 1.0, 3.4, 5.4, 6.54 };
var newlist = new List<double>();
// - .
Func<double, double, double> func = (x, y) => x + y;
var funcBound = func.Bind2nd()(3.2); // - "" .
foreach(var item in mylist )
{
Console.Write( "{0}, ", item );
newlist.Add( funcBound(item) );
}
Console.WriteLine();
foreach(var item in newlist )
Console.Write( "{0}, ", item );
, . Bind2nd<> ,
. Bind2nd<> ,
(, )
, . .
.
( ) ,
.
, :
Func<int, int> fact = null;
fact = x => x > 1 ? x * fact(x-1) : 1;
, fact .
, fact - , fact.
, , ,
.
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
, ,
, -,
-. , ,
, :
Func<int, int> fact = null;
fact = (x) => x > 1 ? x * fact(x-1) : 1;
Func<int, int> newRefToFact = fact;
! , ? ,
fact. , - x => x+1. newRefToFact
- x => x > 1 ? x * fact(x-1) : 1. , ,
newRefToFact, fact, x => x + 1,
.
,
. , -
, , . ,
.
:
delegate TResult AnonRec<T, TResult>( AnonRec<T,TResult> f, T arg );
AnonRec<int, int> fact = (f, x) => x > 1 ? x * f(f, x-1) : 1;
, , , ,
.
f. , fact f ,
f . , ,
. , ,
. http://en.wikipedia.org/wiki/Anonymous_recursion
.
,
(Wes Dyer) Anonymous Recursion in C# http://blogs.msdn.com/wesdyer.
C# . ,
Y- , ,
. Y- http://en.wikipedia.org/wiki/
Fixed_point_combinator.
-,
. , , - C# 2.0,
. ,
- . , -
Expression<T>,
System.Linq.Expression.
. . , ,
, .
.
C# , -
.
. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
LINQ C# 3.0.
.
One of the big benefits that the EDM lends to querying is that the relationships are built into the model and you wont
have to construct joins very often to access related data. Additionally, when using LINQ for the queries, the related
data is presented via IntelliSense, which makes it very discoverable.