web-dev-qa-db-fra.com

Comment supprimer un objet?

J'ai besoin de créer une méthode de classe qui supprime l'instance.

public class Car
{
    private string m_Color;

    public string Color
    {
        get { return m_Color; }
        set { m_Color = value; }
    }

    public Car()
    {
    }

    public void Delete()
    {
        /*This method will delete the instance,
        so any references to this instance will be now null*/
    }
}

class Program
{
    static void Main( string[] args )
    {
        Car car = new Car();

        car.Delete();

        if(car==null)
            Console.WriteLine("It works.");
        else
            Console.WriteLine("It doesn't work.")
    }
}

Je veux savoir s'il existe une solution possible (même si ce n'est pas recommandé) comment procéder.

Les instances de cette classe seront stockées dans des centaines de classes différentes. Je vais essayer de décrire ceci, par exemple, il y aura ces classes:

public class CarKey
{
    private Car m_Car;

    public Car Car
    {
        get { return m_Car; }
    }

    public bool CarExist{ get{ return m_Car != null; } }

    public CarKey( Car car )
    {
        m_Car = car;
    }
}

public class Garages
{
     private List<Car> m_Collection = new List<Car>();

     private int m_Size;

     public int Size{ get{ return m_Size; } }

     public Garages( int size )
     {
         for(int i=0;i<size;i++)
             m_Collection.Add(null);
     }

     public bool IsEmpty( int garage )
     {
         return m_Collection[garage] == null;
     }

     public void InsertCar( Car car, int garage )
     {
          if( m_Collection[garage] != null )
            throw new Exception("This garage is full.");

          m_Collection[garage] = car;
     }


     public Car GetCar( int garage )
     {
         if( m_Collection[garage] == null )
           throw new Exception("There is no car, maybe it was deleted.");

         return m_Collection[garage];
     }
}
4
user1576055

De toute classe, vous ne pouvez pas définir sa valeur sur null. Ceci n'est pas autorisé et n'a pas de sens aussi - 

public void Delete()
{
    this = null; <-- NOT ALLOWED
}

Vous avez besoin d'une instance de classe pour appeler la méthode Delete (), alors pourquoi ne pas définir cette instance sur Null une fois que vous avez terminé.

Car car = new Car();
// Use car objects and once done set back to null
car = null;

Quoi qu'il en soit, ce que vous essayez d'atteindre n'est pas possible en C #. Je soupçonne de votre question que vous voulez cela parce qu'il y a des fuites de mémoire présent dans votre conception actuelle qui ne laisse pas l’instance Car se connecter à allez-vous en. Je vous suggérerais de mieux profiler votre application et identifier les zones qui empêchent le GC de collecter l'instance de voiture et travailler sur l'amélioration de ce domaine.

12
Rohit Vats

Je suggérerais d'utiliser l'interface IDisposable .Net si vous envisagez de publier instance après son utilisation.

Voir un exemple d'implémentation ci-dessous.

public class Car : IDisposable
{

   public void Dispose()
   {  
      Dispose(true);
       // any other managed resource cleanups you can do here
       Gc.SuppressFinalize(this);
   }
   ~Car()      // finalizer
   {
        Dispose(false);
   }

   protected virtual void Dispose(bool disposing)
   {
     if (!_disposed)
     {
      if (disposing)
      {
        if (_stream != null) _stream.Dispose(); // say you have to dispose a stream
      }

      _stream = null;
    _disposed = true;
    }

   }
}

Maintenant dans votre code:

void main()
{
   using(var car = new Car())
   {
     // do something with car
   } // here dispose will automtically get called. 
}
6
user240141

Il semble que vous deviez créer un wrapper autour d'une instance que vous pouvez invalider:

public class Ref<T> where T : class
{
    private T instance;
    public Ref(T instance)
    {
        this.instance = instance;
    }

    public static implicit operator Ref<T>(T inner)
    {
        return new Ref<T>(inner);
    }

    public void Delete()
    {
        this.instance = null;
    }

    public T Instance
    {
        get { return this.instance; }
    }
}

et vous pouvez l'utiliser comme:

Ref<Car> carRef = new Car();
carRef.Delete();
var car = carRef.Instance;     //car is null

Sachez cependant que si un code enregistre la valeur interne dans une variable, elle ne sera pas invalidée en appelant Delete.

4
Lee

Ce que vous demandez n'est pas possible. Il n'y a pas de mécanisme dans .Net qui définirait toutes les références à un objet à null.

Et je pense que le fait que vous essayiez de faire cela indique une sorte de problème de conception. Vous devriez probablement penser au problème sous-jacent et le résoudre d'une autre manière (les autres réponses suggèrent quelques options).

3
svick

Vous ne pouvez pas supprimer un objet géré en C #. C'est pourquoi on appelle le langage MANAGED. Donc, vous n’avez pas à vous effacer avec delete (comme dans c ++).

Il est vrai que vous pouvez définir son instance sur null. Mais cela ne vous aidera pas beaucoup car vous n’avez aucun contrôle de votre GC (Garbage Collector) pour supprimer certains objets en dehors de Collect. Et ce n'est pas ce que vous voulez, car cela supprimera toute votre collection d'une génération.

Alors, comment fait-on alors? Donc: GC recherche périodiquement des objets qui ne sont plus utilisés et le supprime avec un mécanisme interne qui ne devrait pas vous concerner.

When you set an instance to null you just notify that your object has no referene anymore ant that could help CG to collect it faster !!!
1
Iulian Radulescu

Utilisez une collection qui est une propriété statique de votre Car classe . Chaque fois que vous créez une nouvelle instance de Car, stockez la référence dans cette collection.

Pour détruire toutes les Cars, définissez tous les éléments sur null.

1
user3761570

Vous pouvez remplacer par proxy les références à votre objet avec, par exemple, singleton dictionary. Vous pouvez stocker non pas un objet, mais son identifiant ou son hachage et y accéder via le dictionnaire. Ensuite, lorsque vous devez supprimer l'objet, vous définissez la valeur NULL pour sa clé.

0
FLCL