14

インスタンスを削除するクラスのメソッドを作成する必要があります。

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.")
    }
}

これを行う方法が(推奨されていなくても)可能な解決策があるかどうかを知りたいです。

このクラスのインスタンスは、何百もの異なるクラスに格納されます。これを説明しようとします。たとえば、次のクラスがあります。

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

9 に答える 9

22

どのクラスからでも、その値を null に設定することはできません。これは許可されておらず、意味がありません -

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

メソッドを呼び出すにはクラスのインスタンスが必要なDelete()ので、それが終わったらそのインスタンス自体を null に設定してみませんか。

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

とにかく、あなたが達成しようとしていることは C# では不可能です。あなたの質問から、現在の設計にメモリリークがあり、Car インスタンスが消えないため、これが必要であると思われます。アプリケーションのプロファイリングを改善し、GC を停止している領域を特定して車のインスタンスを収集し、その領域の改善に取り組むことをお勧めします。

于 2013-10-20T11:22:28.927 に答える
12

使用後にインスタンスを解放することを考えている場合は、.Net の IDisposable インターフェイスを使用することをお勧めします。

以下のサンプル実装を参照してください。

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;
    }

   }
}

今あなたのコードで:

void main()
{
   using(var car = new Car())
   {
     // do something with car
   } // here dispose will automtically get called. 
}
于 2013-10-20T11:25:03.863 に答える
5

無効化できるインスタンスの周りにラッパーを作成する必要があるようです:

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; }
    }
}

次のように使用できます。

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

ただし、コードが内部値を変数に保存する場合、これは を呼び出しても無効にならないことに注意してくださいDelete

于 2013-10-20T11:33:30.057 に答える
2

あなたが求めていることは不可能です。あるオブジェクトへのすべての参照を .Net に設定するメカニズムは .Net にはありませんnull

そして、あなたがこれをやろうとしているという事実は、ある種の設計上の問題を示していると思います. おそらく根本的な問題について考え、別の方法で解決する必要があります(ここでの他の回答はいくつかのオプションを示唆しています)。

于 2013-10-20T11:43:32.387 に答える
1

C# でマネージド オブジェクトを削除することはできません。それがMANAGED言語と呼ばれる理由です。そのため、(C++ の場合のように) delete で自分を悩ませる必要はありません。

インスタンスをnullに設定できるのは事実です。しかし、GC (ガベージ コレクター) を制御して Collect 以外のオブジェクトを削除することはできないため、それほど役に立ちません。そして、これは世代からすべてのコレクションを削除するため、あなたが望むものではありません.

それで、それはどのように行われますか?そのため、GC は使用されなくなったオブジェクトを定期的に検索し、関係のない内部メカニズムでオブジェクトを削除します。

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 !!!
于 2013-10-20T11:35:50.393 に答える
1

たとえば、辞書シングルトンを使用して、オブジェクトへの参照をプロキシ化できます。オブジェクトではなく、その ID またはハッシュを保存して、辞書を介してアクセスできます。次に、オブジェクトを削除する必要がある場合は、そのキーの値を null に設定します。

于 2013-10-20T11:28:47.707 に答える
0

FLCL の考えは非常に正しいです。コードで示します。

    public class O1<T> where T: class
    {
        public Guid Id { get; }
        public O1(Guid id)
        {
            Id = id;
        }
        public bool IsNull => !GlobalHolder.Holder.ContainsKey(Id);
        public T Val => GlobalHolder.Holder.ContainsKey(Id) ? (T)GlobalHolder.Holder[Id] : null;
    }
    public class GlobalHolder
    {
        public static readonly Dictionary<Guid, object> Holder = new Dictionary<Guid, object>();
        public static O1<T> Instantiate<T>() where T: class, new()
        {
            var a = new T();
            var nguid = Guid.NewGuid();
            var b = new O1<T>(nguid);
            Holder[nguid] = a;
            return b;
        }
        public static void Destroy<T>(O1<T> obj) where T: class
        {
            Holder.Remove(obj.Id);
        }
    }

    public class Animal
    {

    }

    public class AnimalTest
    {
        public static void Test()
        {
            var tom = GlobalHolder.Instantiate<Animal>();
            var duplicateTomReference = tom;
            GlobalHolder.Destroy(tom);
            Console.WriteLine($"{duplicateTomReference.IsNull}");
            // prints true
        }
    }

注: このコード サンプルでは、​​命名規則は Unity に由来しています。

于 2020-10-24T18:38:17.467 に答える
0

クラスの静的プロパティであるコレクションを使用しますCar。の新しいインスタンスを作成するたびCarに、このコレクションに参照を保存します。

すべての を破棄するにはCar、すべての項目を に設定しますnull

于 2015-07-16T00:21:37.943 に答える
-1

これを実現するために拡張メソッドを使用できます。

public static ObjRemoverExtension {
    public static void DeleteObj<T>(this T obj) where T: new()
    {
        obj = null;
    }
}

そして、それを目的のソース ファイルにインポートして、任意のオブジェクトで使用するだけです。GCが回収します。このような:Car.DeleteObj()

編集 申し訳ありませんが、クラス/すべての参照部分のメソッドに気づきませんでしたが、とにかく残します。

于 2013-10-20T11:46:18.433 に答える