Prezentacja programu PowerPoint
Download
Report
Transcript Prezentacja programu PowerPoint
Język C#
( 4.0 )
using System;
namespace HeWo
{
class Hello
{
static void Main(string [] args)
{
Console.WriteLine("Hello World!");
}
}
}
Typy Danych
wartości ( stos , pełne kopiowanie )
logiczne
numeryczne
egzemplarze struktur
referencje ( sterta , kopiowanie referencji )
obiekty klas
tablice
ciągi znaków ( string )
Type C#
CTS
bool
byte
sbyte
short
int
long
ushort
uint
ulong
float
double
char
decimal
Boolean
Byte
SByte
Int16
Int32
Int64
UInt16
UInt32
UInt64
Single
Double
Char
Decimal
CLS
Bytes
Default
Y
Y
N
Y
Y
Y
N
N
N
Y
Y
Y
Y
1
1
1
2
4
8
2
4
8
4
8
2
16
false
0
0
0
0
0
0
0
0
0.0
0.0
0
0.0
Deklaracje i definicje zmiennych
int
Alfa , Beta , Gamma = 5 ;
Operator przypisania wartości
Beta = Gamma;
// OK
Beta = 12;
// OK
Beta = Alfa;
// błąd kompilacji
Stałe
const double Kurs = 3.857 ;
Typy implikowane (3.0)
var
var
var
var
var
a
b
c
d
e
=
=
=
=
=
5;
'K';
128L;
15.332;
"Ala ma kota";
a = 4654434L;
e = 4.5;
//
//
//
//
//
int
char
long
double
string
// long -> int
// błąd
● tylko zmienne lokalne w funkcjach nie mogą być składowymi klas
Rzutowanie
automatyczne
- rozszerzające ( bez ostrzeżenia )
- zawężające ( błąd kompilacji )
wymuszone
(int) LongValue;
int li32 = 5;
long li64;
li64 = li32;
// OK.
li32 = li64;
// błąd kompilacji
li64 = 100111222333;
li32 = (int) li64; // błędna wartość
// 1236974525
Typy rozszerzone ( nullable ) (2.0)
double? Cena;
//
{ numbs, INF, NaN, null }
//
Cena = 7.54 ;
//
Cena = null ;
//
if ( Cena.HasValue )
Cena += 1.4;
operator ??
int Parametr;
int? Pomiar = null;
/*
. . . . . . . . */
Parametr = Pomiar ?? 100 ;
//
string str = null;
/*
. . . . . . . . */
Console.WriteLine( str ?? "Pusty" );
Opakowanie – Rozpakowanie
long aaa = 1234567890 , bbb ;
object objLong = aaa ;
// stos sterta
bbb = (long) objLong ;
// sterta stos
// InvalidCastException
Typ logiczny
bool dobrze;
int alfa = 5;
dobrze = 0;
// błąd
dobrze = 3 * alfa + 1;
// błąd
dobrze = true;
// OK
dobrze = alfa > 10;
// OK
Typy wyliczeniowe
enum Wyliczanka
{
Eme,
Due,
Fake = 10,
Drake
}
//
//
//
//
//
int
== 0
== 1
== 10
== 11
enum Maly : byte
// byte
{ mini , mikro }
dziedziczenie z System.Enum
Enum.IsDefined(typeof(Maly) , "nano");
Funkcje i właściwości typów
zmienne typów będących wartościami są
egzemplarzami struktur dziedziczą funkcje z typu
System.Object.ValueType
─
GetType( )
•
// obiekt Type określający typ
dla typów wyliczeniowych (np. ConsoleColor) :
var ListaKolorów = // tablica stałych
Enum.GetValues(ConsoleColor.Black.GetType());
─
ToString( ) // konwersja binarno – znakowa
long LoVal = 15342443 ;
string Characters = LoVal.ToString ( );
właściwości typów liczbowych
MaxValue
// wartość maksymalna
MinValue
// wartość minimalna
long x = long.MaxValue;
int
y = int.MinValue;
Łańcuchy znaków UNICODE (UTF - 16)
string
zawartość łańcucha niezmienna
dziedziczy z typu System.String
typ referencyjny
Length, Concat, CompareTo, Copy,
Insert , PadLeft , PadRight , Remove ,
Replace , ToLower , ToUpper , Format
= , + , == , != ,
[ ]
string Nap1 , Nap2 = "dobry napis" ;
Nap1 = Nap2 ;
// nowa referencja
Nap1 = Nap2.ToUpper( ); // nowy łańcuch
znaki sterujące jak w C ( @ wyłącza przetwarzanie )
string Opis1 = "\nWyniki\t:" ;
string Opis2 = @"\nBez zmian\t:" ;
Przekształcanie wnętrza łańcucha
klasa System.Text.StringBuilder
using namespace System.Text;
StringBuilder myBuffer =
new StringBuilder ("Ala ma kota");
myBuffer.Append(„ a Ola psa.");
myBuffer.Insert(11, ',');
string Ready = myBuffer.ToString();
// Ala ma kota, a Ola psa.
Wprowadzanie – wyprowadzanie danych
klasa System.Console
─
int Read ( )
// 1 znak (NL, -1)
─
string ReadLine ( )
// do NL
─
string Write ( string
─
string WriteLine ( string ) // z NL
)
// bez NL
//
Console.WriteLine( x.ToString() );
Console.WriteLine( x );
// konwersja
Console.WriteLine( x.ToString() + ", " +
y.ToString() );
Console.Write ("format", w,..,w)
// bez NL
Console.WriteLine ("format", w,..,w) // z NL
"zzz{0}zzz{1}zzz{0}zzz{2}zzz..."
format
─ "zzz"
dowolny ciąg znaków (może być pusty)
─ {0} {1} {2} ... pozycje kolejnych dalszych
argumentów
─ w,...,w
0
ciąg wyrażeń
można stosować znaki formatujące
{K:Zs} lub {K,P:Zs}
─
K numer pozycji
─
Z
─
P szerokość pola
─
s liczba cyfr po kropce
znak
znak formatujący
znaczenie
C
c
waluta (wg. Windows)
D
d
całkowite dziesiętne
E
e
notacja wykładnicza
F
f
niecałkowite dziesiętne
G
g
z wykładnikiem lub bez
N
n
format narodowy
X
x
postać heksydecymalna
int ii = 34;
double dd = 2.52345324 ;
string str = "\nOpis wyniku :\t" ;
Console.WriteLine(
"{0} {1} albo {1,12:D} i {2} lub\n " +
"{2,-15:F3} lub {2:E5} lub {3} " ,
str , ii , dd , dd.ToString() ) ;
//Opis wyniku :
// 2,523
34 albo
34 i 2,52345324 lub
lub 2,52345E+000 lub 2,52345324
konwersja znakowo – binarna
(kultura - ustawienia narodowe)
-
SystemType.Parse(string)
string str;
double dd = 2.5;
str = Console.ReadLine( );
// 12,45
dd = double.Parse( str );
// błędny format -> błąd wykonania
Console.WriteLine( dd );
// 12,45
bool dobrze = false;
string str;
double dd = 2.5;
while ( ! dobrze )
{
str = Console.ReadLine( );
dobrze = double.TryParse(str, out dd);
}
Console.WriteLine(dd);
// VS.NET 2005
- klasa Convert
ToByte
ToSByte
ToChar
ToDecimal
ToDouble
ToSingle
ToInt16
ToInt32
ToInt64
ToUInt16
ToUInt32
ToUInt64
ToString
string st;
long war;
str = Console.ReadLine();
// 124534567043
war = Convert.ToInt64(str);
// format
Console.WriteLine(war);
// 124534567043
kultura (ustawienia narodowe)
- związana z każdym procesem obliczeniowym (wątkiem)
- klasa CultureInfo
using System.Threading;
using System.Globalization;
//
CultureInfo ci = new CultureInfo("de-DE");
Thread.CurrentThread.CurrentCulture = ci;
przesuwanie kursora
// VS.2005
Console.CursorVisible = false;
Console.ForegroundColor = ConsoleColor.Red;
Console.BackgroundColor = ConsoleColor.White;
Console.CursorLeft = X;
// od lewej
Console.CursorTop =
// od góry
Y;
Console.SetCursorPosition( X, Y );
Console.Write("+");
// o 1 w prawo
Console.CursorLeft = X;
// powrót
Console.Clear();
znaki sterujące
ConsoleKeyInfo znak;
//
znak = Console.ReadKey();
if( ConsoleKey.UpArrow == znak.Key)
{
....
}
// Backspace, Home, End, Enter, Escape
// Arrows, Fxx, klawiatura numeryczna
// Play, Volume, ...
Console.Beep( 3000, 1000 ); // 3000 Hz, 1000 ms
Call, S0, Kultura,Move
Wyrażenia arytmetyczne i logiczne
operatory i zasady tworzenia jak w C++
dodatkowo is as oraz =>
konwersja wartości
- rozszerzająca automatycznie
- zawężająca błąd
int a = 2L;
// błąd
float f = 2.45;
// błąd
rzutowanie
( typ ) wyrażenie
lokalne testowanie poprawności checked
// typy całkowitoliczbowe
int a1 = 2000000000;
a1 = a1 + 2000000000;
// -294967296
a1 = checked ( a1 + 2000000000 );
// wyjątek
long l1 = 5000000000;
a1 = l1;
// błąd kompilacji
a1 = ( int ) l1;
// -294967296
a1 = checked ( ( int ) l1 );
// wyjątek
globalne testowanie poprawności
Properites / Build / Advance
+
Check for arithmetic overflow/underflow
lokalne wyłącznie testowania unchecked
int a1 = 2000000000;
a1 = a1 + 2000000000;
// wyjątek
a1 = unchecked ( a1 + 2000000000 ); -294967296
Instrukcje
warunkowe
if
..
else
// jak C++
// warunek wyrażenie logiczne
if ((x + 4) > 1 && (y++ < 8)) // ||
// obliczenie optymalizowane
if ((x + 4) > 1 & (y++ < 8))
// |
// pełne obliczenie
//
switch
// instrukcja
// jak C++
break konieczna
pętle
( ogólnie jak C++ )
for ( int i = 1 ; i < 5 && dalej ; ++i )
{
.......
}
// koniec widoczności zmiennej i
while
, do ... while
foreach
//
// jak C++
wymagany IEnumerator
Struktury
są zawsze wartościami (na stosie, kopiowanie)
mogą zawierać interfejsy, funkcje składowe
i konstruktory z argumentami
są zawsze zapieczętowane
modyfikatory dostępu do pól
modyfikator
opis
public
dostępne zewsząd (domyślny)
private
tylko wewnątrz struktury / klasy
protected
dla klas dziedziczących
internal
tylko w pakiecie
protected
internal
dla klas dziedziczących w pakiecie
public struct Osoba
{
public string Imie;
public string Nazwisko;
public long Pesel;
}
Osoba Prezes;
Prezes.Imie = "Adam" ;
Prezes.Nazwisko = "Betoński" ;
Prezes.Pesel = 54031203287;
Osoba Emeryt ;
Emeryt = Prezes ;
pakowanie i rozpakowanie
object Agent = Emeryt;
// sterta, brak dostępu do pól
long kto = Agent.Pesel;
// błąd
Osoba X_007 = ( Osoba ) Agent ;
// stos, jest dostęp do pól
kto = X_007.Pesel;
// OK
public struct Komputer
{
public string Marka;
public short Cena;
public Komputer (string mm, short cc)
{
Marka = mm;
Cena = cc;
}
}
object PC = new Komputer ( "Alfa", 3000 );
short cc = PC.Cena;
// błąd
Komputer komp = (Komputer) PC;
cc = komp.Cena;
// OK
Tablice
jednowymiarowe
int [ ] Tab_A ; // zmienna referencyjna
Tab_A = new int [ 120 ] ;
// 0 ... 119
// automatyczne zerowanie
string [ ] Tab_B = new string [ X + 5 ] ;
// automatycznie NULL
string [ ] Tab_D =
new string [ 3 ] { "Alfa", "Beta", "Gamma" };
double [ ] Tab_C = { 1.2 , 4.5 , 4.4 } ;
//
Tab_A [ 0 ] = 55 ;
Tab_D [ 2 ] = "Jota" ;
// System.IndexOutOfRangeException
var T = new double[ ]{1.1, 2.2, 3.3};
// tylko jako tablica lokalna w funkcji
wielowymiarowe, pełne
int [ , ] Mat = new int [ 9 , 7 ] ;
Mat [ 3 , 5 ] = 121 ;
//
int [
,
] T23 = { {1, 2, 3}, {4, 5, 6} } ;
//
var T2 = new long [ , ] { { 10, 20, 30 },
{ 100, 200, 300 } };
// tylko jako tablica lokalna w funkcji
●
wielowymiarowe, niepełne
long [ ] [ ] Arr = new long [ 5 ] [ ] ;
// zadana liczba wierszy,
// zmienna liczba kolumn w wierszu
for ( int i = 0 ; i < Arr.Length ; ++i )
Arr [ i ] = new long [ i + 5 ] ;
Arr [ 2 ] [ 3 ] = 12212212234543 ;
kopiowanie tablic
int[] T = { 1, 3, 5, 7, 9 };
int[] R = new int [10];
R = T;
// kopiowanie referencji, R ma 5 elementów
T[0] = 99;
// zmiana wartości R[0]
R = (int[]) T.Clone();
T[1] = 88;
// kopia T
// R[1] bez zmian
int[] S = new int [10];
T.CopyTo( S, 2 );
// kopiowanie elementów T -> S od elementu 2
dziedziczenie z System.Array
właściwości
Length
Range : [ ] 0 ; [ , ] wie : 0, kol : 1
[ , , ] ma : 0, wie : 1, kol : 2
funkcje
BinarySearch , Clear , Clone, CopyTo
GetLength, GetLowerBound , GetUpperBound
GetValue , SetValue , Reverse , Sort
int x = 0;
Array A3D =
Array.CreateInstance(x.GetType(),12,15,24);
// Range = 0, 1, 2 : M, W, K
for (int i = A3D.GetLowerBound(0);
i <= A3D.GetUpperBound(0); ++i)
// M
for (int j = A3D.GetLowerBound(1);
j <= A3D.GetUpperBound(1); ++j)
// W
for (int k = A3D.GetLowerBound(2);
k <= A3D.GetUpperBound(2); ++k)
// K
A3D.SetValue((i * 100 + j * 10 + k),i,j,k);
Console.WriteLine("Multidimensional
Array:");
Console.WriteLine("Rank\tLower\tUpper");
for (int i = 0; i < A3D.Rank; ++i)
Console.WriteLine("{0}\t{1}\t{2}", i,
A3D.GetLowerBound(i),
A3D.GetUpperBound(i));
Multidimensional Array:
Rank
0
1
2
Lower
0
0
0
Upper
11
14
23
string [ ] Napisy = new string [ 10 ];
/* . . . . . . . . . . . */
foreach ( string s in Napisy )
{
Console.Writeline( s );
}
// interfejs IEnumerator jest dostępny
S1, MatMul, Taba, Ewide
Funkcje
tylko funkcje składowe klas
niepotrzebne deklaracje ( zapowiedzi )
modyfikatory argumentów
modyfikator
( brak )
out
ref
params
opis
przez wartość ( kopiowanie ) , argument
aktualny musi być zainicjowany
przez referencję, argument aktualny
może być niezainicjowany
przez referencję, argument aktualny musi
być zainicjowany
zmienna liczba parametrów
public long F ( long p1 , out int p2 ,
ref double p3 )
{
... = ... p1 ... p3 ... ;
...........
p2 = ....... ;
...........
p3 = ....p1 ... p2 ... ;
...........
return .... ;
}
long wynik , a1 = 229977446633 ;
int rezultat ;
double zmiana = 21.4E5 ;
wynik = F (a1 + 1L, out rezultat , ref zmiana);
/* nawet gdyby zmienna rezultat miała nadaną
wartość przed wywołaniem F, to i tak w funkcji F
nie wolno odczytywać tej wartości przed
wewnętrznym ustaleniem wartości p2 */
EwideF
dowolna liczba parametrów – params
public void DoLi (ref int Suma,
params int [ ] Liczby)
{
foreach (int li in Liczby)
Suma += li;
}
//
int Wynik = 174;
DoLi ( ref Wynik, 3, 5, 22, -7, 12);
// 209
wzorce funkcji ( generics )
public void PoLi <TyDa>(params TyDa [ ] Liczby)
{
foreach (TyDa li in Liczby)
Console.WriteLine(li.ToString());
// Suma + li;
niepoprawne
// jedynie przypisanie =
}
//
PoLi <double> (231.43, 99.89, - 15.2321);
public T Mała < T > (T p1, T p2)
where T : System.IComparable< T >
{
T pom;
if ( p1.CompareTo( p2 ) < 0 )
pom = p1;
else
pom = p2;
return pom;
}
//
p1 < p2 błąd
double x;
x = Mała <double> (231.43, 99.89);
wartości domyślne i argumenty nazwane ( 4.0 )
public long FU ( long p1 , bool p2 = true ,
double p3 = 2.7 )
{ ... }
//
long lili;
lili = FU ( 127 );
// poprawnie
lili = FU ( 127, false );
// poprawnie
lili = FU ( 127, false, 3.9 );
// poprawnie
lili = FU ( 127, , 3.9 );
// błąd
lili = FU ( 127, 3.9 );
// błąd
lili = FU ( 127, p3 : 3.9 )
// poprawnie
NamedPar, Refa
Klasy
public class Simple // partial abstract
{
public int Liczba = 9;
public static double Ułamek = 0.21 ;
string Napis ;
// private
sealed
// 0
public int Suma ( int Liczba )
{
return
this.Liczba + Liczba ;
}
public static double Mar( double Cena )
{
return Ułamek * Cena ;
}
public Simple ( )
// przeciążony k. domyślny
{
Liczba = 5 ;
}
// nie można listy powiązań
public Simple ( int Start )
{
Liczba = Start ;
}
public Simple ( Simple s );
{
Liczba = s.Liczba ;
}
}
Simple s0;
// tylko zmienna referencyjna
s0 = new Simple( );
// Liczba == 5
//
Simple s1 = new Simple( ) ;
//
==
5
Simple s2 = new Simple( 9 ) ;
//
==
9
s2.Liczba += s2.Suma( s1.Liczba ); // == 23
Simple s3 = new Simple( s2 ); //
== 23
//
int m = Simple.Mar( 100 ) ;
//
// funkcje i składowe statyczne
// wywołuje się podając nazwę klasy
== 21
modyfikatory dostępu (dla klas i dla składowych)
modyfikator
opis
public
dostępne zewsząd
tylko wewnątrz klasy
(domyślny dla składowych)
private
protected
internal
protected
internal
dla klas dziedziczących
tylko w pakiecie
(domyślny dla klas)
dla klas dziedziczących w pakiecie
klasy wieloplikowe
(2.0)
// plik Prog1.cs
public partial class Employee
{
public void DoWork() { }
}
// plik Prog2.cs
public partial class Employee
{
public void GoToLunch() { }
}
public partial class A { }
public class A { }
// błąd
//
ta sama przestrzeń nazw
niekonfliktowe modyfikatory typu klasy
( nie trzeba powtarzać )
public
private
protected
internal
abstract sealed
niekonfliktowa klasa bazowa i lista interfejsów
( nie trzeba powtarzać )
WinApp
klasy statyczne :
- nie wolno tworzyć obiektu
- wszystkie składowe statyczne
public static class Services
{
public static int Data1 = 123;
public static void Serv1(int param)
{ .... }
}
//
int Res1 = ++ Services.Data1 ;
Services.Serv1(78);
● inicjowanie obiektów klas (3.0)
public class Alfa
{
public int al;
public long fa;
/*
public Alfa( int a, long f)
{
al = a;
fa = f;
}
*/
}
//
Alfa aa = new Alfa { al = 7, fa = 14L };
// składowe public
//
Alfa bb = new Alfa { 7, 14L }; // błąd
public class Alfa
{
public int al;
public long fa;
private char kod;
//
public Alfa( char kk )
{
kod = kk + 5;
}
}
//
Alfa aa = new Alfa (0x41){ al = 7, fa = 14L };
// składowe:
private
//
protected
public
DrawRect
● funkcje rozszerzające (3.0) // Fun(ob) -> ob.Fun()
public static class StringExt // static
{
public static void Older03
(this System.String pt)
{ if (pt[0] > pt[3])
Console.WriteLine(pt[0]);
else
Console.WriteLine(pt[3]); }
public static char LetterOfIndex
(this System.String st, int x)
{ if (x < 0 || st.Length <= x)
return '?';
else return st[x]; }
}
string st = "Autobus.";
Console.WriteLine(st.Older03());
// przekład: Older03(st)
Console.WriteLine("{0}, {1}",
st.LetterOfIndex(4), st.LetterOfIndex(12));
// LetterOfIndex(st,4) LetterOfIndex(st, 12)
// o
// b, ?
using LibOne;
// biblioteka .dll
// ClassOne, int X
public static class LibOneExt
{
public static void Limit15
(this LibOne.ClassOne c1)
{
if (c1.X > 15) c1.X = 15;
}
}
//
ClassOne cc = new ClassOne();
cc.X = 27;
Console.Write(cc.X.ToString() + ",
");
cc.Limit15();
// Limit15(cc);
Console.WriteLine(cc.X);
//27, 15
Exten
Hermetyzacja
składowe prywatne i funkcje dostępu ( jak C++ )
właściwości
public class Account
{
private decimal amount ;
private string number ;
public decimal Total // zapis i odczyt
{
get { return amount ; }
set {
if ( Authorization ( ) )
amount = value ;
}
} // accessors
public string Who
// tylko odczyt
{
get { return number ; }
}
}
//
decimal AC ;
string NC ;
Account Customer = new Account ( ) ;
//
AC = Customer.Total ;
// get_Amount
Customer.Total = AC + 100 ;
// set_Amount
NC = Customer.Who ;
// get_Number
Edit encapsulation
public class Base1
{
private double price;
public double Price
{
get { return price; }
protected set { price = value; }
}
}
//
set dostępne w klasie Base1
i w klasach pochodnych
● właściwości automatyczne (3.0)
Auto-Implemented Properties
public class Point
{
/*
private int x;
private int y;
public int X {get { return x; }
set { x = value; } }
public int Y {get { return y; }
set { y = value; } }
//
public int X { get; set; }
public int Y { get; set; }
// nazwy zmiennym nadaje kompilator
}
*/
public class Point
{
public int X { get;
private set; }
public int Y { get; protected set; }
}
// nazwy zmiennym nadaje kompilator
// zmiana X tylko w klasie Point
// zmiana Y tylko w klasie Point
// i w klasach pochodnych
właściwości statyczne
private static string bankname = " PKO " ;
public static string BankName ;
{
get { return bankname ; }
set { bankname = value ; }
}
składowe tylko do odczytu
public readonly decimal Currency ;
public static readonly string AccType = "A1";
// nadawanie wartości tylko w deklaracji lub
// w konstruktorze klasy
Typy anonimowe (3.0)
public class Point
{
public int X { get; set; }
public int Y { get; set; }
}
//
var TTT = new {T1 = new Point { X = 4, Y = 4 },
T2 = new Point { X = 7, Y = 7 },
T3 = new Point { X = 2, Y = 2 } };
// klasa lokalna opisująca trójkąt
//
Console.WriteLine(TTT.GetType());
//f__AnonymousType0`3[CS3.Point,CS3.Point,CS3.Point]
Console.WriteLine(TTT.ToString());
//{ T1 = CS3.Point, T2 = CS3.Point, T3 = CS3.Point }
Wiązania dynamiczne ( 4.0 )
public object NowyKlient( ... )
{
object kli = null;
if ( ... )
kli = new Klient_A();
else
kli = new Klient_B();
...
return kli;
}
//
Klient_A nowy = (Klient_A) NowyKlient( ... );
if( nowy != null )
{
nowy.Nazwisko = "Nowak"; }
dynamic nowy
= NowyKlient( ... );
nowy.Nazwisko = "Nowak";
// poprawnie
nowy.NieistniejącaFunkcja ( );
// błąd wykonania (nie kompilacji)
również zmienne proste
dynamic liczba = 125.54;
double ile = liczba / 3.22 ;
// poprawne
liczba = "Napis";
// poprawne
char cc = liczba[0];
// 'N'
dynamiczne statyczne
Klient_B kli = new Klient_B();
dynamic dynKli = kli;
// statyczna do dynamicznej
Klient_B natręt = dynKli;
// dynamiczna do statycznej
Dyna
Przeciążanie operatorów
public class Line
{
public int Low , High ;
//
public static Line operator +
// op. binarny
( Line L1 , Line L2 )
{
int a , b;
a = L1.Low < L2.Low ?
L1.Low : L2.Low;
b = L1.High > L2.High ?
L1.High : L2.High;
return new Line { Low = a , High = b } ;
}
// musi być funkcja statyczna
public static int operator * (Line L1, int x)
// operator binarny
{
return
L1.Low * x;
}
}
//
Line L = new Line { Low = –2 , High = 7 } ;
Line K = new Line { Low = 0 ,
High = 9 } ;
Line LK = L + K ;
// ( -2 , 9 )
int Z = LK * 5 ;
// -10
public static Line operator + (Line db)
// operator unarny
{
return new Line { Low = db.Low,
High = db.High + 10 };
}
public static Line operator ++ (Line no)
// operator unarny, pre/post nierozróżnialne
{
return new Line {Low = no.Low – no.High,
High = no.High - 1 };
}
OpOver
Table 12-1. Overloadability of C# Operators
+, -, !, ~, ++, --, true, false
These unary operators can be overloaded.
+, -, *, /, %, &, |, ^, <<, >>
These binary operators can be overloaded.
==, !=, <, >, <=, >=
These comparison operators can be overloaded.
C# demands that “like” operators ( i.e., < and >,
<= and >=, == and != ) are overloaded together.
[]
The [ ] operator cannot be overloaded.
Use the indexer construct.
()
The () operator cannot be overloaded.
Use custom conversion methods.
+=, -=, *=, /=, %=, &=, |=,
Shorthand assignment operators cannot be overloaded;
^=, <<=, >>=
however, you receive them as a freebie when you
overload the related binary operator.
Andrew Troelsen, Pro C# 2010 and the .NET 4 Platform, Fifth Edition, Apress.
Indeksatory
class Zasobnik
{
public int[] dane = new int[100];
public int this[int ix]
{
get { return dane[ix]; }
set { dane[ix] = value; }
}
}
//
Zasobnik zz = new Zasobnik();
zz[9] = 15;
int alfa = zz[9];
Indexer
Definiowanie Konwersji
konwersja jawna
public static explicit operator Okrąg ( Odcinek oo )
{
Okrąg ok = new Okrąg();
if (oo.X > oo.Y)
{
ok.Sx = oo.X;
ok.Sy = oo.Y; }
ok.Sx = oo.Y;
ok.Sy = oo.X; }
else
{
ok.Pr = Math.Abs(oo.X + oo.Y);
return ok;
}
//
Okrąg oki = ( Okrąg ) odcinek;
// jawna
konwersja implikowana
public static implicit operator Okrąg ( Odcinek oo )
{
Okrąg ok = new Okrąg();
ok.Sx = oo.X;
ok.Sy = 0;
ok.Pr = oo.Y * oo.Y;
return ok;
}
//
Okrąg oki =
odcinek;
// implikowana
nie wolno w tej samej klasie zdefiniować obydwu
konwersji ale implikowana zastępuje jawną
CustConv
Relacja całość - część
public class Radio
{
private string Make ;
public void OnOff ( bool on ) { ... }
public Radio ( string name )
{
Make = name ;
}
}
public class Car
{
private string PetName ;
private Radio radio ;
public Car( string music , string name )
{
radio = new Radio ( music );
PetName = name ;
}
public MakeNoice ( bool on )
{
radio.OnOff ( on );
}}
Car MyFirst = new Car ( "Eltra", "Kaszel" ) ;
MyFirst.MakeNoice ( true );
Klasy zagnieżdżone
public class Car
{
private class Radio //(1)
{
public void OnOff ( bool on )
{if (on)
Console.WriteLine("Booom!"); }
}
private Radio radio = new Radio ( ); //(2)
}
// obiektów klasy Radio nie można tworzyć
// poza klasą Car (private)
Car.Radio rd = new Car.Radio();
// błąd
// po zmianie private -> public
(1)
public class Radio { ... }
//
Car.Radio rd = new Car.Radio();
rd.OnOff(true);
// Booom!
//
// po zmianie private -> public
(2)
public Radio radio = new Radio();
//
Car ca = new Car();
ca.radio.OnOff(true);
// Booom!
Dziedziczenie
public class Parent
{
public int a ;
public string b ;
public Parent ( int Va , string Vb )
{
a = Va ;
b = Vb ;
}}
public class Child : Parent
{
public long z ;
public Child
// pojedyncze
( int Va , string Vb , long Vz ) :
base ( Va , Vb )
{ z = Vz ;}
}
składowe public są dziedziczone jako public
składowe protected są dziedziczone jako private
składowe private nie są dziedziczone
//
klasy zapieczętowane
public sealed class Childless
{ ... }
public sealed class Grandson : Child
{ ... }
Funkcje wirtualne
public class Employee
{
protected decimal Payment = 1000 ;
public virtual void Bonus ( decimal X )
{ Payment += X ; }
}
public class Manager : Employee
{
public override void Bonus( decimal X )
{ Payment += 5 * X ; }
}
public class Proxy : Manager
{
public new void Bonus ( decimal X )
{
Payment += 700;
}
}
public class Boss : Manager
{
public override void Bonus(decimal X )
{ Payment += 12 * X ; }
}
Employee [ ] Team =
{
new Employee ( ) , new Manager ( ),
new Proxy ( ), new Boss ( )
} ;
for ( int i = 0 ; i < Team.Length ; ++i )
Team [ i ] . Bonus ( 100 );
// 1100 , 1500 , 1500 , 2200
Proxy wice = new Proxy ( ) ;
wice.Bounus ( 100 ) ;
// 1700
wywołanie funkcji wirtualnej z klasy bazowej
public override Draw ( )
{
............
base.Draw ( ) ;
..........
}
Wydaw
klasy abstrakcyjne i abstrakcyjne funkcje wirtualne
public abstract class Root
{
protected int alfa = 17;
public abstract void Print( );
}
public class Level1Node : Root
{
public override void Print( )
{
Console.WriteLine( alfa );
}
}
Finalizacja
public class Alfa
{
Alfa ( )
{
Console.WriteLine( "Oto jestem." ) ;
}
~Alfa ( )
// wywoływane przez gc
{
Console.WriteLine( "Dobranoc." ) ;
}
}
Zbieranie śmieci
generacje obiektów 0 , 1 , 2
funkcje System.GC
GC.Collect ( NrGeneracji ) //( )- wszystkie
GC.GetGeneration ( obiekt )
GC.MaxGeneration ( )
GC.SupressFinalize ( obiekt )
GC.ReRegisterForFinalize ( obiekt )
GC.GetTotalMemeory ( )
Fina
Pliki dyskowe i serializacja
przestrzeń nazw System.IO
informacje o plikach i katalogach
- abstrakcyjna klasa bazowa FileSystemInfo
Name
Attributes
Exists
-
CreationTime ...
klasy pochodne
FileInfo
DirectoryInfo
klasy
Directory
,
File
przetwarzanie katalogów klasa DirectoryInfo
DirectoryInfo dir1, dir2 ;
dir1 = new DirectoryInfo ( @"C:\MyApp" ) ;
dir2 = new DirectoryInfo ( "." )
// bieżący, zawierający *.exe
Create ( )
Delete ( )
GetDirectories ( )
GetFiles ( )
MoveTo ( )
DirInfo
przetwarzanie plików klasa FileInfo
Open( )
Delete( )
OpenRead( )
MoveTo( )
OpenWrite( )
parametry otwarcia pliku
FileMode.
Append
Create
Open
OpenOrCreate
FileAccess.
Read
ReadWrite
Write
FileShare.
None
Read
ReadWrite
Write
Truncate
wynikiem funkcji Open ( )
jest referencja obiektu klasy
FileStream
umożliwiającego zapis/odczyt do/z pliku
bez formatowania ( ciąg bajtów )
FileInfo ff = new FileInfo
(@"C:\Temp\Data.txt");
FileStream fs =
ff.Open (FileMode.Open , FileAccess.Read);
// albo
FileStream fs = new FileStream
("Plik.bin", FileMode.Open, FileAccess.Read);
właściwości i funkcje klasy FileStream
CanReed CanWrite CanSeek Length Position
Read ( )
ReadByte ( )
Write ( )
WriteByte ( )
Seek ( )
Flush ( )
Close ( )
// ciągi bajtów
byte [ ] TaBa = new byte [ 100 ];
//
for ( int i = 0 ; i < TaBa.Length ; ++i )
TaBa [ i ] = (byte) fs . ReadByte( );
// albo
fs.Read ( TaBa, 0, TaBa.Length );
fs.Seek(0L, SeekOrigin.Begin);
//
.Current
//
.End
// albo
fs.Position = 0;
for ( int i = 0 ; i < TaBa.Length ; ++i )
fs . WriteByte( TaBa[ i ]);
//
fs.Write(TaBa, 0, Taba.Length);
// albo
wykrywanie końca pliku
int Count = 0;
while (Count++ < fs.Length)
{ ..... }
// albo
if (fs.Position != fs.Length)
{ ..... }
zamykanie pliku
fs.Close( );
FileInfo
zapis/odczyt z formatowaniem klasy
Object
TextReader
TextWriter
StreamWriter
StreamReader
StringWriter
StringReader
BinaryReader
BinaryWriter
podstawowe funkcje
TextWriter
TextReader
Write ( )
Peek ( )
WriteLine ( )
Read ( )
Flush ( )
ReadLine ( )
Close ( )
ReadToEnd ( )
FileInfo fi = new FileInfo
( @"C:\Temp\Test.txt" ) ;
// klasa pochodna TextWriter
StreamWriter sw = fi . CreateText ( ) ;
// albo
StreamWriter sw = new StreamWriter("dane.txt");
//
//
klasa pochodna TextReader
StreamReader sr = fi . OpenText ( ) ;
// albo
StreamReader sr = new SteamReader("dane.txt");
int a = 398 ;
double x = 122.453E-42 ;
sw.WriteLine ( " Some text. " ) ;
// 1 arg
sw.Write ( a + " ") ;
sw.Write ( x.ToString ( ) ) ;
sw.Close ( ) ;
//
string str ;
str = sr.ReadLine ( ) ;
a = int.Parse ( sr.ReadLine ( ) ) ;
x = double.Parse ( sr.ReadLine ( ) ) ;
sr.Close ( );
wykrywanie końca pliku
sr.ReadLine() == null
// funkcja
// albo
sr.EndOfStream
// właściwość
StreamRW
podobnie
StringReader
StringWriter
StringWriter stw = new StringWriter();
stw.WriteLine("Tekst ćwiczebny.");
// 1 arg
stw.WriteLine( a );
stw.Close();
StringReader str =
new StringReader ( stw.ToString() );
string st = str.ReadLine();
a = int.Parse ( str.ReadLine ( ) ) ;
str.Close();
klasy
BinaryReader
BinaryWriter
BinaryWriter
BinaryReader
Write ( )
PeekChar ( )
Seek ( )
Read ( )
Flush ( )
ReadXXX ( )
Close ( )
Close ( )
XXX : Boolean, Byte, Bytes, Char, Chars,
Int16, Int32, Int64, Double, Decimal,...
BinaryRW
serializacja automatyczne zapisywanie /
odczytywanie obiektów klas do / z pliku
using System.Runtime.Serialization.
Formatters.Binary ;
using System.IO ;
//
[Serializable]
public class Radio
{
public string Make ;
[NonSerialized]
private int something ;
public bool On ;
}
// nie zapisywane
Radio radio = new Radio ( ) ;
radio.Make = "Aiwa" ;
radio.On = true ;
//
FileStream data = File.Create ("Radio.dat");
BinaryFormatter bifoter = new BinaryFormatter();
//
bifoter.Serialize ( data , radio ) ;
data.Close ( ) ;
//
data = File.OpenRead ( "Radio.dat" ) ;
Radio nn = (Radio)bifoter.Deserialize( data );
Seria
Klasy kolekcji
System.Collections
// usunąć Generics
klasy
ArrayList
// lista dowolnych obiektów
Queue
// kolejka FIFO
Stack
// stos LIFO
SortedList
// posortowana lista par
// <klucz, wartość>
Hashtable
// tablica par
// <klucz, wartość >
// kodowanie mieszające
ArrayList
// tablica dowolnych obiektów
Add, BinarySearch, Clear, Clone,
Contains, CopyTo, IndexOf, Insert,
Remove, Reverse, Sort
// funkcje
Capacity, Count
Queue
// właściwości
// kolejka FIFO
Enqueue, Dequeue, Peek,
Clear, Contains
// funkcje
Count
// właściwość
Stack
// stos LIFO
Push, Pop, Peek,
Clear, Contains
// funkcje
Count
// właściwość
SortedList
// lista par <klucz, wartość>
// posortowana
Add, Clear, ContainsKey, ContainsValue,
GetByIndex, IndexOfKey, IndexOfValue,
Remove, SetByIndex
// funkcje
Capacity, Count, Item
// właściwości
// KeyValuePair – klasa pomocnicza
Hashtable
// tablica par <klucz, wartość >
// kodowanie mieszające
Add, Clear, ContainsKey, ContainsValue,
Remove
// funkcje
Capacity, Count, Item
// właściwości
public class Auto
{
public string Name;
public double Price;
public Auto(string nn, double pp)
{
Name = nn;
Price = pp;
}
}
ArrayList al = new ArrayList();
al.Add ( new Auto("A", 100) );
al.Add ( new Auto("B",
20) );
Console.WriteLine("{0}, {1}",
((Auto)al[0].Price, ((Auto)al[1]).Price);
//
100,
20
SortedList sl = new SortedList();
sl.Add ( "zero",
new Auto("A", 100) );
sl.Add ( "jeden", new Auto("B",
20) );
//
Console.WriteLine("{0}, {1}, {2}, {3}",
((Auto)sl["zero"]).Price,
((Auto)sl["jeden"]).Price;
// 100, 20
//
((Auto)sl.GetByIndex(0)).Price,
((Auto)sl.GetByIndex(1)).Price);
//
20,
100
Wzorce klas kolekcji
generics, typy parametryczne, typy uogólnione
Dictionary <key, value>
SortedDictionary <key, value>
LinkedList <type>
// dwukierunkowa
List <type>
// jednokierunkowa
SortedList <key, value>
Queue <type>
Stack <type>
SortedList sl = new SortedList();
sl.Add(12, 5.5);
sl.Add("B", 9);
sl.Add("C", "alfa");
// kompilacja ok
// błąd wykonania, porównanie kluczy niemożliwe
SortedList <string, int> al =
new SortedList <string, int> ();
al.Add("X", 5);
al.Add("Y", 7);
al.Add("Z", 3);
al.Add(5,
2);
al.Add("K", 3.2);
// błąd kompilacji
// błąd kompilacji
//
Console.WriteLine("{0}, {1}, {2}",
al["X"], al["Y"], al["Z"]);
// 5, 7, 3
wzorce kolekcji we wzorcach funkcji
class Osoba
{
public string Imie;
public string Nazwisko;
public Osoba(string s1, string s2)
{
Imie = s1;
Nazwisko = s2;
}
public overrite string ToString( )
{
return Imie + " " + Nazwisko;
}
}
public void Dopisz <T> (List <T> li,
params T [ ] dane )
{
foreach ( T elem in dane )
li.Add( elem );
}
//
List <Osoba> lios = new List <Osoba>();
Dopisz(lios, new Osoba("Adam", "Kot"),
new Osoba("Anna","Kotka"));
foreach (Osoba os in lios)
Console.WriteLine( os );
Interfejsy
określają operacje realizowane przez klasę
lub jej cechy charakterystyczne
klasy abstrakcyjne zawierające deklaracje
funkcji abstrakcyjnych
public interface INodes_F
{
int GetNumberOfNodes ( ); }
// funkcja abstrakcyjna
// lub
public interface INodes_P
{
int Nodes {get; set;} }
// właściwość abstrakcyjna
public abstract class Shape
{
public int Nodes ;
public double Surface;
}
//
public class Hexagon : Shape , INodes_F
{
public int GetNumberOfNodes ( )
{
return 6 ;
}
}
public class Triangle : Shape , INodes_F
{
public int GetNumberOfNodes ( )
{
return 3 ;
}
}
//
public class Circle : Shape
{
...
}
Hexagon
hex = new Hexagon ( );
if ( hex is INodes_F ) .....
;
// test
//
INodes_F inodes1 = (INodes_F) hex ;
// InvalidCastException
INodes_F inodes2 = hex as INodes_F ;
// NULL
int NodesOfHex = inodes1.GetNumberOfNodes ( ) ;
zmienne reprezentujące interfejsy ( referencje )
mogą być parametrami funkcji
interfejs jako typ może być wynikiem funkcji
Dzie&Int
hierarchie interfejsów
interface IDrawBW
{
void DrawBW ( ) ;
}
interface IDrawGS : IDrawBW
{
void DrawGS ( ) ;
}
interface IDrawCR : IDrawGS
{
void DrawCR ( ) ;
}
public class Picture : IDrawCR
{
// implementacja funkcji
// DrawCR , DrawGS , DrawBW
}
//
Picture pp = new
//
IDrawCR iCR = pp
iCR . DrawBW ( )
iCR . DrawGS ( )
iCR . DrawCR ( )
Picture ( ) ;
as IDrawCr ;
;
;
;
Interfejsy standardowe
System.Collections
interfejsy
ICollection
IDictionary
IDictionaryEnumerator
IHashCodeProvider
IList
//
IEnumerable
IClonable
IComparable
IEnumerator
IComparer
przeglądanie kolekcji
Library EhRL = new Library ( 100000 ) ;
foreach ( Book bb in EhRL ) { ... } ;
// wymaga w IEnumerable oraz IEnumerator
// w klasie Library
public class Library : IEnumerable,
IEnumerator
{
private Book [ ] BookArr ;
// implementacja IEnumerable
public IEnumerator GetEnumerator ( )
{
return ( IEnumerator ) this ;
}
// implementacja IEnumerator
public void Reset ( ) { .... }
public bool MoveNext ( ) { ... }
public object Current
{
get { .... }
} }
-
iteratory
(2.0)
public class DaysOfTheWeek : IEnumerable
{ string[] m_Days = { "Sun", "Mon", "Tue",
"Wed", "Thr", "Fri", "Sat" };
public IEnumerator GetEnumerator()
{ for (int i = 0; i < m_Days.Length; i++)
yield return m_Days[i];
}
}
//
DaysOfTheWeek week = new DaysOfTheWeek();
foreach (string day in week)
System.Console.Write(day + " ");
Iterat
pełne kopiowanie
public class Point
{
public int x , y ;
public Point (int A , int B )
{
x = A ;
y = B ;
}
}
Point AA , BB ;
AA = new Point ( 5, 7) ;
BB = AA ;
// AA i BB wskazują ten sam
// obiekt na stercie (shallow)
// pełne kopiowanie wymaga ICloneable
public class Point : ICloneable
{
public int x , y ;
public Point (int A , int B )
{
x = A ;
y = B ;
}
public object Clone ( )
{
return new Point( this.x , this.y );
}
}
BB = (Point)AA.Clone();
// nowa kopia
sortowanie
public class Point : IComparable
{
public int X, Y;
public int CompareTo ( object ob )
// { < == > } -> { - 0 + }
{
Point temp = (Point) ob;
if ( this.X > temp.X )
return 1;
if ( this.X == temp.X )
return 0 ;
return -1;
}}
Point [ ] aP = new Point [ 100 ];
Array.Sort(aP);
// aP[3].CompareTo((object)aP[7])
SortP, Komis
interfejsy parametryczne, generics
ICollection < T >
IComparer < T >
IDictionary < TKey, TValue >
IEnumerable < T >
IEnumerator < T >
IEqualityComparer < T >
IList < T >
klasy, kolekcje i interfejsy parametryczne
public class Dict<KeyType, EleType >
where KeyType: IComparable<KeyType>
{
Dictionary<KeyType, EleType> dd =
new Dictionary<KeyType,EleType>();
public KeyType patt;
public void Add(KeyType key, EleType val)
{
if (key.CompareTo(patt) != 0 &&
!dd.ContainsKey(key))
dd.Add(key, val);
}
}
Dict<int, string> dis = new Dict<int,string>();
dis.patt = 25;
dis.Add(24, "alfa");
dis.Add(25, "beta");
dis.Add(26, "delta");
dis.Add(26, "gamma");
// {24, alfa}, {26, delta}
Delegacje
klasy, których obiekty udostępniają funkcje
klasy pochodne System.MulticastDelegate
Składowe klasy System.MulticastDelegate
składowa
opis
Method
nazwa funkcji zawartej w delegacji
Target
nazwa klasy, w której zdefiniowana jest funkcja
lub null dla statycznych
Combine( ), +, +=
dodanie funkcji
GetInvocationList
( )
lista funkcji zawartych w delegacji
Remove( ), -, -=
usunięcie funkcji
delegate double Fun(double x, out bool ok);
// nowy typ
// funkcje nazwane
double Sqrt(double x, out bool ok)
{ if ( x >= 0 )
{
ok = true;
return Math.Sqrt( x );
}
else
{
ok = false;
return 0;
}
}
//
double Log (double x, out bool ok)
{ ..............................}
double z, x = 4.3;
bool dobrze = true;
Fun funkcja = new Fun ( Sqrt );
// obiekt delegacji
// albo
Fun funkcja = Sqrt;
// wywołanie
z = funkcja ( x, out dobrze );
// sqrt
//
funkcja = Log;
z = funkcja ( x, out dobrze );
//
if (funkcja != null) ...
// log
tablice delegacji
Fun [] TabFun = new Fun[2];
TabFun[0] = new Fun(Sqrt);
TabFun[1] = Log;
// po ustaleniu indeksu
z = TabFun[indeks](x, out dobrze);
//
double [] Args = {2.34, 5.32};
double [] Results =
{
TabFun[0](Args[0], out dobrze);
TabFun[1](Args[1], out dobrze);
};
delegacje wielokrotne (multicast)
void AsIs(string s)
{
Console.WriteLine(s);
}
//
void Vers(string s)
{
Console.WriteLine(s.ToUpper( ));
}
//
delegate void Print2(string s);
//
Print2 Both = AsIs;
Both += Vers;
Both("Ala ma kota.");
// Ala ma kota.
// ALA MA KOTA.
//
Both -= AsIs;
Both("Ola ma psa.");
// OLA MA PSA
if (Both != null) ...
Dele, MulDele, EwideD
delegacje anonimowe (2.0)
button1.Click +=
// delegacja Click
delegate(System.Object o, System.EventArgs e)
{
MessageBox.Show("Click!");
};
//
delegate int Del( int x );
//
static int n = 79;
// składowa klasy
int m = 2;
// zmienna lokalna
Del d = delegate( int k )
{ return n + m + k + 3; };
//
int F = d(5);
// 89
Anonymous
kowariancja i kontrawariancja delegacji (2.0)
( covariance and contravariance )
class Mammal { ... }
// bazowa
class Dog : Mammal { ... }
// pochodna
//
public delegate Mammal Handler( ); // delegacja
public Mammal FirstHandler( )
{ return new Mammal( ); }
public Dog SecondHandler( )
{ return new Dog( ); }
Handler handler1 = FirstHandler;
Handler handler2 = SecondHandler;// kowariancja
public delegate void Vet ( Dog );
// delegacja
public void FirstHandler(Dog ds) { ... }
public void SecondHandler ( Mammal ms ) { ... }
//
Vet handler1 = FirstHandler;
Vet handler2 = SecondHandler;
// kontrawariancja
● wzorce delegacji (generics)
(3.0)
delegate R Fun <R, A>(A arg);
//
Fun <long, int> d1;
//
long FK (int x) { return (long)x + 1000000L; }
d1 = FK;
//
Fun <double, double> d2;
Fun <char, int> d3;
● wyrażenia lambda (funkcje nienazwane) (3.0)
- jeden argument
delegate R Fun <R, A>(A arg);
//
Fun <int, int> L1 = x => x * x + 1;
// λ x . x * x + 1
Console.WriteLine( L1(12) );
// 145
//
Fun <double, int> L2 = x => (double)x / 2 + 0.5;
//
Console.WriteLine( L2(7) ) ;
// 4,0
- wiele argumentów
delegate R Arg2 <R, A, B> (A x, B y);
//
Arg2 <long, int, char> suma =
(x,y) => (long)(x + y + 1);
Console.WriteLine(" Suma : " +
suma(15, 'A'). ToString());
// Suma : 81
Lambda
Use a delegate when:
-
An eventing design pattern is used.
-
The caller has no need access other properties,
methods, or interfaces on the object
implementing the method.
-
Easy composition is desired.
-
A class may need more than one implementation
of the method.
Use an interface when:
-
There are a group of related methods
that may be called.
-
A class only needs one implementation
of the method.
-
The class using the interface will want to cast
that interface to other interface or class types.
-
The method being implemented is linked
to the type or identity of the class: for example,
comparison methods.
Zdarzenia
zgłoszenie zdarzenia powoduje wywoływanie
wszystkich funkcji zawartych w delegacji
powiązanej z tym zdarzeniem
public class Car
{
private float Gas ;
public delegate void GasShortage
( string msg ) ;
public event GasShortage Yellow ;
public event GasShortage Red ;
public void SpeedUp ( double speed )
{
if ( Gas < 2 && Yellow != null )
Yellow ( "Only " +
Gas.ToString ( ) +
" gallons of gas !" );
if ( Gas < 0.5 && Red != null )
Red ( "Almost no gas !" ) ;
}
}
public class Driver
{
private Car MyCar = new Car( );
public void Driving ( )
{
MyCar.Yellow +=
new Car.GasShortage ( YellowLight );
MyCar.Red +=
new Car.GasShortage ( RedLight ) ;
}
public void Parking ( )
{ MyCar.Yellow -=
new Car.GasShortage ( YellowLight ) ;
}
public static void YellowLight
(string msg )
{
Console.WriteLine ( msg );
}
public static void RedLight
(string msg )
{
Alarm ( ) ;
Console.WriteLine ( msg );
}
}
Event, Loteria
Obsługa wyjątków
throw nazwa_wyjątku
// obiekt klasy dziedziczącej z System.Exception
try
{
......
}
catch ( typ_wyjątku )
{
......
}
..............
catch
{
......
// wszystkie wyjątki
}
finally
{
......
}
Exep
Zapytania ( 3.0 )
• wyrażenia zapytaniowe - querry expressions
• przestrzeń nazw LINQ - Language-Integrated Query
• 3 etapy :
1. określenie źródła danych,
2. utworzenie zapytania,
3. wykonanie zapytania.
class FirstLINQ
{ static void Main()
{
int[] numbers =
//
1. Data source.
new int[7] { 0, 1, 2, 3, 4, 5, 6 };
//
2. Query creation.
var numQuery =
from num in numbers
where (num % 2) == 0
select num;
// 3. Query execution.
foreach (int elem in numQuery)
{
Console.Write("{0} ", elem);
}}}
• technologie LINQ
•
Linq to Objects
•
Linq to DataSet
•
Linq to SQL
•
Linq to XML
•
Linq to own sources
IEnumerable
IEnumerable< >
IQueryable< > , IQueryProvider
• J. Matulewski, C# 3,0 i .Net. 3.5 Technologia LINQ,
Helion, 2008
• Przykłady :
http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
•
słowa kluczowe
from
// źródło danych
where
// filtrowanie danych
select
// pobieranie danych
join
// łączenie danych
orderby
// sortowanie danych
ascending
// rosnąco
descending
// malejąco
let
// nadanie wartości
group
// grupowanie danych
into
// kontynuacja zapytania
on
// połącz tabele
equals
// równość pól
• funkcje rozszerzające IEnumerable, IEnumerable< >
Select, SelectMany
// pobieranie danych
OrderBy, ThenBy, OrderByDescending,
ThenByDescending, Reverse
// sortowanie
Where
// filtrowanie
Aggregate, Average, Count, LongCount,
Max, Min, Sum
// artymetyczne
Cast, OfType, ToArray, ToDictionary, ToList,
ToLookup, ToSequence
// konwersja
Element, DefaultIfEmpty, ElementAt,
ElementAtOrDefault, First, FirstOrDefault,
Last, LastOrDefault,
Single, SingleOrDefault // pobieranie elementu
EqualAll
// porównywanie
Empty, Range, Repeat
// tworzenie
GruopBy
// grupowanie
GroupJoin, Join
// łączenie
Skip, SkipWhile,
// pomijanie
Take, TakeWhile
// wybór
All, Any, Contains
// kwantyfikatory
Concat, Distinct, Exept,
Intersection, Union
// operacje na zbiorach
• Linq to Objects
->
• Linq to own sources
Linq1
->
Linq2
Współbieżność
przestrzeń nazw System.Threading
klasa Thread tworzenie ścieżek i zarządzanie
ich wykonywaniem
główne funkcje
Start
Suspend
Sleep
Resume
Abort
GetHashCode
główne właściwości
CurrentThread
Priority
Name
ThreadState
IsBackGround
IsAlive
priorytety ścieżek
Lowest
BelowNormal
AboveNormal
Normal
Highest
ścieżki pierwszoplanowe i drugoplanowe
( ForeGround / BackGroung Threads )
– dopóki istnieje przynajmniej jedna ścieżka
pierwszoplanowa aplikacja nie jest zamykana przez CLR
– po zakończeniu ostatniej ścieżki pierwszoplanowej
CLR kończy wszystkie aktywne jeszcze ścieżki
drugoplanowe
public class Worker
{
public bool EndOfWork = false ;
public void DoWork ( )
// funkcja ścieżki
{ Console.WriteLine ("Worker's ID is {0}\n" +
"Worker's name is {1}",
Thread.CurrentThread.GetHashCode ( ) ,
Thread.CurrentThread.Name ) ;
for ( int i = 0; i < 1000 && !EndOfWork
; ++i )
{
}
Console.WriteLine ( i ) ;
Thread.Sleep ( 500 ) ;
}
// End of Worker
static void Main ( string [ ] args )
{
Worker ww = new Worker ( ) ;
Thread job =
new Thread( new ThreadStart( ww.DoWork ));
// delegacja ThreadStart
// funkcja bezargumentowa
job.Name = "Ben" ;
job.Start ( ) ;
Thread.Sleep ( 5000 );
job.Suspend ( ) ;
ww.EndOfWork = true ;
job.Resume ( ) ;
}
// funkcje z argumentami
class AddParams
// klasa argumentu
{
public int a, b;
public AddParams(int numb1, int numb2)
{
a = numb1;
b = numb2;
}
}
class Program
{
void Add(object data)
// funkcja ścieżki
{
if (data is AddParams)
{
AddParams ap = (AddParams)data;
Console.WriteLine("{0} + {1} is {2}",
ap.a, ap.b, ap.a + ap.b);
}
}
void Run ( )
{
AddParams ap = new AddParams(10, 10);
Thread t = new Thread(
new ParameterizedThreadStart(Add));
t.Start(ap);
// przyśnij, aby druga ścieżka
// zakończyła pracę
Thread.Sleep(50);
}
}
ParamThread
asynchroniczne wykonywanie delegacji
public delegate int BinaryOp(int x, int y);
int Add(int x, int y)
{
Thread.Sleep(5000);
return x + y;
}
//
BinaryOp b = new BinaryOp(Add);
// wywołanie synchroniczne, ta sama ścieżka
int answer = b(10, 10);
// lub
int answer = b.Invoke(10, 10);
// asynchronicznie, odrębna ścieżka
BinaryOp b = new BinaryOp(Add);
// Start secondary thread
IAsyncResult iftAR =
b.BeginInvoke(10, 10, null, null);
// Do other work on primary thread...
int answer = b.EndInvoke(iftAR);
Console.WriteLine("10 + 10 is {0}.", answer);
AsyncDel
// funkcje zwrotne
bool Ready = false;
void AddComplete(IAsyncResult itfAR)
{
Console.WriteLine("Your addition is ready");
Ready = true;
}
//
IAsyncResult iftAR = b.BeginInvoke(10, 10,
new AsyncCallback(AddComplete), null);
while (!Ready)
{ // other work is performed here... }
int answer = b.EndInvoke(iftAR);
AsyncCall
wykonywanie cykliczne
void PrintTime(object state)
{
Console.WriteLine("Time is: {0}",
DateTime.Now.ToLongTimeString());
}
TimerCallback timeCB =
new TimerCallback(PrintTime);
Timer t = new Timer(timeCB, null, 0, 1000);
// delegacja, parametr,
// opóźnienie startu, interwał
// ścieżka drugoplanowa
Timer
synchronizacja dostępu
do obiektów współużytkowanych
─
lock
( słowo kluczowe )
─ System.Treading.Semaphore
─ System.Treading.Mutex
─
System.Treading.Monitor
─
System.Treading.Interlocked
─ synchronizacja za pomocą zdarzeń
─
atrybut wykluczania
public class SharedData_1
{
private Records [ ] DataBase ;
object UpdateLock;
public Update ( string str )
{
lock ( UpdateLock )
{
........... // aktualizacja
}
}
}
Adders
public Semaphore sem1 = new Semaphore (
init_val, max_val ); // count = init_val
public class SharedData_2
{
private Records [ ] DataBase ;
public Update ( string str )
{ sem1.WaitOne( );
// if ( count != 0 ) --count; else
........... // aktualizacja
sem1.Release( ); // ++count;
}
} // ścieżki nie są identyfikowane
wait;
public Mutex mut1 = new Mutex ( );
public class SharedData_2
{ private Records [ ] DataBase ;
public Update ( string str )
{
mut1.WaitOne( );
...........
// request ownership
// of a mutex
// updating
mut1.ReleaseMutex( ); // release ownership
}
} // ścieżki są identyfikowane
public class SharedData_3
{
private Records [ ] DataBase ;
object UpdateObject;
public Update ( string str )
{
try
{
Monitor.Enter
( UpdateObject )
........... // aktualizacja
}
finally
// zawsze się wykona
{
Monitor.Exit ( UpdateObject ) ;
} }
}
// .TryEnter
.Wait()
.Pulse()
public class MainCounter
// Interlocked
{
private long Counter = 0;
public void Inc ( )
// + 1
{
Interlocked.Increment( ref Counter );
}
public void Dec ( )
// - 1
{
Interlocked.Decrement( ref Counter );
}
public void Exch ( ref Value )
//
{
Interlocked.Exchange( ref Counter,
ref Value );
}
public void CompExch ( val1, val2 )
{
Interlocked.CompareExchange
( ref Counter, val1, val2 );
}
// if (Counter == val1)
//
}
Counter = val2;
synchronizacja ścieżek za pomocą zdarzeń
─
ManualResetEvent
(true / false)
─
AutoResetEvent
(true / false)
─
Reset()
─
Set()
true
─
WaitOne()
false
:
Manual
bz
Auto
false, gdy było true
ResetEvent
atrybut wykluczania Synchronization
using System.Runtime.Remoting.Contexts;
//
Thread safe
[Synchronization]
class Services : ContextBoundObject
{
public void Read ( ... ) { ... }
public void Print ( ... ) { ... }
public void Update ( ... ) { ... }
}
// wszystkie funkcje wykonywane niepodzielnie
pula ścieżek CLR
─ powołanie nowej ścieżki ( async delegate )
powoduje uruchomienie jednej z oczekujących
ścieżek utworzonych dla programu przez CLR
─ można do kolejnych ścieżek puli przypisywać
funkcje do wykonania ( poprzez delegację
WaitCallback ) - ścieżki drugoplanowe
public class Printer
{
public void PrintNumbers()
{
}
... }
Printer prin = new Printer();
WaitCallback workItem = new
WaitCallback(PrintTheNumbers);
// Queue the method ten times.
for (int i = 0; i < 10; i++)
ThreadPool.QueueUserWorkItem(workItem, prin);
//
void PrintTheNumbers(object state)
{
Printer task = (Printer)state;
task.PrintNumbers();
}
ResetEventPool, PrinterPool
współbieżne wykonywanie zadań
TPL – Task Parallel Library
using System.Threading.Tasks;
─ współbieżne przetwarzanie rozłącznych zbiorów danych
Parallel.For ( from, to, action )
Parallel.ForEach ( data_source, action )
// również z dodatkowymi parametrami
Parallel.For ( 0, 4, DoWork );
// powołanie 5 ścieżek, z których każda
// wykonuje funkcję zawartą w delegacji DoWork
DataPara
─ współbieżne obliczenia
Parallel.Invoke( action [ ] ac_list)
// powołanie dla każdej akcji z ac_list
// ścieżki wykonującej tę akcję
─ przerwanie wykonania wszystkich ścieżek
CancelationToken
TaskPara
współbieżne zapytania PLINQ
AsParallel()
WithCancellation()
WithDegreeOfParallelism()
//
private CancellationTokenSource cancelToken =
new CancellationTokenSource()
//
cancelToken.Cancel();
int[] modThreeIsZero = null;
// source – vector of integers
try
{
modThreeIsZero =
(from num in source.AsParallel().
WithCancellation(cancelToken.Token)
where num % 3 == 0
orderby num descending
select num).ToArray();
}
catch (OperationCanceledException ex)
{
Console.WriteLine( ex.Message );
}
ParLinq
Przestrzeń nazw
łączy zdefiniowane typy
( klasy, struktury, delegacje, zdarzenia, wyliczenia)
using System ;
namespace MySpace
{
public class Alfa { ... }
public class Beta { ... }
.........
}
gdy definicje klas w kilku plikach
należy powtórzyć deklarację namespace
korzystanie z przestrzeni nazw w innej przestrzeni
using System ;
using MySpace ;
namespace NextSpace
{
public class Alfa_1 : Alfa
{ ..... }
public class Alfa_2 : MySpace.Alfa
// gdy konfliktowe nazwy
{ .... }
}
przestrzeń nazw definiująca stałe
namespace Constants
{
public sealed class CT
{
public static readonly double
pi = 3.1415926536 ;
public static readonly double
e = 2.7182818285 ;
private CT( ) {}
}
}
using Constants ;
double radius = 23.4 ;
double perimeter = 2.0 * CT.pi * r ;
Pakiety i odzwierciedlenie ( refleksja ) typów
pakiet ( assembly )
─
aplikacja
─
biblioteka
Manifest
Metadane Typów
CIL
Zasoby
.......
składniki przestrzeni nazw System.Reflection
Klasa
Opis
Assembly
wczytanie pakietu, analiza manifestu lista
typów ( klas , struktur )
AssemblyName
MethodInfo
wersja, ustawienia regionalne
opis funkcji składowej
ParameterInfo
opis parametru
PropertyInfo
opis właściwości
FieldInfo
opis danej składowej
tworzenie biblioteki .dll
typ projektu: Class Library
np. CarTuneUpLib
public
CarTuneUpLib.dll
Garage : WashCar() ,ChangeOil() ...
korzystanie z biblioteki
za pomocą Add Reference
dodać bibliotekę CarTuneUpLib
//
using CarTuneUpLib ;
public static int Main ( string [ ] args )
{
Garage BlueNut = new Garage ( ) ;
BlueNut.ChangeOil ( ... ) ;
............. }
dynamiczne ładowanie biblioteki
using System ;
using System.Reflection ;
using System.IO ;
Assembly a = Assembly.Load ( "CarTuneUpLib" );
// CarTuneUpLib.dll tam gdzie .exe
// klasy
Type [ ] Classes = a.GetTypes( );
// odczytywanie składowych
Type ctulg = a.GetType("CarTuneUpLib.Garage");
MemberInfo [ ] mi = ctulg.GetMembers( );
// podobnie parametry funkcji
dynamiczne wywoływanie funkcji
// tworzenie klasy
object obj = Activator.CreateInstance( ctulg );
//
MethodInfo wash = ctulg.GetMethod( "WashCar" );
wash.Invoke( obj, null );
// bezargumentowa
//
object [ ] TabPar = { par1, par2, ... };
xxx.Invoke ( obj, TabPar );
// z argumentami
pakiety prywatne i współużytkowane
( Global Assembly Cache )
wersje pakietów współużytkowanych a.b.c.d
─
a : główny numer wersji
─
b : podrzędny numer wersji
─
c : numer kolejny kompilacji
─
d : liczba szybkich poprawek
gdy różne a lub b wersja nieodpowiednia