Wyrażenia lambda #1

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

Metody rozszerzające

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

Typy anonimowe

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:

Zmienna var

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

Tags: ,

C# 3.0 | LINQ

Tryby Debug i Release

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:

Droga do rzeczywistości

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").
Road to reality
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.
Droga do rzeczywistości

Co to jest SkinId?

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:


SkinId

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen