Professional Documents
Culture Documents
Chapitre
1………………………………………………………………………………
…... 7
Installation et introduction
………………………………………………………………….7
Histoire de C#
……………………………………………………………………………….
7
Pourquoi C#
….……………………………………………………………………………
…7
Lancer C# sur
Windows..……………………………………………………………………
7
Chapitre
2………………………………………………………………………………
…….9
Classes et programmation des objets
connectés…………………………………………...12
Classes
basiques………………………………………………………………………
……12
Propriétés..…………….……………………………………………………
……………..14
Constructors et
destructors ………………………………………………………………..19
Héritage………………………………………………………………………
……………….24
Résumé………………………………………………………………………
……………….25
Quiz de fin de
chapitres……………………………………………………………………
…27
Réponses……………………………………………………………………
………………..28
Chapitre
3………………………………………………………………………………
…..29
Structures de classes
avancées…………………………………………………………….29
Polymorphisme…
…………………………………………………………………………..29
Interfaces……………………………………………………………………
………………35
Exercices
………………………………………………………………………………
……37
Quiz de fin de
chapitre………………………………………………………………………
41
Réponses……………………………………………………………………
……………….41
Chapitre 4
………………………………………………………………………………
…43
Fonctionnalité
intermédiaire……………………………………………………………. 43
Exercice………………………………………………………………………
…………….44
Expression régulière
………………………………………………………………………46
Directive du pré-
processeur….…………………………………………………………….52
Gestions des
exceptions….………………………………………………………………..5
5
Questions de fin de
chapitre………………………………………………………………59
Réponses….…………………………………………………………………
……………59
Chapitre 5
………………………………………………………………………………
…60
Programme
formateur……………………………………………………………………
60
Caractéristiques
……………………………………………………………………………60
Réflexion……………………………………………………………………
……………...65
Métadata… …………………………………………………………………
……………..65
Indexeurs
………………………………………………………………………………
….67
Collection……………………………………………………………………
…………..72
Génériques…………………………………………………………………
…………….75
Question de fin de
chapitre………………………………………………………………79
Réponses……………………………………………………………………
……………79
Chapitre
6………………………………………………………………………………
..79
Processus et
fonctionnalités……………………………………………………………..8
0
Déléguées.
………………………………………………………………………………..
80
Méthodes
anonymes…………………………………………………………………….
..84
Evénements…………………………………………………………………
……………86
Multithreading………………………………………………………………
……………88
LINQ…………………………………………………………………………
…………..95
Exercices….…………………………………………………………………
…………..97
Questions de fin de
chapitre……………………………………………………………..99
Réponses
….…………………………………………………………………………….
.99
Chapitre 1
Installation et introduction
Histoire de C#
Jan 2002
C# 1.0
-Type safe programming language
-Modern
- OOP (Object Orientated Programming)
Nov 2005
C# 2005
-Generics
-Partial classes
-Anonymous types
-Iterators
-Nullable types
-Static classes
Nov 2007
C# 2007
-Improvements of previous additions
-Extensions methods
-Expression trees
-Partial methods
April 2010
C# 4.0
-Dynamic binding
-Naming and optional arguments
Aug 2012
C# 5.0
-Asynchronous Programming
A huge addition allowing programmers to create multithreaded
applications
-Caller info attributes
July 2015
C# 6.0 (Version in this tutorial)
-Exception filters
-String interpolation
-Static type members into namespaces
-Complier as a service
Pourquoi C# ?
C# possède beaucoup d’avantages par rapport aux autres langages
similaires comme Java ou Python.
C # est un type incroyablement sûr, ce qui signifie que lorsqu'une
variable est créée, un type doit être défini, ce qui signifie qu'un
autre type ne peut pas être logé dans cette variable.
C# possède un contrôle totale sur les fuites de mémoire qui sont
une grande inquiétude pour beaucoup de programmeurs C++
C# fournit une librairies riche de propriétés ce qui permet
d’implanter des propriétés en plus simple et directe.
N’importe quel système avec .NET framework lancera
l’application. Cependant, le cadre est supporté principalement sur
Windows, ce qui signifie que les supports Linux ou Mac sont
presque ou entièrement non-existants
Utilisateurs de Mac :
Classes basiques
}
Avec toutes ces variables et fonctions définis dans les parenthèses, une
version étoffée ci dessous
class Book
{
public Book(int numberOfPages, int currentPage, string colour, string
name)
{
_numberOfPages = numberOfPages;
_currentPage = currentPage;
_colour = colour;
_name = name;
}
}
Il y a plusieurs choses à noter. Les fonctions dans la boite sont connues
come Constructors (expliqué dans ce chapitre), il est appelé lors de la
création d’un nouvel objet. Cette classe contient toutes les variables et les
fonctions membres, qui sont tous les deux accessibles en utilisant
l'opérateur membre. Dans ce cas toutes les variables sont marqués comme
« privé » , signifiant qu’on ne peut y accéder en dehors de la classe, c’est là
que getters et setters ( Acessors methods) entrent en usage, la fonction
« returnCurrentPage » est une getter ? et vous permet d’accéder à la valeur
de la page en cour , c'est la manière recommandée de gérer l'accès aux
variables, cela permet au programmeur de contrôler l'accès aux variables.
class Program
{
static void Main(string[] args)
{
Book book1 = new Book(200, 32, "Red", "Harry Potter");
book1.changeMe = "Test";
Console.WriteLine(book1.changeMe);
Recap :
Les classes fournissent une manière intuitive de stocker les
données sur des objets du monde réels.
Ils permettent de construire des fonctionnalités autour des
données.
Elles sont utilisées comme une façon de faire des tas de
conteneurs pour les données.
Accesor methods permette l’accès pour modifier la valeur.
Propriétés :
Et appelé ainsi :
Cela revient à :
Une utilisation plus avancée de setter pourrait être de valider l’input ?. Par
exemple, vous ne pouvez pas avoir la page en cours qui est plus large que le
nombre total de pages. Le code ressemble donc à cela :
class Book
{
int totalPages = 500;
public int currentPage
{
get
{
return currentPage;
}
set
{
//Validation check
if (value < totalPages)
{
currentPage = value;
}
else if(value == totalPages)
{
Console.WriteLine("You've finished the book!");
}
else
{
//Error message
Console.WriteLine("Invalid current page!");
}
}
}
}
Cela donne au programmeur la possibilité d'écrire du code qui tient compte
de nombreuses possibilités.
Static :
Comme mentionné dans le chapitre précédent, les fonctions membres
permettent aux classes de contenir les fonctionnalités qui sont en quelques
sorte relié aux données contenus dedans, ce qui permet aux classes d’être
presque des programmes autonomes avec les membres variables qui
donnent aux classes leur fonctionnalité.
namespace ConsoleApplication1
{
//
class Program
{
static void Main(string[] args)
{
Example e = new Example();
e.Instance();
e.Static() //Error
Example.Instance(); //Error
Example.Static();
}
}
class Example
{
public void Instance()
{
Console.WriteLine("Instance!");
}
public static void Static()
{
Console.WriteLine("Static!");
}
}
}
namespace ConsoleApplication1
{
//
class Program
{
static void Main(string[] args)
{
int i = Person.WorkOutAge(new DateTime(1990, 10, 15));
Console.WriteLine(i);
}
}
class Person
{
public Person(string _name, int _age)
{
name = _name;
age = _age;
}
return (int)years;
}
}
}
Ce programme utilise une méthode statique pour calculer l’âge d’une
personne en utilisant leur date de naissance, ce qui permet à la méthode de
contenir des fonctions révélatrices sans en séparée une crée par instance.
Connectors et Destructors :
class Person
{
public Person()
{
Console.WriteLine("Person created");
}
}
Vous pouvez aussi avoir autant de constructors que vous voulez, cependant
ils ont tous besoin de différents types de paramètres et de nombres de
paramètres (ceci est connu comme une fonction signature) donc avec les
exemples ci dessous je ne pourrais pas définir d’autre constructors sans
paramètres, ceci est connu comme une surcharge (= overloading).
Par exemple :
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Person p1 = new Person("John", 32);
Person p2 = new Person("James", 50, "Train Driver");
}
}
class Person
{
public Person(string _name, int _age)
{
name = _name;
age = _age;
job = "N/A";
}
public Person(string _name, int _age, string _job)
{
name = _name;
age = _age;
job = _job;
}
}
}
La section surlignée montre l’utilisation de la surcharge, le compiler détecte
automatiquement quel constructor utiliser en fonction des types dans la liste
de paramètres.
class Person
{
~Person()
{
Console.WriteLine("Person deleted!");
}
}
Cette méthode ne peut être appelée manuellement mais est gérée par
l’interne Garbage Collector qui est construit en partie par le compiler crée
par le management de mémoire automatique.
Cela peut être démontré ainsi, si la méthode est appelée et qu’il crée une
instance à la Personne et qu’ensuite le programme sort de la portée de la
méthode principale, le garbage collector sera appelé pour nettoyer la
mémoire.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Function();
class Person
{
~Person()
{
Console.WriteLine("Person deleted!");
Console.ReadKey();
}
}
}
Output
>Person deleted!
Exercice :
Créez une classe qui contient les données pour Pets, la classe aura besoin
d’un nom, un âge et un type d’animal. Il y aura aussi besoin d’un
Cosntructor d’un destructor et d’un membre fonction qui imprime toutes les
données pour l’animal.
Le tester en ayant un chien appelé Jose qui a un 1 an, un chat appelé Besse
qui a cinq ans et un perroquet appelé James qui a 10 ans.
Solution :
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Pet p1 = new Pet("Jose", 1, "Dog");
p1.Print();
Console.ReadKey();
}
}
class Pet
{
public Pet(string _name, int _age, string _type)
{
name = _name;
age = _age;
type = _type;
}
Héritage :
L’héritage est une fonction de langage qui permet aux classes de prendre en
compte les caractéristiques d’un autre, l’héritage est fait de cette façon :
Ce qui signifie que n’importe quel fonction ou variable est marquée comme
« Publique » ou « Protégé » (protégé est expliqué dans le chapitre suivant).
Le chien aura sa propre version pour y accéder, ce qui permet de créer
rapidement de nouveaux types de classes sans répéter la fonction et la
définition des variables.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Dog d1 = new Dog("Rocko", 3, "Blue One", "Red");
d1.PrintName();
}
}
class Animal
{
public Animal(string _name, int _age)
{
name = _name;
age = _age;
}
L’encapsulation :
Nous en avons vu trois auparavant mais dans cette section, nous irons plus
dans les détails à propos des sections ci dessous :
Publique
Protégée
Privé
Interne
Protection interne
Publique :
Publique vous permet simplement un accès total à tout les objets membres.
Par exemple :
class Program
{
static void Main(string[] args)
{
Public p = new Public();
class Public
{
public int value;
}
Privée :
C’est l’opposé complet de publique ou les appels internes à une variable
sont autorisés, ce qui signifie qui si nous voulons changer une variable nous
devons utiliser la fonction accesor
class Program
{
static void Main(string[] args)
{
Private p = new Private();
//Error here!
p.value = 3;
}
}
class Private
{
private int value;
}
Protégé :
Protégé est un petit peu différent, cela implique l’héritage lorsqu’une classe
hérite des fonctions et des variables d’un autre mentionné précédemment.
Interne :
Protection interne :
Note :
Vous pensez peut-être et si un modificateur d'accès n'est pas spécifié? Et
bien dans ce cas (et c’est totalement valide), par défaut cela sera privé.
Réponses
Polymorphisme
Statique polymorphisme
Fonction overloading
//Printing integer
i.Print(1);
//Printing float
i.Print(2.0f);
//Printing double
i.Print(4d);
//Printing long
i.Print(4L);
}
}
class Interface
{
string printStr = "Print!";
public void Print(int i)
{
Console.WriteLine(i);
}
Dynamique overloading :
C# permet la création d’une classe abstraite ; une classe abstraite peut agir
comme un modèle ou un design pour d’autres classes pour hériter et
s’adapter pour les circonstances pour lesquelles elles sont crées. Ensuite les
classes dérivées peuvent prendre des fonctions abstraites et adapter leurs
comportements, cependant il y a des règles à propos des classes abstraites :
Vous ne pouvez pas créer directement une instance d’une classe
abstraite
Vous ne pouvez pas déclarer une méthode abstraite qui n’est pas
logé dans une classe abstraite
Il y a aussi un mot clé connu comme « sealed » et les classes
scellées ne peuvent être hérité, par conséquent les méthodes
abstraites ne peuvent être définis comme scellées.
Ci dessous un exemple qui montre l’utilisation d’une classe abstraite :
using System;
namespace ConsoleApplication1
{
abstract class Shape
{
public abstract int Volume();
//Creates a 2D Rectangle
class Rectangle : Shape
{
public Rectangle(int w, int h)
{
height = h;
width = w;
}
//Creates a 3D Cylinder
class Cylinder : Shape
{
public Cylinder(int w, int h)
{
height = h;
width = w;
}
class Program
{
static void Main(string[] args)
{
Rectangle rec = new Rectangle(10, 10);
Console.WriteLine(rec.Volume());
Console.ReadKey();
}
}
Quelques petites choses à noter dans cette partie entourée par le rectangle
est la définition de la classe abstraite, ou un volume de classe abstraite est
défini, ceci est ensuite pris dans les autres méthodes et est surchargé,
remarqué que le mot-clé « surcharge » qui est utilisé pour créer une
définition customisé du Volume() où chaque classe possède une conception
customisée par Volume appelé qui est ensuite appelé dans la méthode
principale. Une classe abstraite requiert que la méthode qui hérite doit créer
une version surchargée. Ce qui signifie que les classes abstraites sont
conçues pour être des plans très stricts pour la forme et la disposition d'une
méthode.
using System;
namespace ConsoleApplication1
{
class Human
{
public virtual void SayHello()
{
Console.WriteLine("Hello!");
}
}
class Program
{
static void Main(string[] args)
{
American a = new American();
a.SayHello();
Console.ReadKey();
}
}
}
Interfaces
Les interfaces sont très structurées, ils sont une copie bleue que chaque
méthode héritée doit suivre, un peu comme un contrat. Une interface est un
peu comme une classe abstraite mais comment une classe abstraire peut
hériter et être étendu alors qu’une interface doit juste être implanté. Les
interfaces permettent la séparation des définitions de fonctions depuis
l’implantation et améliorer la lisibilité et le design.
Une interface est définie comme chaque méthode ou propriété qui doit être
créer est poser dans une sorte de liste, une interface ne peut pas contenir
d’implémentation.
interface ITransaction
{
//Methods
void Process();
}
interface IVehicle
{
string Colour { get; }
string EngineType { get; }
int NumberOfWheels { get; }
int Gas { get; }
void StartEngine();
void StopEngine();
}
Comme vous pouvez le voir, « Car » doit implanter tous les items définis
dans l’interface IVehicle, ce qui donne une sorte de « plug and play » effet
lorsque vous créez de nouvelles classes qui concernent les véhicules car le
design et layout est très renforcé.
Exercice :
Solution
Namespaces :
Les namespaces sont utilisés pour séparer les définitions, cela fait que les
noms définis dans un espace de noms ne sont pas en conflit avec un autre.
}
Et pour appeler une autre fonction de namespace vous devez utiliser les
membres opérateurs de cette manière :
using System;
namespace ConsoleApplication1
{
class Program
{
public class SameName
{
public void Function()
{
Console.WriteLine("Main!");
}
}
Console.ReadKey();
}
}
}
namespace Namespace1
{
public class SameName
{
public void Function()
{
Console.WriteLine("Namespace1!");
}
}
}
Output
>Main!
>Namespace1!
using System;
Cela est apparu sur le dessus de certains extraits de code, c’est simplement
le programme qui vous indique d’utiliser le « System » namespace pour des
items comme
Console.WriteLine("");
Et
Console.ReadKey();
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Namespace1.Class c = new Namespace1.Class();
c.Function();
Console.ReadKey();
}
}
}
namespace Namespace1
{
public class Class
{
public void Function()
{
Console.WriteLine("Namespace1!");
}
}
}
En utilisant le segment : b
using System;
using Namespace1;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Class c = new Class();
c.Function();
Console.ReadKey();
}
}
}
namespace Namespace1
{
public class Class
{
public void Function()
{
Console.WriteLine("Namespace1!");
}
}
}
Réponses :
Fonctionnalité intermédiaire
Opérateur overloading
Dans cet exemple nous allons créer une classe appelé « Grade » et
surchargé le plus opérateur. Un opérateur overloader est défini comme :
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Grade a = new Grade(30);
a.Print();
Grade c = a + b;
c.Print();
Console.ReadKey();
}
}
class Grade
{
int mark;
public Grade(int m)
{
mark = m;
}
Output
>The mark is: 30
>The mark is: 40
>The mark is: 70
Exercice :
if (a == b)
{
Console.WriteLine("Equal grades!");
}
Et définissez les deux notes comme étant exactement les mêmes, disons 30.
Il faut imprimer "Grades égaux"
Note :
La fonction surcharge opérateur doit retourner un bool
Le « != » operateur a aussi besoin d’implanter à ces cotés ( cela
fera juste l’opposé complet)
Solution
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Grade a = new Grade(30);
a.Print();
Grade b = new Grade(30);
b.Print();
//Test
if (a == b)
{
Console.WriteLine("Equal grades!");
}
Console.ReadKey();
}
}
class Grade
{
int mark;
public Grade(int m)
{
mark = m;
}
Output
>The mark is: 30
>The mark is: 30
>Equal grades!
Expression régulière
Character Description
^ Est une référence pour commencer
le mot
$ Réfère à la fin d’une ligne
\w Réfère à un mot consistant de a-
z,A-Z,0-9 et souligner
+ Réfère à 0 ou à plus de récurrences
| Utilisé pour spécifier « ou »
[nnn] Utilisé pour spécifier une classe de
caractère pour vérifier avec
i.e(abcd) ne retournera que les
matchs sur aabc et pas dcab
^\w+$
Cela semble intimidant je sais, mais cela correspond simplement à
n’importe quel mot donné en utilisant le System.Text.Regular.Expression
nous pouvons faire correspondre un motif. Le code ci dessous le démontre :
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
while (true)
{
//Change expression here!
string regExpression = @"^\w+$";
if (Regex.IsMatch(input, regExpression))
{
Console.WriteLine($"{input} is a match!", input);
}
else
{
Console.WriteLine("No match!");
}
Console.WriteLine();
}
}
}
}
^([\w]+\.[\w]+)$
Cette section dans les parenthèses spécifie le set de caractère, donc dans
cette case cela dit que n’importe quel mot avec (A-Z,a-z,0-9 et ‘_ ») est
valide ensuite il va dans “\.”qui vérifient un arrêt entier et le [\ w] + est
répété après l'arrêt, donc cette regex cherche un motif d'un mot séparé par
un arrêt complet. Ajoutez cette expression au programme utilisé dans
l'exemple précédent et essayez-le.
Cela peut maintenant être adapté à ce complex regex utlisé pour identifier
des adresses email , chaque section sera expliqué
^((([\w]+\.[\w]+))|([\w]+))\@([\w]+\.)+([A-Za-z]{1,2}\.([A-Za-z]{1,2})|
([A-Za-z]{1,3}))$
Directive Explication
#define Cela crée un symbole
#undef Utilisé pour un symbole indéfini
#if Cela est utilisé pour tester un
symbole contre une condition
#else Utilisé aux cotés de #if
#elif Et sinon et un si dans la même
déclaration
#endif Utilisé pour signifier une close à un
#if dans la déclaration
#line Modifie le numéro de ligne du
compilateur et une fonctionnalité
facultative consiste à modifier les
sorties de nom de fichier pour les
fichiers et les avertissements
#region Utile pour le formatage
#endregion Montre la fin d’une région
#define VALUE
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
#if (VALUE)
Console.WriteLine("Defined");
#else
Console.WriteLine("Not Defined");
#endif
Console.ReadKey();
}
}
}
Output
>Defined
Comme vous pouvez le voir ceci peut être utilisé pour basculer facilement
le code, l'exemple le plus courant est l'utilisation du code de débogage ou
d'un mode verbeux.
#define VERBOSE
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start!");
int a = 1 + 3;
#if (VERBOSE)
Console.WriteLine("Addition complete");
#endif
int b = 1 - 4;
#if (VERBOSE)
Console.WriteLine("Subtraction complete");
#endif
int c = 1 * 3;
#if (VERBOSE)
Console.WriteLine("Multiplication complete");
#endif
int d = 1 / 3;
#if (VERBOSE)
Console.WriteLine("Division complete");
#endif
Console.WriteLine("End!");
Console.ReadKey();
}
}
}
Exception Handing
Une exception est "levée" lorsqu'une erreur se produit, c'est une réponse
une situation à laquelle le programme ne peut pas continuer. Des exceptions
peuvent être gérées cependant et votre programme ne doit pas toujours
exploser, il y a 4 mots-clés; essayer, attraper, finalité et jeter:
try—ceci est utilisé pour entourer le code que vous souhaitez
surveiller pour une exception, si une exception est trouvée cela
transfère le contrôle de la section.
Catch—ceci est le lieu ou le programme finira si une exception
est levée dans une section d’essai d’accompagnement
Finally—ceci peut avvompagner un try/catch mais s'exécutera
toujours indépendamment d'une exception levée, un bon exemple
est lors de l'ouverture d'un fichier à lire, il a toujours besoin de
fermeture.
Throw—ceci est utilisé manuellement pour lever manuellement
une exception avec votre texte customer
Ci dessous un exemple d’utilisation de try/catch :
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
//Diving by zero error!
int zero = 0;
int i = 1 / zero;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
}
}
Output
> Attempted to divide by zero.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
StreamReader sr = null;
try
{
sr = new StreamReader("file.txt");
//Used to simulate an example
throw new Exception("Error reading file!");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
//Closes the file
if (sr != null)
{
sr.Close();
}
}
Console.ReadKey();
}
}
}
Réponses :
1. Publique et statique
2. Utilisé pour correspondre à un motif d’une ligne
3. System.Text.RegularExpressions,
4. Cela dit au compiler de prendre la ligne littéralement et d’ignorer
backslash identifiers.
5. Il n’y a pas de support pour les macros.
6. Toujours, même si une exception est levée.
7. Ceci est utilisé pour créer vos propres exceptions customisées
8. Elles sont utilisées pour formater et améliorer le rendement.
9. Signifie le commencement d’un mot.
10. N’importe nombre de caractères dans une rangée qui sont a,b,f et
e qui correspondrait .
Chapitre 5
Attribut
Un attribut est une étiquette utilisée pour transmettre au compilateur des
informations sur les comportements des éléments du programme, un attribut
est spécifié par une paire de crochets ([]) et est placé au-dessus de l'élément
sur lequel ils fournissent des informations.
Le cadre .NET fournit deux types d’attributs :
Prédéfinis
Custom built
Prédéfinis
Il y a trois types d’attributs pré-définis :
AttributeUsage
Conditional
Obsolete
Attribute Usage :
L’Attribute Usage décrit comment un attribut custome peut être utiliser et
ou il peut être appliqué, la syntaxe est ci dessous :
Condition
Ces attributs conditionnés sont utilisé pour marquer une méthode qui
dépend d’une certaines directive pre-processor c’est cet exemple que nous
utiliserons pour débugger par exemple :
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
Debugging();
Console.ReadKey();
}
[Conditional("DEBUG")]
static void Debugging()
{
Console.WriteLine("This is example debugging code:");
Console.WriteLine("Number of loops: " + 1);
Console.WriteLine("Values found: " + 102);
}
}
}
#define CUSTOM
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
Custom_Method();
Console.ReadKey();
}
[Conditional("CUSTOM")]
static void Custom_Method()
{
Console.WriteLine("Custom output!");
}
}
}
Obsolète :
Ceci est utilisé pour des raisons d'héritage et de compatibilité, si par
exemple vous avez une classe qui a utilisé une fonction SaveFile () mais a
été mise à jour plus tard et cette fonction est devenue obsolète une nouvelle
fonction a été créée appelée Save () () serait marqué comme obsolète, donc
d'autres programmes qui utilisent ces fonctions n'auraient pas de problèmes
de compatibilité.
Cet exemple montre comment utilisé obsolete
using System;
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
Output old = new Output();
old.PrintData();
Console.ReadKey();
}
}
class Output
{
string example = "Example";
Output
>Example
>Example
Comme vous pouvez le voir cela est très similaire à créer une classe, à
l'exception de l'héritage hors attribut et de l'attribut AttributeUsage ci-
dessus. Cela peut être utilisé comme ça:
[Description("Main method!")]
[Description("AllowMultiple == true, so you can have multiple
Descriptions")]
class Program
{
public static void Main()
{
}
}
Réflexion
La réflexion d ‘un objet est utilisé pour obtenir des informations lors de
l’exécution, le System.Reflection donne accès à ces propriétés
Metadata
Les métadonnées sont des données sur les données, et dans ce cas, il s'agit
de données sur les attributs. Pour commencer, vous devez créer une instance
d'informations sur les membres comme suit:
Cela peut être utilisé pour vérifier les informations. L’exemple ci dessous
imprime les attributs attachés
Pour cet exemple, nous allons utiliser le Description Attribute vu plus tôt :
using System;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
AttributeTest t = new AttributeTest();
t.PrintAttributes();
Console.ReadKey();
}
}
[Description("Description 1!")]
[Description("Description 2!")]
class AttributeTest
{
MemberInfo info = typeof(AttributeTest);
//Prints attributes
foreach (Description attr in attributes)
{
Console.WriteLine(attr.Text);
}
}
Output
>Description 1!
>Description 2!
…info.GetCustomAttributes(true);
Renvoie la liste des attributs et les attributs sont ensuite imprimés dans la
boucle foreach suivante.
Indexers
Example[2];
Avec la même exacte syntaxe sur l’étalage
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
Inventory main_floor = new Inventory();
//Adds Items
main_floor.AddItem(new Item("PS4", 499.50));
main_floor.AddItem(new Item("RX_480", 200.50));
class Inventory
{
List<Item> Items = new List<Item>();
}
}
Exercice
Ajoutez une version surchargée de l’indexer (ceci eut être fait) qui prend le
prix comme index et renvoie le nom. Pour des raisons de simplicité, ne vous
inquiétez pas si deux articles ont le même prix, mais supposez que tous les
articles ont des prix différents
Solution
return -1;
}
}
public string this[double index]
{
get
{
foreach (Item item in Items)
{
if (item.Price == index)
{
return item.Name;
}
}
return null;
}
}
}
Collections
List<T>
List est la version de la mise à jour plus moderne de l’ArrayList, c'est une
liste de taille dynamique qui est utilisée pour stocker différentes valeurs du
même type, elle peut être étendue et réduite (où elle se redimensionne
automatiquement). La classe List est une classe générique (apprise dans le
chapitre suivant) mais ce que cela signifie dans ce cas, c'est qu'elle peut
contenir n'importe quoi, même d'autres listes (Voici comment vous pouvez
faire une liste 2D).
Hashtable
Note : ceci est déprécié et ne devrait pas être utilisé, vous devriez utilisé un
Dictionnaire <>, mais c’est important que vous sachiez comment la
collectionne fonctionne.
Une hashtable est une table (comme son nom l'indique) qui stocke des
paires clé-valeur, ces paires sont déterminées par une fonction de hachage.
Une fonction de hachage prend une entrée de n'importe quelle longueur et
renvoie une valeur de longueur fixe, ce processus ne peut pas non plus être
annulé. Donc, dans le cas des tables de hachage, une paire de clés à ajouter
est hachée, maintenant ce hachage sera égal à une position dans la table. La
paire de clés sera ensuite stockée à cet emplacement.
L'une des plus grandes positivités d'une table de hachage est la rapidité
d'accès ou de vérification de la table et des éléments, car dans la plupart des
structures linéaires comme un tableau ou une liste, vous devez rechercher
une liste de façon exhaustive un objet, mais dans le cas d'une hashtable si
une cible de recherche a haché pour trouver où elle irait et qu'il n'y a pas de
valeur à cet endroit, elle n'est pas là.
Console.WriteLine(dictionary[key]);
Stack
Ceci est connu comme une structure de données du premier entré, dernier
sorti (FILO) où lorsqu'une valeur est placée dans son 'push' et qu'une valeur
est prise (ne peut être que du haut de la pile), elle est sautée.
Queue
Une file d'attente est très similaire à une pile mais est une structure de
données First-in First-out (FIFO). Les éléments sont ajoutés et supprimés en
utilisant 'Enqueue ()' et 'Dequeue ()' respectivement.
Et l'ajout d'une suppression d'une file d'attente est fait comme suit:
class Generic<T>
{
Remarquez les utilisation de <>, ceux-ci sont utilisés pour créer un type de
données générique, ceux-ci n'ont pas besoin d'être définis comme 'T' et
peuvent être des définitions multiples:
L’exemple ci dessus est valide mais est conseillé pour la lisibilité pour
commencer la défintion avec un « T ». Ci dessous un exemple comment
utiliser le type de données générique
class Generic<TEx>
{
public TEx value;
Ainsi les génériques vous permettent d’une façon très dynamique de définit
une classe ce qui permet presque une quantité infinie de données types. Ci
dessous un actuel programme qui est utilisé pour échanger les deux types de
données
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
int a = 10;
int b = 42;
Console.ReadKey();
}
}
public class Swap<T>
{
public Swap(ref T Left, ref T Right)
{
T temp;
temp = Left;
Left = Right;
Right = temp;
}
}
}
Console.WriteLine(intArray[0]);
Console.WriteLine(strArray[0]);
Console.ReadKey();
}
}
public class Array<T>
{
T[] array;
public Array(int size)
{
array = new T[size];
}
}
}
C’est un peu de la triche d’avoir un étalage interne défini mais vous
obtiendrez l’image. L’étalage défini comme un étalage de générique, ce qui
vous permet de définir un type plus tard.
Processus et fonctionnalité
Délégués
Les Délégués sont très similaire à la fonction de pointeur dans C ou C++ si
vous avez déjà croisé ce concept auparavant. Ainsi les délégués sont une
variable de type référence qui contient des références à une fonction.
Un réel usage pour les délégués est l’utilisation pour les rappelles
dynamiques d’une fonction, le délégué est passé comme un paramètre et la
fonction est appelée dynamiquement.
Par exemple la définition ci dessous peut être utilisé pour référencer
n’importe quel méthode qui possède deux paramètres internes, il retourne et
est marqué comme privé.
public delegate int ExampleDeligate(int a, int b);
Comme vous pouvez le voir le délégué est initialisé et dans les parenthèses
il y a le nom de la fonction de référence.
addDel(1, 2);
Cela vous vous donne une bonne dynamique, une façon utilisable pour
passer les fonctions comme des paramètres. Ci dessous un exemple utilisant
cet acte comme un calculateur :
using System;
namespace ConsoleApplication1
{
class Program
{
public delegate float Calculation(float a, float b);
static void Main()
{
//All you have to do is pass in the function by name
Calculater(10, 20, Add);
Calculater(5, 267, Sub);
Calculater(14, 2, Mul);
Calculater(10, 10, Div);
Console.ReadKey();
}
//Basic functions
public static float Add(float a, float b)
{
return a + b;
}
public static float Sub(float a, float b)
{
return a - b;
}
public static float Mul(float a, float b)
{
return a * b;
}
public static float Div(float a, float b)
{
return a / b;
}
}
}
Output
>New value is: 30
>New value is: -262
>New value is: 28
>New value is: 1
Multicasting
Ce qui signifie que toutes les méthodes seront appelées en une longue
chaine, donc par exemple disons que les paramètres sont 10 et 20 la
réponse serait égale à la dernière méthode ajoutée, dans ce cas ( 10/20=0.5)
dans cet exemple cela lance toutes les méthodes mais elles ne s’affectent
pas les unes les autres donc cela ne change pas la réponse, donc faites
attention à la considération nécessaire lorsque vous choisissez quelle
méthode ajouter à un multicast délégué.
//Method call
call();
Console.ReadKey();
}
Méthode anonyme
Précédemment nous avons mentionné que les délégués sont utilisés pour
référencer n’importe quelle méthode avec la même signature que le
délégué.
using System;
namespace ConsoleApplication1
{
//Delegate
public delegate int Calculation(int a, int b);
class Program
{
Calculation add = delegate (int a, int b)
{
return a + b;
};
Calculation sub = delegate (int a, int b)
{
return a - b;
};
Calculation mul = delegate (int a, int b)
{
return a * b;
};
Calculation div = delegate (int a, int b)
{
return a / b;
};
static void Main()
{
Program p = new Program();
p.add(10, 20);
p.div(2, 10);
Console.WriteLine();
}
}
}
Donc, les méthodes anonymes doivent être utilisées lorsque les frais
généraux de création d'un
Evènements
Les événement sont une action de l’utilisateur comme entré, un click, un
mouvements de la sourie etc... Ceci permet au programme ou au code
d’exécuter ce qui est dépendant d’un événement déclencheur (trigger
détection)
Les délégués sont souvent utilisés avec des évènements qui sont associés
avec le gestionnaire d'événements (détection de déclencheur) en utilisant le
délégué. Les évènements utilisent les publisher-subscriber modèle :
using System;
namespace ConsoleApplication1
{
//Delegate
public delegate string DelExample(string str);
class EventExample
{
//Event decleration
event DelExample MyEvent;
public EventExample()
{
MyEvent += new DelExample(PrintWelcome);
}
Multithreading
Threads
Les outils requis pour créer et travailler avec les restes de fils dans le
System.Threading classe. Une des fonctions les plus simples est d’être
capable d’attraper le fil en cour de cette manière :
Thread t = Thread.CurrentThread;
Créer un fil
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
public static void DoLotsOfWork()
{
for (int i = 0; i < 5; i++)
{
Thread t = Thread.CurrentThread;
Console.WriteLine($"{t.Name}: i is equal to: {i}");
}
}
s.Start();
}
Console.ReadKey();
}
}
}
Output
Cet exemple ci dessus crée 5 fils qui sortent 5 itérations d'une boucle for,
comme vous pouvez le voir tout ne sort pas en ordre, cela est du au fait que
tout s’opère en même temps et que chaque ligne travaille indépendamment.
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static object padLock = new object();
public static void DoLotsOfWork()
{
lock (padLock)
{
for (int i = 0; i < 5; i++)
{
Thread t = Thread.CurrentThread;
Console.WriteLine($"{t.Name}: i is equal to: {i}");
}
}
}
s.Start();
}
Console.ReadKey();
}
}
}
Output
>Thread 0: i is equal to: 0
Comme vous pouvez le voir chaque itération de boucle sort dans l’ordre de
0 à 4, on pourrait croire que les lignes ne sortent pas dans l’ordre, le mot
lock travaille sur un premier arrivé premier servi de base et une fois qu'un
fil le touche, il devient verrouillé jusqu'à ce que l'objet soit libéré. S'il vous
plaît également pas l'utilisation d'un objet à côté de la serrure, cela est
utilisé comme un drapeau pour si le verrou est disponible ou verrouillé.
namespace ConsoleApplication1
{
class Program
{
public static void WriteToFile()
{
//Error here!
StreamWriter sw = new StreamWriter("file.txt");
for (int i = 0; i < 5; i++)
{
sw.WriteLine($"Test {i}");
}
sw.Close();
}
Console.ReadKey();
}
}
}
using System;
using System.IO;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static object padLock = new object();
public static void WriteToFile()
{
lock (padLock)
{
StreamWriter sw = new StreamWriter("file.txt");
for (int i = 0; i < 5; i++)
{
sw.WriteLine($"Test {i}");
}
sw.Close();
Console.WriteLine("File written to!");
}
}
s.Start();
}
Console.ReadKey();
}
}
}
Ce code ne crashera pas mais il ne peut être considéré comme
multithreated, il utilise plusieurs threads mais joue comme une application
à une thread, la déclaration verrouillage ne devrait être utilisé seulement
lorsque c’est nécessaire. Copiez ce code et lancez le pour vous familiarisez
avec son fonctionnement.
LINQ
LINQ signifie Langage Integrated Query et résout les problèmes avec des
données d’interrogation et permet une syntaxe stricte, lisible et compacte
pour le retour des données d’interrogation.
Nous couvrirons seulement le LINQ queries pour les objets internes, mais
LINQ peut-être utilisé pour questionner les données en différentes façons.
Les différentes façons sont :
Nous verrons seulement la syntaxe query car je pense que c’est la plus
simple à utiliser mais soyez libre de jeter un coup d’œil à l’autre query pour
des recherches en plus.
Query syntaxe :
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
string[] words = {"test","verylongword", "sw", "one"};
Output
>test
>sw
>one
select word.Length;
Exercice
Dans le squelette du programme ci dessous ajoutez une déclaration LINQ
pour chercher un étalage de valeur de « nombres » pour chercher ces
mêmes nombres. Ensuite utilisez une boucle foreach pour sortir le résultat.
Code
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
int[] numbers = {1, 4, 99, 34, 23, 12, 3, 2, 909, 1000, 13, 1, 2};
}
}
}
Solution
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
int[] numbers = {1,4,99, 34, 23, 12, 3, 2, 909, 1000, 13, 1, 2};
>4
>34
>12
>2
>1000
>2
Donc rappelez vous que LINQ offre une syntaxe très simple et contrôlé
pour rechercher des données, il peut aussi être utilisé pour rechercher à
travers de multiples types de données incluant les commandes de recherche
SQL sur une base de donnée pour les rassembler dans un tableau qui peut
être incroyablement puissant pour un programmeur.
Quiz de fin de chapitre :
1. Qu’est ce qu’un délégué permet au programmeur de faire ?
2. Qu‘est ce que le multicasting vous permet de faire avec le
délégué ?
3. Qu’est ce qu’une méthode anonyme ?
4. A quoi correspond un gestionnaire d’évènements ?
5. Qu’est ce qu’un thread ?
6. Quel est le nom de la structure qui prévient deux threads
d’utiliser le même block de code ?
7. Que signifie LINQ ?
8. Qu’est ce LINQ vous permet de faire ?
9. Qu’elles sont les deux types de syntaxes de LINQ ?
10. Dans quel scénario le multithreadong devrait maintenant vous
aidez ?
Réponses
1. Sauvegarder une référence pour une fonction, ce qui permettra au
programmer de faire passer les appels de fonction en tant que
paramètre.
2. Vous pouvez écrasez plusieurs fonctions d’appels en un seul
délégué.
3. Une fonction sans définition de fonction est juste un délégué
définis avec un corps
4. Un délégué qui se déclenche lorsque l’événement est déclenché
5. Un seul procédé indépendant d’exécution
6. Verrou
7. Language Integrated Query
8. Une recherche de données rapides pour des résultats, par
exemple si vous voulez travaillez avec une longueur de cinq
caractères
9. Query et Lambda
10. Lorsque le problème est trivial i.e un simple problème.