Introduction et quelques notes pêle-mêle à propos du C#.
private const double x = 1.0, y = 2.0, z = 3.0;
Type | Range | Size | Suffixe |
---|---|---|---|
sbyte | -128 → 127 | Signed 8-bit integer | |
byte | 0 → 255 | Unsigned 8-bit integer | |
char | U+0000 → U+ffff | Unicode 16-bit character | |
short | -32,768 → 32,767 | Signed 16-bit integer | |
ushort | 0 → 65,535 | Unsigned 16-bit integer | |
int | -2,147,483,648 → 2,147,483,647 | Signed 32-bit integer | |
uint | 0 → 4,294,967,295 | Unsigned 32-bit integer | U |
long | -9,223,372,036,854,775,808 → 9,223,372,036,854,775,807 | Signed 64-bit integer | L |
ulong | 0 → 18,446,744,073,709,551,615 | Unsigned 64-bit integer | UL |
Type | Approximate range | Precision | Suffixe |
---|---|---|---|
float | ±1.5e−45 to ±3.4e38 | 7 digits | F |
double | ±5.0e−324 to ±1.7e308 | 15-16 digits | D |
Type | Approximate Range | Precision | .NET Framework type | Suffixe |
---|---|---|---|---|
decimal | ±1.0 × 10−28 to ±7.9 × 1028 | 28-29 significant digits | System.Decimal | M |
La signification du symbole @
devant une chaîne de caractère signifie que les caractères d'échappement (escape caracters) ne seront pas traitées. Très utile pour les chaînes du type :
"C:\\repertoire\\fichier.txt"
qui peut être remplacé par @"C:\\repertoire\\fichier.txt"
.@"^(97(8|9))?\d{9}(\d|X)$"
.
On peut utiliser $
devant une chaîne pour pouvoir utiliser directement des variables.
string variable = "quelconque valeur"; string interpolation = $"On peut utiliser la valeur de la variable {variable} ici.";
Guid id = Guid.Empty; string inter = $"Commande {(!id.Equals(Guid.Empty) ? $"-Id {id}" : string.Empty)}";
Il y a une façon comparable à JavaDoc de documenter son code en C#. Si vous êtes dans Visual Studio, tapez trois barres obliques (///
) avant l'entête de l'élément à commenter (classe, méthode, enum, etc). Contrairement à Javadoc qui génère du HTML, le compilateur C# produit du XML, ce qui est plus flexible1).
Élément prédéfini | Utilisé pour |
---|---|
<c> | Une façon d'indiquer que le text inlus entre doit être vu comme du code |
<code> | Comme l'élément précédent (<c> ) pour le faire sur plusieurs lignes |
<example> | Permet de spécifier un exemple d'utilisation d'une méthode ou d'un membre de librairie |
<exception> | Permet de documenter une classe d'exception |
<include> | Permet de référer aux commentaires dans un autre fichier, utilisant la syntaxe XPath, qui décrit les types et les membres dans le code source. |
<list> | Utilisé pour insérer une liste dans le fichier de documentation |
<para> | Utilisé pour insérer un paragraphe dans le fichier de documentation |
<param> | Décrit un paramètre |
<paramref> | Ce tag permet de faire référence à un paramètre dans le texte |
<permission> | Permet de documenter les permission d'accès |
<remarks> | Ce tag permet de fournir des informations complémentaires sur une entité sous la forme d'une remarque. |
<returns> | Décrit la valeur retournée d'une méthode |
<see> | Ce tag permet de faire un lien vers un élément accessible dans le code |
<seealso> | Ce tag permet de faire un lien vers un élément qui sera inclus dans la section See Also. |
<summary> | Utilisé pour une description générale |
<value> | Permet de fournir des informations sur une propriété |
Ces tags sont utilisables en fonction de l'entité documentée2) :
Entité | Tags utilisables |
---|---|
class | <summary>, <remarks>, <seealso> |
struct | <summary>, <remarks>, <seealso> |
interface | <summary>, <remarks>, <seealso> |
delegate | <summary>, <remarks>, <seealso>, <param>, <returns> |
enum | <summary>, <remarks>, <seealso> |
constructor | <summary>, <remarks>, <seealso>, <param>, <permission>, <exception> |
property | <summary>, <remarks>, <seealso>, <value>, <permission>, <exception> |
method | <summary>, <remarks>, <seealso>, <param>, <returns>, <permission>, <exception> |
event | <summary>, <remarks>, <seealso> |
<list type="bullet" | "number" | "table"> <listheader> <term>term</term> <description>description</description> </listheader> <item> <term>term</term> <description>description</description> </item> </list>
Voir C# Operators.
Employe employe = new { Nom = "Tremblay", Prenom = "Réjean", Code = "rtrem009" };
List<Employe> listeEmploye = new List<Employe> { new Employe { Id = 1, Nom="Tremblay", Prenom ="Réjean" }, new Employe { Id = 2, Nom="Smith", Prenom ="John" }, new Employe { Id = 3, Nom="Gagnon", Prenom ="Alain" } };
public string Title { get; set; }
au lieu de :
private string title; public string Title { get { return title; } set { title = value; } }
Pour changer le type d'un objet :
string s = (string)obj; // Change obj en string string s = ((Form)obj).Text; // Change obj en Form Object obj = new TextBox(); Button btn = obj as Button; // L'opérateur as retourne null si le cast ne peut pas se faire
Pour obtenir un int
à partir d'une chaîne :
int chiffre; string chaine; chaine = "1234"; chiffre = int.Parse(chaine);
Le commutateur switch
peut être utilisé avec des données intégrales ou des chaînes3).
using System; class SwitchTest { static void Main() { Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large"); Console.Write("Please enter your selection: "); string s = Console.ReadLine(); int n = int.Parse(s); int cost = 0; switch(n) { case 1: cost += 25; break; case 2: cost += 25; goto case 1; case 3: cost += 50; goto case 1; default: Console.WriteLine("Invalid selection. Please select 1, 2, or 3."); break; } if (cost != 0) { Console.WriteLine("Please insert {0} cents.", cost); } Console.WriteLine("Thank you for your business."); Console.ReadLine(); } }
switch(s) { case "1": // ... case "2": // ... }
Il es possible de créer des listes d'objets4).
using System; using System.Collections.Generic; public class Example { public static void Main() { List<string> dinosaurs = new List<string>(); Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity); dinosaurs.Add("Tyrannosaurus"); dinosaurs.Add("Amargasaurus"); dinosaurs.Add("Mamenchisaurus"); dinosaurs.Add("Deinonychus"); dinosaurs.Add("Compsognathus"); Console.WriteLine(); foreach(string dinosaur in dinosaurs) { Console.WriteLine(dinosaur); } Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity); Console.WriteLine("Count: {0}", dinosaurs.Count); Console.WriteLine("\nContains(\"Deinonychus\"): {0}", dinosaurs.Contains("Deinonychus")); Console.WriteLine("\nInsert(2, \"Compsognathus\")"); dinosaurs.Insert(2, "Compsognathus"); Console.WriteLine(); foreach(string dinosaur in dinosaurs) { Console.WriteLine(dinosaur); } Console.WriteLine("\ndinosaurs[3]: {0}", dinosaurs[3]); Console.WriteLine("\nRemove(\"Compsognathus\")"); dinosaurs.Remove("Compsognathus"); Console.WriteLine(); foreach(string dinosaur in dinosaurs) { Console.WriteLine(dinosaur); } dinosaurs.TrimExcess(); Console.WriteLine("\nTrimExcess()"); Console.WriteLine("Capacity: {0}", dinosaurs.Capacity); Console.WriteLine("Count: {0}", dinosaurs.Count); dinosaurs.Clear(); Console.WriteLine("\nClear()"); Console.WriteLine("Capacity: {0}", dinosaurs.Capacity); Console.WriteLine("Count: {0}", dinosaurs.Count); } }
Une liste:
var list = new List<int> { 1, 2, 3 };
Après on peut créer une seconde liste basée sur la première:
var list2 = new List<int>(list) { 4, 5 };
Ou même:
string[] ab = new string[] { "a", "b" }; List<string> abcd = new List<string>(ab) { "c", "d" };
Un dictionnaire:
var dict = new Dictionary<int, int> { { 0, 1 }, { 1, 2 }, }; // Equivalent to var dict = new Dictionary<int, int>(); dict.Add(0, 1); dict.Add(1, 2); var dict = new Dictionary<int, int> { [0] = 1, [1] = 2, }; // Equivalent to var dict = new Dictionary<int, int>(); dict[0] = 1; dict[1] = 2;
Pour se baser sur des dictionnaires existants:
var dict2 = new Dictionary<int, int>(dict) { [2] = 3 }; // ou var dict2 = new Dictionary<int, int>(dict) { [0] = 4 };
Il est possible de soustraire et additionner avec les dates en utilisant TimeSpan
.
DateTime UneDate = DateTime.Parse("12 May 2007 20:15:00"); // Ajout d'une heure, 10 minutes, 30 secondes UneDate = UneDate + new TimeSpan(1, 10, 30); // UneDate = 2 May 2007 21:25:30 // Soustraire 15 jours UneDate = UneDate - new TimeSpan(15, 0, 0, 0); // UneDate = 17 Apr 2007 21:25:30
public class DateHelper { public static DateTime _UnixEpoch = new DateTime(1970,1,1,0,0,0); public static int ToUnixTimeStamp(int year, int month, int day) { DateTime dt = new DateTime(year, month, day, 0, 0, 0); TimeSpan ts = (dt - _UnixEpoch); return (int)ts.TotalSeconds; } public static int ToBasicDateFormat(int year, int month, int day) { return(year*10000 + month*100 + day); } public static long ToTicks(int year, int month, int day) { return new DateTime(year, month, day).Ticks; } }
public DateTime GetFirstDayOfCurrentWeek() { DateTime firstDayOfCurrentWeek = DateTime.Now.AddDays(DayOfWeek.Monday - DateTime.Now.DayOfWeek); firstDayOfCurrentWeek.AddHours(-firstDayOfCurrentWeek.Hour).AddMinutes(-firstDayOfCurrentWeek.Minute); return firstDayOfCurrentWeek; }
public static class ExtensionMethods { public static string[] ToStringArray(this int[] intArray) { return Array.ConvertAll<int, string>(intArray, delegate(int intParameter) { return intParameter.ToString(); }); } public static int[] ToIntArray(this string[] strArray) { return Array.ConvertAll<string, int>(strArray, delegate(string intParameter) { return int.Parse(intParameter.ToString()); }); } }
[Flags] public enum Styles { None = 0, Flat = 1, Sunken = 2, Raised = 4 }
La valeur 0 devrait être une absence de flag. (Réf: Effective C#, Bill Wagner, p110).
tetxBox.TextChanged += new EventHandler(this.TextChangedHandler);
public override bool Equals(Object obj) { if (obj == null) { return false; } Employe t = obj as Employe ; if (t == null) { return false; } if (this.IdEmploye == t.IdEmploye) { return true; } else { return false; } } public static bool operator ==(Employe x, Employe y) { // Si les deux sont null, ou s'ils sont la meme instance, retourne true if (System.Object.ReferenceEquals(x, y)) { return true; } // Si un est null, mais pas les deux, retourne false. if (((object)x == null) || ((object)y == null)) { return false; } return x.Equals(y); } public static bool operator !=(Employe x, Employe y) { // Si les deux sont null, ou s'ils sont la meme instance, retourne false if (System.Object.ReferenceEquals(x, y)) { return false; } // Si un est null, mais pas les deux, retourne true. if (((object)x == null) || ((object)y == null)) { return true; } return !x.Equals(y); }
Source : Guidelines for Overloading Equals() and Operator == (C# Programming Guide)
Main thread:
void Main() { Thread.CurrentThread.Name = "Main Thread here"; }
Créer un thread:
void Main() { Thread thread = new Thread(WriteUsingNewThread); thread.Name = "Worker Thread"; thread.Start(); } private static void WriteUsingNewThread() { for (int i = 0; i < 1000; i++) { Console.WriteLine(" Z" + i + " "); } }
Shared resources
using System.Threading; private static bool isCompleted = false; void Main() { Thread thread = new Thread(HelloWorld); thread.Start(); HelloWorld(); } private static void HelloWorld() { if (!isCompleted) { Console.WriteLine("Hello World"); isCompleted = true; } }
Thread:
Processus:
void Main() { Employee employee = new Employee (); employee.Name = "my name"; employee.CompanyName = "company name"; ThreadPool.QueueUserWorkItem(new WaitCallback(DisplayEmployeeInfo), employee); } private static void DisplayEmployeeInfo(object employee) { Console.WriteLine(Thread.CurrentThread.IsThreadPoolThread); Employee emp = employee as Employee; Console.WriteLine("Person name is {0} and company name is {1}", emp.Name, emp.CompanyName); } class Employee { public string Name { get; set; } public string CompanyName { get; set; } }
À titre informatif, on peut demander combien de processeurs sont disponibles:
var processorCount = Environment.ProcessorCount;
Par exemple, sur un i7 12700K, processCount
serait 20.
On pourrait donc faire:
ThreadPool.SetMaxThreads(processorCount * 2, processorCount * 2);
Les deux arguments de SetMaxThreads
sont:
int workerThreads
: Le maximum de worker threads dans le thread pool.int completionPortThreads
: Le maximum de threads I/O asynchrones dans le thread pool.On pourrait obtenir le minimum des valeurs, et les multiplier selon les besoins:
int workerThreads = 0; int completionThreads = 0; ThreadPool.GetMinThreads(out workerThreads, out completionThreads); ThreadPool.SetMaxThreads(workerThreads * 2, completionThreads * 2);
Si on exécute Execute()
(sans le new Thread(Execute).Start()
), on va tomber dans le catch
et le message ex.Message
s'affichera dans la console vu qu'ils sont dans le même thread.
Par contre, si on exécute new Thread(Execute).Start();
(sans le Execute()
), on ne tombera pas dans le catch
vu que le throw null
(là où l'exception est générée) se trouve dans un autre thread (dans worker thread, tandis que le try/catch
est dans le main thread).
using System.Threading; void Main() { Demo(); } private static void Demo() { try { Execute(); // Première fois avec cette ligne new Thread(Execute).Start(); // Deuxième fois avec cette ligne } catch (Exception ex) { Console.WriteLine(ex.Message); } } static void Execute() { throw null; }
Il faut donc voir là où l'erreur peut être généré plus localement et le mettre dans un try/catch
:
private static void Demo() { new Thread(Execute).Start(); } static void Execute() { try { throw null; // pourrait être n'importe quelle méthode/opération qui lance des exceptions. } catch (Exception ex) { Console.WriteLine(ex.Message); } }
Les Task
sont comme des threads mais de plus haut niveau et faciles à gérer, entre autres pour le retour de valeurs.
using System.Threading.Tasks; async void Main() { // Simple tâche Task task = new Task(SimpleMethod); task.Start(); // Tâche qui retourne une valeur Task<string> taskThatReturns = new Task<string>(MethodThatReturns); taskThatReturns.Start(); taskThatReturns.Wait(); Console.WriteLine("Returning MethodThatReturns' return is '{0}'", taskThatReturns.Result); } private static void SimpleMethod() { Console.WriteLine("Simple Task here"); } private static string MethodThatReturns() { Thread.Sleep(2000); // Simuler un temps d'opération, dans une Task on devrait utiliser Task.Delay(ms) return "returns"; }
void Main() { Task<string> task = Task.Factory.StartNew<string> (() => GetPosts("https://jsonplaceholder.typicode.com/posts")); DoSomethingElse(); // task.Wait(); // Décommenté, l'exception se produira ici, et le catch n'aura pas d'effet. // Si on doit utiliser le Wait(), le déplacer dans le try try { task.Wait(); Console.WriteLine(task.Result); } catch (AggregateException ex) { Console.WriteLine(ex.Message); } } string GetPosts(string urlv) { // throw null; // Décommenter pour simuler une erreur // WebClient ci-dessous est obsolète, mais on l'a gardé vu que c'est simplement un exemple. using (var client = new System.Net.WebClient()) { return client.DownloadString(urlv); } } void DoSomethingElse() { Console.WriteLine("Something Else"); }
Permet d'exécuter de la logique suite à une logique précédente (appelé antecedent).
Task chaining:
Exemple simple d'utilisation de continuation:
void Main() { Task<string> antecedent = Task.Run(() => DateTime.Today.ToShortDateString()); Task<string> continuation = antecedent.ContinueWith(x => "Today is " + antecedent.Result); Console.WriteLine(continuation.Result); }
Exemple de Monitor
, qui est semblable à lock
:
void Main() { Account account = new Account(20000); Task task1 = Task.Factory.StartNew(() => account.WithdrawRandomly()); Task task2 = Task.Factory.StartNew(() => account.WithdrawRandomly()); Task task3 = Task.Factory.StartNew(() => account.WithdrawRandomly()); Task.WaitAll(task1, task2, task3); Console.WriteLine("All tasks completed"); } public class Account { Object caztonLock = new Object(); private int balance; public Account(int initialBalance) { balance = initialBalance; } public int Withdraw(int amount) { if (balance < 0) { throw new Exception("Not enough balance"); } Monitor.Enter(caztonLock); // equivalent to lock(object) {} try { if (balance >= amount) { Console.WriteLine("Amount drawn: {0}", amount); balance = balance - amount; return balance; } } finally { Monitor.Exit(caztonLock); } return 0; } public void WithdrawRandomly() { for (int i = 0; i < 100; i++) { var balance = Withdraw((new Random()).Next(2000, 5000)); if (balance > 0) { Console.WriteLine("Balance left: {0}", balance); } } } }
private static ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim(); private static Dictionary<int, string> persons = new Dictionary<int, string>(); private static Random random = new Random(); void Main() { var task1 = Task.Factory.StartNew(Read); var task2 = Task.Factory.StartNew(Write, "Someone"); var task3 = Task.Factory.StartNew(Write, "Simone"); var task4 = Task.Factory.StartNew(Read); var task5 = Task.Factory.StartNew(Read); Task.WaitAll(task1, task2, task3, task4, task5); } private static void Read() { for (int i = 0; i < 10; i++) { readerWriterLockSlim.EnterReadLock(); Thread.Sleep(50); // simulation of reading readerWriterLockSlim.ExitReadLock(); } } private static void Write(object user) { for (int i = 0; i < 10; i++) { int id = GetRandom(); readerWriterLockSlim.EnterWriteLock(); var person = "Person " + i; persons.Add(id, person); readerWriterLockSlim.ExitWriteLock(); Console.WriteLine(user + " added " + person); Thread.Sleep(250); } } private static int GetRandom() // Pour la synchronisation { lock (random) { return random.Next(2000, 3000); } }
private static Mutex mutex = new Mutex(); // Initially owned est par défaut à false void Main() { for (int i = 0; i < 10; i++) { Thread thread = new Thread(AquireMutex); thread.Name = string.Format("Thread {0}", i + 1); thread.Start(); } } private static void AquireMutex(object obj) { mutex.WaitOne(); // On peut utiliser la façon suivante pour ne pas bloquer le thread continuellement //if (!mutex.WaitOne(TimeSpan.FromSeconds(1), false)) //{ // return; //} DoSomething(); mutex.ReleaseMutex(); Console.WriteLine("The mutex has been released by {0}", Thread.CurrentThread.Name); } static void DoSomething() { Thread.Sleep(1000); Console.WriteLine("Mutex aquired by {0}", Thread.CurrentThread.Name); }
private static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(3); // '3' est la capacité void Main() { for (int i = 0; i < 10; i++) { new Thread(EnterSemaphore).Start(i + 1); } } void EnterSemaphore(object id) { Console.WriteLine("{0} is waiting to be part of the club", id); semaphoreSlim.Wait(); Console.WriteLine("{0} is part of the club", id); Thread.Sleep(1000 / (int) id); Console.WriteLine("{0} left the club", id); }
void Main() { var task1 = Task.Factory.StartNew(AddItem); var task2 = Task.Factory.StartNew(AddItem); var task3 = Task.Factory.StartNew(AddItem); var task4 = Task.Factory.StartNew(AddItem); var task5 = Task.Factory.StartNew(AddItem); Task.WaitAll(task1,task2,task3,task4,task5); foreach (var item in items) { Console.WriteLine(item.Key + ": " + item.Value); } } private static void AddItem() { lock (items) { Console.WriteLine("Lock acquired by {0}", Task.CurrentId); items.Add(items.Count, "World " + items.Count); } Dictionary<int, string> dictionary; lock (items) { Console.WriteLine("Lock 2 acquired by {0}", Task.CurrentId); dictionary = items; } } private static void AddItemNotSafe() { if (items.ContainsKey(1)) { // Ceci devrait être "locked" // do something } else { items.Add(1, "Hello World"); // Ceci devrait être "locked" } }
Pros:
Cons:
Ceci peut mener à une erreur System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.
Permet de signaler à d'autres threads qu'une ressource peut être accédée.
EventWaitHandle permet le signalement
WaitOne()
Set
signals release of a waiting threadstatic EventWaitHandle eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); // Equivalent: static EventWaitHandle eventWaitHandle = new AutoResetEvent(false); void Main() { Task.Factory.StartNew(WorkerThread); Thread.Sleep(2500); // Simulation de temps de traitement eventWaitHandle.Set(); } void WorkerThread() { Console.WriteLine("Waiting to Enter the gate"); eventWaitHandle.WaitOne(); // Logic Console.WriteLine("Gate Entered"); }
Le two-way signaling utilise deux EventWaitHandle.
static EventWaitHandle first = new AutoResetEvent(false); static EventWaitHandle second = new AutoResetEvent(false); static object customLock = new object(); static string value = String.Empty; void Main() { Task.Factory.StartNew(WorkerThread); Console.WriteLine("Main thread is waiting"); first.WaitOne(); lock (customLock) { value = "Updating value in main thread"; Console.WriteLine(value); } Thread.Sleep(1000); second.Set(); Console.WriteLine("Released Worker thread"); } void WorkerThread() { Thread.Sleep(1000); lock (customLock) { value = "Updating value in worker thread"; Console.WriteLine(value); } first.Set(); Console.WriteLine("Release main thread"); Console.WriteLine("Worker thread is waiting..."); second.WaitOne(); }
static ManualResetEvent customEvent = new ManualResetEvent(false); // Equivalent: static EventWaitHandle eventWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); void Main() { Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Thread.Sleep(1000); Console.WriteLine("Press a key to release all the threads"); Console.Read(); customEvent.Set(); Thread.Sleep(1000); Console.WriteLine("Press a key again. Thread won't block even if they call WaitOne"); Console.Read(); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Thread.Sleep(1000); Console.WriteLine("Press a key again. Thread will block if they call WaitOne"); Console.Read(); customEvent.Reset(); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Task.Factory.StartNew(CallWaitOne); Thread.Sleep(1000); Console.WriteLine("Press a key again calls Set()"); Console.Read(); customEvent.Set(); Console.ReadLine(); } void CallWaitOne() { Console.WriteLine("{0} has called WaitOne", Task.CurrentId); customEvent.WaitOne(); Console.WriteLine("{0} finally ended", Task.CurrentId); }
static CountdownEvent customCountdown = new CountdownEvent(5); void Main() { Task.Factory.StartNew(DoSomething); Task.Factory.StartNew(DoSomething); Task.Factory.StartNew(DoSomething); Task.Factory.StartNew(DoSomething); Task.Factory.StartNew(DoSomething); customCountdown.Wait(); Console.WriteLine("Signal has been called 5 times"); } void DoSomething() { Thread.Sleep(250); Console.WriteLine("{0} is calling signal", Task.CurrentId); customCountdown.Signal(); }
Exemple simple:
void Main() { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < 10; i++) { Console.WriteLine(i); } stopwatch.Stop(); Console.WriteLine("Time taken: {0}", stopwatch.ElapsedTicks); stopwatch.Start(); Parallel.For(0, 10, i => { Console.WriteLine(i); }); stopwatch.Stop(); Console.WriteLine("Time taken: {0}", stopwatch.ElapsedTicks); }
Le cas en parallèle prend plus de temps dû au overhead. L'instruction n'étant pas assez complexe pour justifier la parallèlisation.
// Générer des images: https://picsum.photos/3840/2160 void Main() { var path = Directory.GetCurrentDirectory(); var files = Directory.GetFiles(path + @"\pictures", "*.jpg"); var normalAlteredPath = path + @"\normalAlteredPath"; var parallelAlteredPath = path + @"\parallelAlteredPath"; Directory.CreateDirectory(normalAlteredPath); Directory.CreateDirectory(parallelAlteredPath); ParallelExecutionMode(files, normalAlteredPath); NormalExecutionMode(files, parallelAlteredPath); } void NormalExecutionMode(string[] files, string alteredPath) { Stopwatch stopwatch = Stopwatch.StartNew(); foreach (var currentFile in files) { var file = Path.GetFileName(currentFile); using (var fileBitmap = new Bitmap(currentFile)) { fileBitmap.RotateFlip(RotateFlipType.Rotate270FlipX); fileBitmap.Save(Path.Combine(alteredPath, file)); Console.WriteLine("Thread {0}", Thread.CurrentThread.ManagedThreadId); } } Console.WriteLine("Normal execution time: {0}", stopwatch.ElapsedMilliseconds); stopwatch.Stop(); } void ParallelExecutionMode(string[] files, string alteredPath) { Stopwatch stopwatch = Stopwatch.StartNew(); Parallel.ForEach(files, currentFile => { var file = Path.GetFileName(currentFile); using (var fileBitmap = new Bitmap(currentFile)) { fileBitmap.RotateFlip(RotateFlipType.Rotate270FlipX); fileBitmap.Save(Path.Combine(alteredPath, file)); Console.WriteLine("Thread {0}", Thread.CurrentThread.ManagedThreadId); } }); Console.WriteLine("Parallel execution time: {0}", stopwatch.ElapsedMilliseconds); stopwatch.Stop(); }
void Main() { var list = Enumerable.Range(0, 100000000).ToArray(); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); ParallelOptions parallelOptions = new ParallelOptions(); parallelOptions.CancellationToken = cancellationTokenSource.Token; parallelOptions.MaxDegreeOfParallelism = System.Environment.ProcessorCount; Console.WriteLine("Press 'x' to cancel"); Task.Factory.StartNew(() => { if (Console.ReadLine() == "x") { cancellationTokenSource.Cancel(); } long total = 0; try { Parallel.For<long>(0, list.Length, parallelOptions, () => 0, (count, parallelLoopState, subtotal) => { Thread.Sleep(200); parallelOptions.CancellationToken.ThrowIfCancellationRequested(); subtotal += list[count]; return subtotal; }, (x) => { Interlocked.Add(ref total, x); }); } catch (OperationCanceledException ex) { Console.WriteLine("Cancelled " + ex.Message); } finally { cancellationTokenSource.Dispose(); } Console.WriteLine("The final sum is {0}", total); }); }
void Main() { Task<DateTime> task = Task.Run(() => DoSomething()); List<Task<DateTime>> continuationTasks = new List<Task<DateTime>>(); for (int i = 0; i < 3; i++) { task = task.ContinueWith((x, y) => DoSomething(), new Person { Id = i }); continuationTasks.Add(task); } task.Wait(); foreach (var continuation in continuationTasks) { Person person = continuation.AsyncState as Person; Console.WriteLine("Task finished at " + continuation.Result + ". Person id is {0}", person.Id); } } static DateTime DoSomething() { return DateTime.Now; } internal class Person { public int Id { get; set; } }
void Main() { TaskCompletionSource<Product> taskCompletionSource = new TaskCompletionSource<Product>(); Task<Product> lazyTask = taskCompletionSource.Task; Task.Factory.StartNew(() => { Thread.Sleep(2000); taskCompletionSource.SetResult(new Product { Id = 1, Name = "Some name" }); }); Task.Factory.StartNew(() => { if (Console.ReadLine() == "x") { Product result = lazyTask.Result; Console.WriteLine("Result is {0}", result.Name); } }); Thread.Sleep(5000); } class Product { public int Id { get; set; } public string Name { get; set; } }
Parallel LINQ:
void Main() { var list = Enumerable.Range(1, 100000); var primeNumbers = list .AsParallel() .Where(IsPrime); Console.WriteLine("{0} prime numbers", primeNumbers.Count()); } bool IsPrime(int x) { if (x == 1) return false; if (x == 2) return true; if (x % 2 == 0) return false; var boundary = (int)Math.Floor(Math.Sqrt(x)); for (int i = 3; i <= boundary; i += 2) { if (x % i == 0) { return false; } } return true; }
void Main() { List<string> websites = new List<string>(); websites.Add("apple.com"); websites.Add("google.com"); websites.Add("microsoft.com"); List<PingReply> responses = websites .AsParallel() .WithDegreeOfParallelism(websites.Count()) .Select(PingSites) .ToList(); foreach (var response in responses) { Console.WriteLine(response.Address + " " + response.Status + " " + response.RoundtripTime); } Console.ReadLine(); } private static PingReply PingSites(string websiteName) { Ping ping = new Ping(); return ping.Send(websiteName); }
void Main() { var circle = new Circle(5); var circleRadius100 = new Circle(250); var rectangle = new Rectangle(420, 1337); var square = new Rectangle(70, 70); var shapes = new List<Shape> { circle, circleRadius100, rectangle, square }; var randomShape = shapes[new Random().Next(shapes.Count)]; CSharp6Feature(randomShape); CSharp7Feature(randomShape); CSharp8Feature(randomShape); CSharp9Feature(randomShape); } private void CSharp6Feature(Shape shape) { Console.WriteLine("=== C# 6 Pattern matching features ==="); if (shape is Circle) // 'is' operator { var circle = (Circle)shape; Console.WriteLine($"Circle with radius {circle.Radius}"); } else { Console.WriteLine($"Shape is something else"); } } private void CSharp7Feature(Shape shape) { Console.WriteLine("=== C# 7 Pattern matching features ==="); if (shape is Circle circle) // implicit casting { Console.WriteLine($"Circle with radius {circle.Radius}"); } else { Console.WriteLine($"Shape is something else"); } // using switch switch (shape) { case Circle c: Console.WriteLine($"Circle with radius {c.Radius}"); break; case Rectangle r when r.Height == r.Width: Console.WriteLine($"This is a square"); break; default: Console.WriteLine($"Shape is something else"); break; } } private void CSharp8Feature(Shape shape) { Console.WriteLine("=== C# 8 Pattern matching features ==="); if (shape is Circle { Radius: 10 }) { Console.WriteLine($"Circle with radius of 10"); } var shapeDetails = shape switch { Circle => "This is a circle", // we can drop the 'cir' is not used Rectangle rec when rec.Height == rec.Width => "This is a square", _ => "Shape is something else" }; } private void CSharp9Feature(Shape shape) { Console.WriteLine("=== C# 9 Pattern matching features ==="); if (shape is not Rectangle) // 'not' added { Console.WriteLine($"This is not a rectangle"); } if (shape is Circle { Radius: > 100 and < 200, Area: >= 1000 }) { Console.WriteLine($"Circle with radius greater than 100"); } // that can be used like so: if (shape is not null) {...} var shapeDetails = shape switch { Circle => "This is a circle", // we can drop the 'cir' is not used Rectangle rec when rec.Height == rec.Width => "This is a square", { Area: 100 } => "Area is 100", _ => "Shape is something else" }; var areaDetails = shape.Area switch { >= 100 and <= 200 => "Area is between 100 and 200", _ => "" }; } public static class Extensions { public static bool IsLetter(this char c) => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z'; } public abstract class Shape { public abstract double Area { get; } } public class Rectangle : Shape, ISquare { public Rectangle(int height, int width) { Height = height; Width = width; } public override double Area => Height * Width; public int Height { get; set; } public int Width { get; set; } } public class Circle : Shape { private const double PI = Math.PI; public Circle(int diameter) { Diameter = diameter; } public int Diameter { get; set; } public int Radius => Diameter / 2; public override double Area => PI * Radius * Radius; } public interface ISquare { int Height { get; set; } int Width { get; set; } } static decimal GetGroupTicketPriceDiscount(int groupSize, DateTime visitDate) => (groupSize, visitDate.DayOfWeek) switch { (<= 0, _) => throw new ArgumentException("Group size must be positive"), (_, DayOfWeek.Saturday or DayOfWeek.Sunday) => 0.0m, (>= 5 and < 10, DayOfWeek.Monday) => 20.0m, (>= 10, DayOfWeek.Monday) => 30.0m, (>= 5 and < 10, _) => 12.0m, (>= 10, _) => 15.0m, _ => 0.0m };
On peut créer des observable de la façon suivante:
using System.Reactive; using System.Reactive.Disposables; // ... var observable = Observable.Create<int>(observer => { for (int i = 0; i < 100; i++) { observer.OnNext(i); } observer.OnCompleted(); return Disposable.Empty; });
Requiert le package System.Reactive
using System.Diagnostics; //.. Debug.Listeners.Add(new ConsoleTraceListener()); Debug.WriteLine("test");
CultureInfo cu = CultureInfo.CreateSpecificCulture("en-CA");
var frCACultureInfo = new CultureInfo("fr-CA"); var dateTimeInfo = frCACultureInfo.DateTimeFormat; string mois = dateTimeInfo.GetMonthName(DateTime.Now.Month);
CultureInfo invCulture = CultureInfo.InvariantCulture; DateTime dtIn = DateTime.Now; dtIn.ToString("d", invCulture).Dump(); string dt = dtIn.ToString("d", invCulture); (dt.Substring(8, 2) + dt.Substring(0, 2) + dt.Substring(3, 2)) .Dump();
IKVM.GNU.Classpath.dll
PDFBox-0.7.3.dll
FontBox-0.1.0-dev.dll
IKVM.Runtime.dll
IKVM.GNU.Classpath.dll
et PDFBox-0.7.3.dll
.bin
du projet.using System; using org.pdfbox.pdmodel; using org.pdfbox.util; namespace PDFReader { class Program { static void Main(string[] args) { PDDocument doc = PDDocument.load("lopreacamasa.pdf"); PDFTextStripper pdfStripper = new PDFTextStripper(); Console.Write(pdfStripper.getText(doc)); } } }
using iTextSharp.text; using iTextSharp.text.pdf; // create an instance of the pdfparser class PDFParser pdfParser = new PDFParser(); // extract the text String result = pdfParser.ExtractText(pdfFile);
Retrouver la version d'un autre projet (ou DLL):
var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.ManifestModule.ToString() == "Nom_du_fichier.dll"); if (assembly != null) { string version = assembly.GetName().Version.ToString(); }