vendredi 5 avril 2024

Questions techniques avec leurs réponses C#.Net - p1



1. Quelle est la différence entre String et StringBuilder en C# ?

Réponse :

  • String est immuable (chaque modification crée une nouvelle instance en mémoire).

  • StringBuilder est mutable (il modifie la même instance, évitant ainsi les allocations mémoire inutiles).

  • StringBuilder est plus performant pour des opérations répétées de concaténation.

string s = "Hello";
s += " World"; // Nouvelle instance créée

StringBuilder sb = new StringBuilder("Hello");
sb.Append(" World"); // Modifie l’instance existante

2. Quels sont les principes SOLID en programmation orientée objet ?

Réponse :

Les principes SOLID sont 5 bonnes pratiques pour un code modulaire et maintenable :

  1. Single Responsibility Principle (SRP) : Une classe doit avoir une seule raison de changer.

  2. Open/Closed Principle (OCP) : Une classe doit être ouverte à l’extension mais fermée à la modification.

  3. Liskov Substitution Principle (LSP) : Une classe dérivée doit pouvoir remplacer sa classe mère sans altérer le comportement.

  4. Interface Segregation Principle (ISP) : Une interface ne doit pas imposer l’implémentation de méthodes inutiles.

  5. Dependency Inversion Principle (DIP) : Une classe doit dépendre d’abstractions, pas d’implémentations concrètes.


3. Quelle est la différence entre Task et Thread en C# ?

Réponse :

  • Thread représente un thread physique du système d’exploitation.

  • Task appartient à la TPL (Task Parallel Library) et est plus optimisé pour le multitâche.

  • Task permet la gestion plus fine des tâches asynchrones avec async/await.

// Thread classique
Thread t = new Thread(() => Console.WriteLine("Hello Thread"));
t.Start();

// Task asynchrone
Task.Run(() => Console.WriteLine("Hello Task"));

4. Quelle est la différence entre ref, out et in en C# ?

Réponse :

  • ref : Passe un paramètre par référence, il doit être initialisé avant l’appel.

  • out : Passe un paramètre par référence, mais n’a pas besoin d’être initialisé avant l’appel.

  • in : Passe un paramètre par référence en lecture seule (ne peut pas être modifié).

void Test(ref int x) { x += 10; }  // x doit être initialisé avant
void Test(out int y) { y = 10; }   // y n'a pas besoin d’être initialisé
void Test(in int z) { Console.WriteLine(z); } // z ne peut pas être modifié

5. Explique la différence entre IEnumerable, IQueryable, List<T> et Array en C# ?

Réponse :

Type Description Exécution Mémoire
IEnumerable<T> Collection en mémoire Exécution immédiate Faible
IQueryable<T> Exécute des requêtes SQL sur la DB Exécution différée Optimisé
List<T> Liste dynamique en mémoire Exécution immédiate Moyen
Array Tableau fixe en mémoire Exécution immédiate Élevé

6. Que fait le mot-clé lock en C# ?

Réponse :

lock empêche plusieurs threads d’accéder à une ressource partagée en même temps, évitant ainsi les conditions de course.

private static object verrou = new object();

void AccèsCritique()
{
    lock (verrou)
    {
        Console.WriteLine("Section critique");
    }
}

⚠️ À éviter sur des objets globaux (ex : this) pour éviter les deadlocks.


7. Qu’est-ce que le GC (Garbage Collector) et comment fonctionne-t-il en .NET ?

Réponse :

Le Garbage Collector (GC) libère automatiquement la mémoire des objets non référencés. Il fonctionne en trois générations :

  • Gen 0 : Objets récents (collectés souvent).

  • Gen 1 : Objets intermédiaires.

  • Gen 2 : Objets longue durée (collectés rarement).

Déclenchement :

  • Lorsque la mémoire est insuffisante.

  • Périodiquement en arrière-plan.

  • Manuel via GC.Collect() (⚠️ à éviter).


8. Comment implémenter le pattern Dispose en C# ?

Réponse :

Une classe qui utilise des ressources non managées (ex: fichiers, connexions) doit implémenter IDisposable et la méthode Dispose().

class FichierHandler : IDisposable
{
    private FileStream _file;

    public FichierHandler(string path)
    {
        _file = new FileStream(path, FileMode.Open);
    }

    public void Dispose()
    {
        _file?.Dispose();
        GC.SuppressFinalize(this);
    }
}

Utilisation avec using :

using (var fichier = new FichierHandler("test.txt"))
{
    // Utilisation du fichier
} // Dispose() est appelé automatiquement ici

9. Quelle est la différence entre abstract class et interface en C# ?

Réponse :

Type Héritage Implémentation Champs et Constructeurs
Abstract Class Une seule classe par héritage Peut contenir des méthodes implémentées ✅ Oui
Interface Plusieurs implémentations Ne contient que des méthodes abstraites (jusqu'à C# 8) ❌ Non
// Classe Abstraite
abstract class Animal
{
    public abstract void FaireSon();
}

// Interface
interface IVolant
{
    void Voler();
}

10. Comment fonctionne le async/await en C# ?

Réponse :

async/await permet d’exécuter des opérations asynchrones sans bloquer le thread principal.

async Task<int> ChargerDonnéesAsync()
{
    await Task.Delay(2000); // Simule une attente
    return 42;
}

async void Afficher()
{
    int result = await ChargerDonnéesAsync();
    Console.WriteLine(result);
}
  • await attend la fin d’une tâche sans bloquer le thread.

  • async doit être utilisé avec Task ou Task<T>.

  • ⚠️ async void est déconseillé sauf pour les événements, car il ne permet pas la gestion des exceptions.



Aucun commentaire:

Enregistrer un commentaire