我需要创建一个删除实例的类方法。
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];
}
}
答案 0 :(得分:14)
从任何类中,您都无法将其值设置为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收集汽车实例的区域 努力改善这一领域。
答案 1 :(得分:6)
我建议,如果您打算在使用后发布实例,请使用.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.
}
答案 2 :(得分:4)
听起来你需要在一个你可以无效的实例周围创建一个包装器:
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
不会使其无效。
答案 3 :(得分:3)
你所要求的是不可能的。 .Net中没有任何机制可以将对某些对象的所有引用设置为null
。
我认为你试图这样做的事实表明某种设计问题。你应该考虑潜在的问题并以另一种方式解决它(这里的其他答案提出了一些选择)。
答案 4 :(得分:1)
您无法在C#中删除托管对象。这就是为什么称为MANAGED语言。因此,您不必为删除自己(就像在c ++中一样)。
确实可以将它的实例设置为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 !!!
答案 5 :(得分:1)
使用属于Car
类的静态属性的集合。
每次创建Car
的新实例时,都会将引用存储在此集合中。
要销毁所有Car
,只需将所有项目设置为null
。
答案 6 :(得分:0)
您可以使用例如字典单例代理对对象的引用。您可以存储不是对象,但是它的ID或哈希并访问字典。然后,当您需要删除对象时,将其键的值设置为null。
答案 7 :(得分: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。
答案 8 :(得分:-1)
您可以使用扩展方法来实现此目的。
public static ObjRemoverExtension {
public static void DeleteObj<T>(this T obj) where T: new()
{
obj = null;
}
}
然后您只需将其导入所需的源文件并在任何对象上使用。 GC会收集它。像这样:Car.DeleteObj()
修改强> 抱歉没有注意到类/所有引用的方法部分,但我还是会留下它。