Вы находитесь на странице: 1из 51

. LINQ.

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

, ++ 44 . ( .Net Framework 3.5),


77 , C# 24 (Contextual Keywords). .
add

ascending

by

descending

equals

from

get

global

group

into

join

let

on

orderby

partial (type)

. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
partial (method)

remove

select

set

var

where (generic type constraint)

where (query clause)

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#, . , .

(local variable type inference). : var s = "Hi";


string s = "Hi";
(auto-implemented properties). c
(, ) :
decimal salary;
public decimal Salary
{
get { return salary; }
set { salary = value; }
}

.
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
____________________________________________________________________________________________________________________________

Generic-, generic- generic-. generic


. , generic- ,
. (template),
++, generic. .
-, .
.
, .
.NET (LINQ).
ASP.NET AJAX (Asynchronous JavaScript and XML).
Web- () .
, ,
JavaScript.

.

, ,
, , . :
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),
. . .
}

new . : new[] {. . .}.


, generic- :
var persons = new List<Person>
{
new Person(){ Name = "Bale", Birth = new DateTime(1981, 3, 26), Salary = 10000m },
. . .
}

Generic-

. (
- ). , delegate,
( ). ( ),
. , .
, :
.

. LINQ. 2007-2010
____________________________________________________________________________________________________________________________

System ( System.Core) : Action Func,


. Action. :
public delegate void Action();

// 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
____________________________________________________________________________________________________________________________

void (int), Action<Person> void (Person).


. Program Inform.
static void Inform(string name)
//
{
Console.WriteLine(Environment.ExpandEnvironmentVariables(name));
}

Main Inform generic- Action<string> .


Action<string> s = Inform;
s("%SystemDrive%");

Action<T> s void (string).


: s ("%SystemDrive%"); Inform ("%SystemDrive%");.

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

Main SaveImage generic- Action<string, byte[]>.


byte[] img = File.ReadAllBytes(@"C:\Windows\Web\Wallpaper\Landscapes\img11.jpg");
Action<string, byte[]> save = SaveImage;
save(@"C:\Test.jpg", img); // C:\Test.jpg

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

pFunc ( , ) Sin Sqrt.


() double (double).
Func T,
TResult. Func <Person, int> p, Person int,
, : int GetHash (Person), int GetPersonID (Person).

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

Main , StupidFunc generic-:


MyFunc<int, int, int, int, string, double> pf = StupidFunc;
Console.WriteLine("pf(1, 2, 3, 4, \"10\") = " + pf(1, 2, 3, 4, "10"));

. delegate res Func<a, b, c, d, e, res>(...); (generic delegate), , 5 (a, b, c, d, e)


res ( void void- Action<>).
, .
, . , <int, int,
int, int, string, double>, ,
. Func<>.

pf Func<int, int, int, int, string, double>


. StupidFunc ,
StupidFunc (task). ,
(InvocationList). pf = StupidFunc StupidFunc
.
, . , ,
.
-
.Net Framework 3.0 , =>.
=> (lambda operator) : . (Lambda Expressions). .
, operator,
statement. lambda operator , -.
.
=> , . C
C# , , .
, -.
, .

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

//

static void Main()


{
FuncType Half = delegate(int x) { return x / 2.0f; }; //
Console.WriteLine (Half (3));
}

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

Generic- ForEach<>, Array, . ,


foreach, C#. generic- ForEach -,
. :
Console.WriteLine("\n\nFormat double as decimal");
var amounts = new double[] { 10.36, 12.0, 134 };
Array.ForEach<double>(amounts, c => Console.WriteLine("{0:c}", c));

.
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 + ", ");

c, extension- Where, C#.


, . :
where? , :
var where = words.Where (c => c == "Where");

Intellisense Where.
, IEnumerable<string>. ,
, var ( ).
IEnumerable<string> where = words.Where(c => c == "Where");

. , -:
c => c == "Where"

. : Func<string, bool>, c string, c == "Where"


bool.
LINQ generic-,
IEnumerable<T>.
, , var , ,
.
IEnumerable<T> , . :
, . , ,
, abstract- Array, IEnumerable.
: IEnumerable<T>
, IEnumerable<T>.

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
____________________________________________________________________________________________________________________________

, song <Anonymous Type>,


- .NET, . var
<Anonymous Type> .
, Artist Song ( ). , ,
, ,
.
var songs = new[]
{
new { Artist = "Low Rowles", Song = "Cheek to cheek" },
song,
new { Artist = "Frank Sinatra", Song = "September In the Rain" }
};

. , 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>.

BinaryTree<T> : List<T> path;


.
public BinaryTree ()
{
path = new 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));
}

Extender , object, , .NET Framework,


object. (
, object) . .
. ,
DateTime.Now.IsIn(dates) , ( , ). Main()
3. () Intellisense.
?
var ints2D = new int[][] {
ints,
new[] { 2, 3, 4 },
new[] { 1, 2, 3, 4, 5, 6, 7 }
};
Console.WriteLine("ints {0:d} is in ints2D: {1}", ints, ints.IsIn(ints2D));

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

extension- Dump(this object o) . string


: Chars, (property), Length.
.
Chars --> unknown
Length --> 51

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

Extender , String LengthOrNull.

. 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.
. , ,
.

System generic- ( , ) Predicate<>.


bool Predicate<T>(T). ,
T true false. ,
extension- FindAll.
, , .
Console.WriteLine("\nTest FindAll for Array");
Action<int> print = c => Console.Write(c + ", ");
int[] fib = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 }; // Fibonacci
Predicate<int> pred = c => c % 2 == 1;
Array.ForEach<int> (Array.FindAll<int>(fib, pred), print);

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

Take, TakeWhile, Skip, SkipWhile

. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
4

(Join)

Join, GroupJoin

(Concatenation)

Concat

(Ordering)

OrderBy, OrderByDescending, ThenBy, ThenByDescending, Reverse

(Grouping)

GroupBy, ToLookup

(Set)

Distinct, Union, Intersect, Except

(Conversion)

AsEnumerable, AsQueryable, ToArray, ToList, ToDictionary, Cast, OfType, ToLookup

10

(Equality)

SequenceEqual

11

ElementAt, ElementAtOrDefault, First, FirstOrDefault, Last, LastOrDefault, Single,


SingleOrDefault,

12

(Generation)

DefaultIfEmpty, Empty, Range, Repeat

13

(Quantifiers)

Any, All, Contains

14

(Aggregate)

Count, LongCount, Sum, Min, Max, Average, Aggregate


extension- Where,
. IEnumerable<T>
. :
public static IEnumerable<T> Where<T>(this IEnumerable<T> src, Func<T,bool> pred);

pred generic- Func <T, bool> -. ,


, bool.
Where src . true,
, false, . , ()
. ,
. .
string line = new string('\u2500', 22);
Console.WriteLine(line + "Test Where");
string[] words = { "cool", "google", "bool", "true", "soon", "do", "bootable", "zoom", "bottom" };
var q = words.Where(c => c.Contains("oo"));
Console.WriteLine("Words containing 'oo':\n" + line);
foreach (var s in q)
Console.WriteLine(s + "\t" + s.Length);

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

pred Func<T, int, bool> ,


: , , generic- ,
.
, bool ( bool).
. , .
string[] digitNames = { "zero","one","two","three","four","five","six","seven","eight","nine" };
var q = digitNames.Where((s, i) => s.Length <= i);
Console.WriteLine("Name: Length: Pos:\n{0}", new string('\u2500', 21));
int k = 0;
foreach (var s in q)
Console.WriteLine("{0,-8} {1,-5}
{2}", s, s.Length, ++k);

. LINQ. 2007-2010
____________________________________________________________________________________________________________________________

-: (s, i) => s.Length <= i. (s, i) , ,


Where, i digitNames.
int. - Func<T,int,bool>.

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
____________________________________________________________________________________________________________________________

Select SelectMany , (selector) -,


.
Single, SingleOrDefault, First, FirstOrDefault, Last, LastOrDefault
IEnumerable IQueryable, ,
. .
string[] words = { "abstract", "false", "finally", "null", "for", "if", "object", "Freeloader" };
Console.WriteLine(words.First(s => s[0] == 'f'));
Console.WriteLine(words.Last(s => s.StartsWith("f", StringComparison.InvariantCultureIgnoreCase)));

, First Single . FirstOrDefault SingleOrDefault


, null. .
int?[] ia = new int?[1];
int? n = ia.FirstOrDefault(c => (c & 1) == 1);
Console.WriteLine(n == null ? "null" : n.ToString());
ia = new int?[] { 6, 8, 9};
n = ia.FirstOrDefault(c => (c & 1) == 1);
Console.WriteLine(n == null ? "null" : n.ToString());

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

source generic- keySelector,


. ,
Person .
public class Person
{
public string Name { get; set; }
public DateTime Birth { get; set; }
public int Status { get; set; }
}

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

res Aggregate withdrawals 3000,


5000 s <= b.
Union, Intersect, Except Count
: Union, Intersect, Except Count.
, .

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

. from, where select,


C# 3.5. .
Console.WriteLine("\nConcise Version of IsLeapYear Query");
var q = from y in Enumerable.Range(2000, 6)
where (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
select y;
foreach (var v in q)
Console.WriteLine(v);

,
. , ,
. , ,
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
____________________________________________________________________________________________________________________________

orderby extension- OrderBy. ,


.
var people = new[]{
new {Name="Alex Black", Position="Developer", Birth=new DateTime(1980,2,26) },
new {Name="Alex Ritter", Position="Boss", Birth=new DateTime(1969,3,15) },
new {Name="Peter Pann", Position="Manager", Birth=new DateTime(1980,9,12) },
new {Name="Joy Amore", Position="Referent", Birth=new DateTime(1990,6,27) },
new {Name="Jack O'Mule", Position="Referent", Birth=new DateTime(1990,4,2) },
new {Name="Jill Sweet", Position="Referent", Birth=new DateTime(1990,9,20) },
new {Name="Brad Show", Position="Developer", Birth=new DateTime(1980,2,26) }
};
var q = from p in people
orderby p.Position descending, p.Name
select p;
foreach (var v in q)
Console.WriteLine(v);

Position,
Name. extension- .
q = people.OrderByDescending (p => p.Position).ThenBy (p => p.Name);

, extension-
, , : from, select, orderby, descending,
.

: group by, extension- GroupBy,


. , , ,
. ( Key).
.
( ), .
var numbers = new [] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var gr = from n in numbers group n by n % 3;
Console.WriteLine("Test grouping");
foreach (var g in gr.ToArray()) // var IGrouping<int, int>
{
Console.Write("\n Group # " + g.Key + ": ");
foreach (var v in g.ToArray())
Console.Write(v + ", ");
}

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

dynamic Office COM Interop. , Office


C# dynamic. dynamic :
((Excel.Range)excel.Cells[1, 1]).Value2 = "ID";

:
X1.Cells[1, 1].Value = "ID";

(Index Properties) :
xl.Cells[1, 1] = "ID";

. LINQ. 2007-2010
____________________________________________________________________________________________________________________________

COM Interop Primary Interop Assemblies (PIA) COM , ,


() . C# 4.0 No-PIA,
(distribution module) PIA.

How to: Detect and Resolve Conflicting Submissions


Northwnd db = new Northwnd(@"c:\northwnd.mdf");
Customer newCust = new Customer();
newCust.City = "Auburn";
newCust.CustomerID = "AUBUR";
newCust.CompanyName = "AubCo";
db.Customers.InsertOnSubmit(newCust);
try
{
db.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException e)
{
Console.WriteLine("Optimistic concurrency error.");
Console.WriteLine(e.Message);
Console.ReadLine();
foreach (ObjectChangeConflict occ in db.ChangeConflicts)
{
MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType());
Customer entityInConflict = (Customer)occ.Object;
Console.WriteLine("Table name: {0}", metatable.TableName);
Console.Write("Customer ID: ");
Console.WriteLine(entityInConflict.CustomerID);
foreach (MemberChangeConflict mcc in occ.MemberConflicts)
{
object currVal = mcc.CurrentValue;
object origVal = mcc.OriginalValue;
object databaseVal = mcc.DatabaseValue;
MemberInfo mi = mcc.Member;
Console.WriteLine("Member: {0}", mi.Name);
Console.WriteLine("current value: {0}", currVal);
Console.WriteLine("original value: {0}", origVal);
Console.WriteLine("database value: {0}", databaseVal);
}
}
}
catch (Exception ee) // Catch other exceptions
{
Console.WriteLine(ee.Message);
}
finally
{
Console.WriteLine("TryCatch block has finished.");
}

How to: Resolve Concurrency Conflicts by Retaining Database Values


In this scenario, a ChangeConflictException exception is thrown when User1 tries to submit changes, because User2
has in the meantime changed the Assistant and Department columns. The following table shows the situation.
Manager

Assistant

Department

Original database state when queried by User1 and User2.

Alfreds

Maria

Sales

User1 prepares to submit these changes.

Alfred

User2 has already submitted these changes.

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
}

How to: Resolve Concurrency Conflicts by Overwriting Database Values


User1 decides to resolve this conflict by overwriting database values with the current client member values. When
User1 resolves the conflict by using KeepCurrentValues, the result in the database is as in following table:
New state after conflict resolution.

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
}

How to: Resolve Concurrency Conflicts by Merging with Database Values


User1 decides to resolve this conflict by merging database values with the current client member values. The result
will be that database values are overwritten only when the current changeset has also modified that value. When User1 resolves the conflict by using KeepChanges, the result in the database is as in the following table:
New state after conflict resolution.

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

How to: Display Generated SQL


db.Log = Console.Out;
You can view changes tracked by a DataContext by using GetChangeSet.
Northwnd db = new Northwnd(@"c:\northwnd.mdf");
var custQuery =
from cust in db.Customers
where cust.City == "London"
select cust;

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

How to: Display LINQ to SQL Commands


In the following example, the console window displays the output from the query, followed by the SQL commands
that are generated, the type of commands, and the type of connection.
Northwnd db = new Northwnd(@"c:\northwnd.mdf");
var q =
from cust in db.Customers
where cust.City == "London"
select cust;
Console.WriteLine("Customers from London:");
foreach (var z in q)
Console.WriteLine("\t {0}",z.ContactName);
DbCommand dc = db.GetCommand(q);
Console.WriteLine("\nCommand Text: \n{0}",dc.CommandText);
Console.WriteLine("\nCommand Type: {0}",dc.CommandType);
Console.WriteLine("\nConnection: {0}",dc.Connection);

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

class SpaceShip {};


class GiantSpaceShip : public SpaceShip {};
class Asteroid
{
public:
virtual void CollideWith(SpaceShip&) {
cout << "Asteroid hit a SpaceShip" << endl;
}
virtual void CollideWith(GiantSpaceShip&) {
cout << "Asteroid hit a GiantSpaceShip" << endl;
}
};
class ExplodingAsteroid : public Asteroid {
public:
virtual void CollideWith(SpaceShip&) {
cout << "ExplodingAsteroid hit a SpaceShip" << endl;
}
virtual void CollideWith(GiantSpaceShip&) {
cout << "ExplodingAsteroid hit a GiantSpaceShip" << endl;
}

. LINQ. 2007-2010
____________________________________________________________________________________________________________________________
};

Suppose SpaceShip and GiantSpaceShip both have the function


virtual void CollideWith(Asteroid& asteroid) { asteroid.CollideWith(*this); }

. LINQ. 2007-2010
____________________________________________________________________________________________________________________________

"C# 2008: "


:
C# 3.0 C#
.
, ( ), ,
, ; .
Lisp, Haskell, F# Scheme.
,
, C- ( C#).
C# 3.0 ,
. -
, .
F# .NET Framework.
(Robert Pickering) Foundations of F# (Berkeley,
CA: Apress, 2007 .). , C++. ,
C++, .
C++ ,
(David Abrahams) (Aleksey Gurtovoy) C++ Template Metaprogramming: Concepts,
Tools, and Techniques from Boost and Beyond (Boston, MA: Addison-Wesley Professional, 2004 .).

-
-,
. 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
____________________________________________________________________________________________________________________________

for( int i = 0; i < 10; ++i )


Console.WriteLine( func(i) );
}
}

. , ,

, .
. ,
, -
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- . ,
, :

Fk k- . (http://mathworld.wolfram.com/ReciprocalFibonacciConstant.html. Eric W. "Reciprocal Fibonacci Constant." MathWorld A Wolfram Web Resource).


, n- :
Func<int, int> fib = x => x > 1 ? fib(x-1) + fib(x-2) : x;
for(int i = 30; i < 40; ++i)
Console.WriteLine( fib(i) );

, , .. 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;

CLR , newRefToFact fact


. , :
Func<int, int> fact = null;
fact = x => x > 1 ? x * fact(x-1) : 1;
Func<int, int> newRefToFact = fact;
fact = x => x + 1;

! , ? ,
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.

Вам также может понравиться