by Piotrosz
21. December 2008
Wyrażenie lambda w C# to delegat bez nazwy (delegat anonimowy). Jest to operacja, bądź ciąg operacji bez nazwy. Lewa strona wyrażenia lambda to parametry (może ich w ogóle nie być). Po prawej stronie są zdefiniowane operacje. Obie strony są rozdzielone "=>". W podobny sposób definiuje się funkcję w matematyce i można to sobie z tym skojarzyć.
Na przykład: x => x*x to operacja podnoszenia do kwadratu. "x" jest w tym wyrażeniu zmienną wolną, tzn. jest tylko oznaczeniem i nie ma różnicy jaka litera czy słowo zostanie użyta/użyte. Taka definicja: cx => cx*cx jest dokładnie równoważna poprzedniej.
Pierwsze eksperymenty z wyrażeniami Lambda w C# 3.0:
using System;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace LINQ_4
{
class Program
{
delegate double PodnoszenieDoKwadratu(double x);
delegate double Mnozenie(double x, double y);
delegate string ZwracanieStringa();
static void Main(string[] args)
{
PodnoszenieDoKwadratu p = x => x * x;
double Liczba = p(1.2d);
Console.WriteLine(Liczba); // 1.44
// Musi być nawias jak jest więcej niż 1 argument
Mnozenie m = (x, y) => x * y;
Liczba = m(2d, 3d);
Console.WriteLine(Liczba); // 6
// Wyrażenie Lambda bez parametrów.
// Wyrażenie to jest ciągiem poleceń;
ZwracanieStringa mc = () => { string s = "cześć"; return s; }; // to samo co: () => { "cześć" };
string Slowo = mc();
Console.WriteLine(Slowo); // cześć
// Func to wbudowany delegat generyczny
// Pierwszy parametr to argument, a drugi to zwracany typ
Func EqualToA = x => x == "A";
bool z = EqualToA("B");
Console.WriteLine(z); // False
// Wyrażenie Lambda może być argumentem metody!
int[] Liczby = { 2, 3, 4, 5, 6, 9, 12 };
// Count to metoda rozszerzająca, która jako argument przyjmuje predyktat (wyrażenie lambda)
int IlePodzielnychPrzez3 = Liczby.Count(x => x % 3 == 0);
Console.WriteLine(IlePodzielnychPrzez3); // 4
int PierwszaPodzielnaPrzez3 = Liczby.First(x => x % 3 == 0);
Console.WriteLine(PierwszaPodzielnaPrzez3); // 3
bool CzySaWielokrotnosci4 = Liczby.Any(f => f % 4 == 0 && f != 4);
Console.WriteLine(CzySaWielokrotnosci4); // True
}
}
}
by Piotrosz
21. December 2008
Metody rozszerzające ("extension methods") pozwalają na dodanie metod do istniejących typów bez korzystania z dziedziczenia lub uciekania się modyfikacji definicji orginalnego typu. Metody te są zawsze statyczne, ale wywoływane są zawsze z poziomu określonej instancji klasy, a więc nie ma różnicy pomiędzy wywołaniem metody zdefiniowanej w klasie a wywołaniem metody rozszerzającej zdefiniowanej dla tej klasy. Operatory LINQ są zdefiniowane właśnie jako metody rozszerzające System.Collections.IEnumerable oraz System.Collections.Generic.IEnumerable(T). Metoda rozszerzająca jako pierwszy argument musi mieć zawsze typ docelowy, który jest rozszerzany poprzedzony słowem kluczowym "this".
Przyład dodania metody rozszerzającej do klasy string:
using System;
using System.Linq;
using System.Text;
namespace LINQ_3
{
class Program
{
static void Main(string[] args)
{
string s = "a";
Console.WriteLine(s.AppendStar());
// Wynik: a*
}
}
public static class ExtensionsTest
{
public static string AppendStar(this string str /* reszta argumentów...*/)
{
return string.Format("{0}*", str);
}
}
}
by Piotrosz
21. December 2008
Typy anonimowe pozwalają na stworzenie instancji klasy bez pisania definicji klasy. Robi to automatycznie kompilator. Poniższy przykład pokazuje jak automatycznie tworzone są nazwy takich klas:
using System;
using System.Linq;
using System.Text;
namespace LINQ_2
{
class Program
{
static void Main(string[] args)
{
var Book1 = new { Title = "A", Year = 1975, Color = System.Drawing.Color.Red };
Console.WriteLine(Book1.GetType());
var Book2 = new { Title = "B", Year = 1999, Color = System.Drawing.Color.Red };
Console.WriteLine(Book2.GetType());
var Other = new { Angle = 12.4d, Thickness = 225.6d };
Console.WriteLine(Other.GetType());
var Other2 = new { X = 23.6d, Z = 32.6d };
Console.WriteLine(Other2.GetType());
}
}
}
Wynik:

by Piotrosz
21. December 2008
var jest rodzajem zmiennej, której typ jest wnioskowany na podstawie przypisania do niej wartości. Można powiedzieć, że jest to inteligentna zmienna:
namespace LINQ_1
{
class Program
{
static void Main(string[] args)
{
var Name = "Pedro";
Console.WriteLine(Name.GetType());
var Age = 10;
Console.WriteLine(Age.GetType());
var Amount = 134.67m;
Console.WriteLine(Amount.GetType());
var ArrayOfInts = new [] { 1, 2, 3 };
Console.WriteLine(ArrayOfInts.GetType());
var CustomClass = new Class1();
Console.WriteLine(CustomClass.GetType());
var Obj = new object();
Console.WriteLine(Obj.GetType());
}
}
class Class1
{
int x;
double y;
}
}
Wynik:
Jak widać nie ma tu naruszenia faktu, że C# jest językiem silnie typowanym. Nie ma to nic wspólnego z var występującym w Java Scripcie czy Dim w Visual Basic.
Typ zmiennej var jest zawsze określony. Ale jest warunek, że zmienna musi zostać przypisana w tej samej linijce, w której jest jej deklaracja (aby kompilator miał możliwość wywnioskowania jej typu).
by Piotrosz
19. December 2008
Tworząc aplikację .NET w Visual Studio (na przykład aplikację konsolową lub okienkową), jest możliwość wyboru skompilowania jej do pakietu (assembly) w trybie
Debug albo
Release. W trybie Release aplikacja jest optymalizowana pod względem wydajności i szybkości; wygenerowany kod jest mniejszy, ale nie jest on dostępny dla narzędzi debugujących. Odpowiednie pliki .exe znajdują się w katalogach bin\Debug i bin\Release projektu. Najszybsze odpalenie programu w trybie Debug albo Release:

by Piotrosz
16. December 2008
Oto scena z filmu "Happy Go Lucky" Mike'a Leigh. Książką, którą ogląda Poppy na samym początku filmu jest "Road To Reality" Rogera Penrose'a. Bohaterka na jej widok stwierdza: "Ain't goin' there" ("Nie wybieram się tam").
Zdałem sobie sprawę, że również posiadam tę książkę! Polskie tłumaczenie tytułu to "Droga do rzeczywistości". Polecam ją wszystkim, którzy mają nadmiar wolnego czasu i interesują się makabrycznie trudną matematyką. Penrose pisał to dzieło 8 lat. Wydaje mi się, że przeczytanie i zrozumienie jej zajmie czytelnikowi niebędącemu profesorem matematyki co najmniej tyle samo czasu. Książka jest ciężka w dosłownym i metaforycznym tego słowa znaczeniu.
by Piotrosz
15. December 2008
Atrybut SkinId powoduje, że dana skórka nie będzie automatycznie aplikowana do wszystkich kontrolek danego typu, a tylko do tych, które mają również taki sam atrybut SkinId.
Na przykład w pliku .skin w katalogu tematu jest zdefiniowana skórka dla guzika:
Do pierwszego guzika skórka ta nie aplikuje się, a do drugiego tak:
