C# 例如,是否可以销毁/删除自我?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17486608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible for instance to destroy/delete self?
提问by jnovacho
NOTE: I'm interested in C#,Java and C++ most, but as this is the more academic question any language will do.
注意:我对 C#、Java 和 C++ 最感兴趣,但因为这是任何语言都可以做的更具学术性的问题。
I know that this problem is solvable from outside, by using appropriate methods of given languages (calling free, Dispose, or by removing all references to instance).
我知道这个问题是从外面可解,利用给定的语言的适当的方法(电话free,Dispose或通过删除所有引用实例)。
My idea is that I create an instance, and in the constructor , I start the private timer. When the timer ends it will call some instance method and destroy the variable.
我的想法是创建一个实例,然后在构造函数中启动私有计时器。当计时器结束时,它会调用一些实例方法并销毁变量。
I think that in C# it should be possible to call Disposeon self, when the IDisposableis implemented, but this would not destroy the instace.
我认为在 C# 中应该可以在实现时调用Disposeself IDisposable,但这不会破坏实例。
In C++ I could call the destructor, but that would lead to the memory leak, plus it is really bad practice.
在 C++ 中,我可以调用destructor,但这会导致内存泄漏,而且这是非常糟糕的做法。
In Java I have no clue, assigning to thisit's not possible as it is finalfield.
在 Java 中我不知道,分配给this它是不可能的,因为它是final字段。
So is there any way for instance, to destroy self?
那么有没有什么办法,例如,摧毁自我?
采纳答案by Nikola Davidovic
Your question is very interesting, and I don't know of any other way to do so in C# but to force from the inside of the instance its destruction from the outside. So this is what I came up with to check if it is possible.
You can create the class Foo, which has event that is fired when the specific interval of the timer elapses. The class that is registered to that event (Bar) within event de-registers the event and sets the reference of the instance to null. This is how I would do it, tested and it works.
你的问题很有趣,我不知道在 C# 中还有什么其他方法可以做到这一点,只能从实例内部强制从外部销毁它。所以这就是我想出来的,以检查是否可能。您可以创建类Foo,它具有在计时器的特定时间间隔过后触发的事件。Bar在 event 中注册到该事件 ( )的类取消注册该事件并将实例的引用设置为null。这就是我要做的,经过测试并且可以正常工作。
public class Foo
{
public delegate void SelfDestroyer(object sender, EventArgs ea);
public event SelfDestroyer DestroyMe;
Timer t;
public Foo()
{
t = new Timer();
t.Interval = 2000;
t.Tick += t_Tick;
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
OnDestroyMe();
}
public void OnDestroyMe()
{
SelfDestroyer temp = DestroyMe;
if (temp != null)
{
temp(this, new EventArgs());
}
}
}
public class Bar
{
Foo foo;
public Bar()
{
foo = new Foo();
foo.DestroyMe += foo_DestroyMe;
}
void foo_DestroyMe(object sender, EventArgs ea)
{
foo.DestroyMe -= foo_DestroyMe;
foo = null;
}
}
And in order to test this, you can set up a button click within a Form, something like this, and check it in the debugger:
为了测试这一点,您可以在表单中设置一个按钮单击,如下所示,并在调试器中检查它:
Bar bar = null;
private void button2_Click(object sender, EventArgs e)
{
if(bar==null)
bar = new Bar();
}
So next time when you click the button, you will be able to see that Barinstance still exists but the Fooinstance within it is null although it has been created within the Bar's constructor.
因此,下次单击该按钮时,您将能够看到该Bar实例仍然存在,但其中的Foo实例为 null,尽管它已在Bar构造函数中创建。
回答by Tigran
No, there is no way to achieve what you are trying to do in C#.
不,没有办法实现您在C#.
If you consider an example :
如果你考虑一个例子:
public class Kamikadze {
......
private void TimerTick(..)
{
....
if(itsTime) {
DestroyMe();
}
}
.....
}
var kamikadze = new Kamikadze ();
after a while DestroyMe()will be called that cleans internaldata.
一段时间DestroyMe()后将调用清理内部数据。
But the reference kamikadze(pointerif you wish) is still valid and points to that memory location, so GCwill not do anything, will not collect it, and instance of Kamikadzewill remain in memory.
但是引用kamikadze(如果您愿意,则为指针)仍然有效并指向该内存位置,因此GC不会做任何事情,不会收集它,并且实例Kamikadze将保留在内存中。
回答by Slava
For C++ take a look at this: http://www.parashift.com/c++-faq/delete-this.html.
对于 C++,看看这个:http: //www.parashift.com/c++-faq/delete-this.html。
回答by Neil Kirk
C++: If an object was allocated dynamically, it can delete its this pointer in its own function, provided the this pointer is never used again after that point.
C++:如果一个对象是动态分配的,它可以在自己的函数中删除它的 this 指针,前提是在该点之后不再使用 this 指针。
回答by Casey
In C++, instances committing suicide are an integral part of the Finite State Machine Pattern:
在 C++ 中,自杀实例是有限状态机模式的一个组成部分:
//Context class contains a pointer to a State object.
void BattleshipGame::SetGameState(IState* state) {
game_state = state;
}
void BattleshipGame::Loss() {
game_state->Loss(this);
}
void BattleshipGame::Idle() {
game_state->Idle(this);
}
void BattleshipGame::FlyBy() {
game_state->FlyBy(this);
}
void BattleshipGame::Attack() {
game_state->Attack(this);
}
void BattleshipGame::Win() {
game_state->Win(this);
}
void BattleshipGame::Load() {
game_state->Loading(this);
}
//State base class contains methods for switching to every state.
class IState {
public:
virtual void Loading(BattleshipGame* context);
virtual void Idle(BattleshipGame* context);
virtual void FlyBy(BattleshipGame* context);
virtual void Attack(BattleshipGame* context);
virtual void Win(BattleshipGame* context);
virtual void Loss(BattleshipGame* context);
protected:
private:
};
//Implementations in the State base class are defined, but empty.
//Derived States only call what they need:
void StateIdle::Loss(BattleshipGame* context) {
//context->SetGameState(new StateLoss());
context->SetGameState(new StateLoss(context));
delete this;
}
void StateIdle::Idle(BattleshipGame* context) {
context->SetGameState(new StateIdle());
delete this;
}
void StateIdle::FlyBy(BattleshipGame* context) {
context->SetGameState(new StateFlyBy());
delete this;
}
void StateIdle::Win(BattleshipGame* context) {
context->SetGameState(new StateWin());
delete this;
}
//Similar design for all other states...
回答by Sebastian Negraszus
The closest thing in C# that I can think of:
我能想到的 C# 中最接近的东西:
On creation, every object stores a reference to itself in the GC root, e.g. by putting the reference into a class static list. Outside of the class, nobody is allowed to store (strong) references to the object. Everybody uses a WeakReferenceand checks if the Targetis still IsAlivebefore touching the object. That way, the only thing that is keeping the object alive is the static reference.
在创建时,每个对象都会在 GC 根中存储对自身的引用,例如通过将引用放入类静态列表中。在类之外,不允许任何人存储对对象的(强)引用。每个人都使用 aWeakReference并在触摸物体之前检查它Target是否仍然存在IsAlive。这样,保持对象存活的唯一方法就是静态引用。
When the object decides to kill itself, it simply removes the reference from the list. Sooner or later, the GC collects the object. Or, if you are really impatient, call GC.Collect()(ouch!).
当对象决定杀死自己时,它只是从列表中删除引用。GC 迟早会收集对象。或者,如果您真的不耐烦,请致电GC.Collect()(哎哟!)。
But I really really would not recommendthis solution!
但我真的真的不推荐这个解决方案!
It's much better put some flag into the class/object to signal whether it's still alive and make everybody check this flag before using the object. This can be combined with the IDisposablesolution.
最好在类/对象中放置一些标志来表示它是否还活着,并让每个人在使用该对象之前检查这个标志。这可以与IDisposable解决方案结合使用。
回答by Mark
In C#, you're right you can implement IDisposable but the trick is instead of calling Dispose method make use of the using statement.
在 C# 中,您是对的,您可以实现 IDisposable,但诀窍是使用 using 语句而不是调用 Dispose 方法。
class Program
{
static void Main(string[] args)
{
using (MyClass obj = new MyClass())
{
obj.SayHello();
}
// obj.SayHello(); // Error: The name 'obj' does not exist in the current context
}
}
class MyClass : IDisposable
{
public void SayHello()
{
Console.WriteLine("Hello");
}
public void Dispose()
{
// Do something (e.g: close some open connection, etc)
}
}
For Reference: microsoft-docs/using-statement

