如何在C#中销毁静态类

时间:2021-08-08 19:35:13

I am using .net 1.1. I have a session class in which I have stored many static variables that hold some data to be used by many classes.

我正在使用.net 1.1。我有一个会话类,我在其中存储了许多静态变量,这些变量包含许多类要使用的数据。

I want to find a simple way of destroying this class instead of resetting every variable one by one. For example if there is a static class MyStatic, I would have liked to destroy/remove this class from the memory by writing MyStatic = null, which is not currently possible,

我想找到一种简单的方法来销毁这个类,而不是逐个重置每个变量。例如,如果有一个静态类MyStatic,我本来希望通过写MyStatic = null来破坏/删除这个类,这是目前不可能的,

Additional question.

The idea of singleton is good, but I have the following questions:

单身人士的想法很好,但我有以下问题:

If singleton is implemented, the 'single' object will still remain in the memory. In singleton, we are only checking if an instance is already existing. how can i make sure that this instance variable also gets destroyed.

如果实现单例,“单个”对象仍将保留在内存中。在单例中,我们只检查实例是否已存在。我怎样才能确保此实例变量也被破坏。

I have a main class which initializes the variable in the static class. Even if I plan to implement a Rest() method, I need to call it from a method, for eg, the destructor in the main class. But this destructor gets called only when GC collects this main class object in the memory, which means the Reset() gets called very late

我有一个主类,它初始化静态类中的变量。即使我计划实现一个Rest()方法,我也需要从一个方法中调用它,例如,主类中的析构函数。但是只有当GC在内存中收集这个主类对象时才会调用此析构函数,这意味着Reset()被调用得很晚

thanks pradeep

10 个解决方案

#1


Don't use a static class to store your variables. Use an instance (and make it a singleton if you only want one instance at any given time.) You can then implement IDisposible, and just call Dispose() when you want to destroy it.

不要使用静态类来存储变量。使用一个实例(如果你在任何给定的时间只想要一个实例,那就使它成为单例。)然后你可以实现IDisposible,并在你想要销毁时调用Dispose()。

For more information check out this site: http://csharpindepth.com/Articles/General/Singleton.aspx

欲了解更多信息,请访问该网站:http://csharpindepth.com/Articles/General/Singleton.aspx

EDIT

The object is still subject to garbage collection, so unless you are using lots of unmanaged resources, you should be fine. You can implement IDisposible to clean up any resources that need to be cleaned up as well.

该对象仍然需要进行垃圾回收,因此除非您使用大量非托管资源,否则您应该没问题。您可以实现IDisposible来清理任何需要清理的资源。

#2


Instead of a static class, have a static instance of a class:

而不是静态类,具有类的静态实例:

class Foo
{
  public int Something;
  public static Foo Instance = new Foo();
  public void Reset()
  {
    Instance = new Foo();
  }
}

void test
{
  int i = Foo.Instance.Something;
}

You can also delegate to an instance of the class:

您还可以委托给该类的实例:

class Foo
{
  public int Something
  {
    get { return instance.something; }
  }
  private int something;
  private static Foo instance = new Foo();
  public void Reset()
  {
    instance = new Foo();
  }
}

void test
{
  int i = Foo.Something;
}

#3


There's no way to destroy a static unless it resides in a separate AppDomain in which case you can get rid of it by unloading the AppDomain. However it is usually better to avoid statics.

除非它驻留在单独的AppDomain中,否则无法销毁静态,在这种情况下,您可以通过卸载AppDomain来消除静态。然而,通常最好避免使用静力学。

EDIT: Additional question

编辑:其他问题

When the singleton is no longer referenced it will be collected just as everything else. In other words, if you want it collected you must make sure that there are no references to it. It goes without saying that if you store a static reference to your singleton, you will have the same problem as before.

当不再引用单例时,它将像其他一样被收集。换句话说,如果你想收集它,你必须确保没有对它的引用。不言而喻,如果您将静态引用存储到您的单例中,您将遇到与以前相同的问题。

#4


Use a Singleton like ktrauberman said, and have an initialization method or a reset method. You only have to write the code once and call the method.

使用像ktrauberman这样的Singleton,并且有一个初始化方法或一个重置方法。您只需编写一次代码并调用该方法。

#5


You destroy objects, not classes. There's nothing wrong with static classes--C# provides them for a reason. Singletons are just extra overhead, unless you actually need an object, e.g. when you have to pass the object as a parameter.

你破坏对象,而不是类。静态类没有任何问题 - C#提供它们是有原因的。单身人士只是额外的开销,除非你真的需要一个物体,例如当您必须将对象作为参数传递时。

Static classes contain only static variables. These variables tend to last for the lifetime of the app, in which case you don't have to worry about disposing referenced objects, unless you have a mild case of OCD. That just leaves the case where your static class allocates and releases resources throughout its lifetime. Dispose of these objects in due course as you usually would (e.g., "using...").

静态类仅包含静态变量。这些变量往往会持续应用程序的生命周期,在这种情况下,您不必担心处置引用的对象,除非您有一个温和的OCD案例。这就是静态类在其生命周期中分配和释放资源的情况。像往常一样在适当的时候处理这​​些物体(例如,“使用......”)。

#6


The best way in your condition is to have an Reset() method built-in as well, which can reset the values of the class.

你的条件最好的方法是内置一个Reset()方法,它可以重置类的值。

#7


class myclass

{

private static myclass singleobj = null;
private myclass(){}
public static myclass CreateInstance()
{
if(singleobj == null)
  singleobj =  new myclass();

return singleobj
}

}

#8


Building on Ahemd Said's answer: (and props to him!)

以Ahemd Said的回答为基础:(并向他道具!)

class Singleton
{
    private static Singleton instance  = null;
    private Singleton(){}   // private constructor: stops others from using

    public static Singleton Instance
    {
        get { return instance ?? (instance = new Singleton()); }
        set {
                if (null != value)
                { throw new InvalidValueException(); }
                else
                { instance = null; }
            }
    }
}


void SampleUsage()
{
    Singleton myObj = Singleton.Instance;
    // use myObj for your work...
    myObj.Instance = null;  // The set-operator makes it ready for GC
}

(untested... but mostly right, I think) You could also add in usage of the IDispose interface for more cleanup.

(未经测试......但大多数是正确的,我认为)您还可以添加IDispose接口的使用以进行更多清理。

#9


You can create a method in the static class which resets the values of all properties. Consider you have a static class

您可以在静态类中创建一个方法,该方法将重置所有属性的值。考虑一下你有一个静态类

public static class ClassA
{
     public static int id=0;
     public static string name="";

     public static void ResetValues()
     {
         // Here you want to reset to the old initialized value
         id=0;
         name="";
     }
}

Now you can use any of the below approaches from any other class to reset value of a static class

现在,您可以使用任何其他类的以下任何方法来重置静态类的值

Approach 1 - Calling directly

方法1 - 直接呼叫

ClassA.ResetValues();

Approach 2 - Invoking method dynamically from a known namespace and known class

方法2 - 从已知的命名空间和已知类动态调用方法

Type t1 = Type.GetType("Namespace1.ClassA");
MethodInfo methodInfo1 = t1.GetMethod("ResetValues");
if (methodInfo1 != null)
{
     object result = null;
     result = methodInfo1.Invoke(null, null);                
}

Approach 3 - Invoking method dynamically from an assembly/set of assemblies

方法3 - 从一个程序集/一组程序集动态调用方法

foreach (var Ass in AppDomain.CurrentDomain.GetAssemblies())
{
     // Use the above "If" condition if you want to filter from only one Dll
     if (Ass.ManifestModule.FullyQualifiedName.EndsWith("YourDll.dll"))
     {
            List<Type> lstClasses = Ass.GetTypes().Where(t => t.IsClass && t.IsSealed && t.IsAbstract).ToList();
            foreach (Type type in lstClasses)
            {
                  MethodInfo methodInfo = type.GetMethod("ResetValues");
                  if (methodInfo != null)
                  {
                       object result = null;
                       result = methodInfo.Invoke(null, null);                                
                  }
             }
             break;
    }
}

#10


Inject the objects into the static class at startup from a non static class that implements IDisposable, then when your non static class is destroyed so are the objects the static class uses.

在启动时从一个实现IDisposable的非静态类将对象注入静态类,然后在非静态类被销毁时,静态类使用的对象也是如此。

Make sure to implement something like "Disable()" so the static class is made aware it's objects have just been set to null.

确保实现类似“Disable()”的内容,以便让静态类知道它的对象刚被设置为null。

Eg I have a logger class as follows:

例如,我有一个记录器类如下:

public static class Logger
{
    private static Action<string, Exception, bool> _logError;

    public static void InitLogger(Action<string, Exception, bool> logError)
    {
        if(logError != null) _logError = logError;
    }

    public static void LogError(string msg, Exception e = null, bool sendEmailReport = false)
    {
        _logError?.Invoke(msg, e, sendEmailReport);
    }

In my constructor of my Form I call the following to setup the logger.

在我的Form的构造函数中,我调用以下内容来设置记录器。

Logger.InitLogger(LogError);

Then from any class in my project I can do the following:

然后从我的项目中的任何类,我可以执行以下操作:

Logger.LogError("error",new Exception("error), true);

#1


Don't use a static class to store your variables. Use an instance (and make it a singleton if you only want one instance at any given time.) You can then implement IDisposible, and just call Dispose() when you want to destroy it.

不要使用静态类来存储变量。使用一个实例(如果你在任何给定的时间只想要一个实例,那就使它成为单例。)然后你可以实现IDisposible,并在你想要销毁时调用Dispose()。

For more information check out this site: http://csharpindepth.com/Articles/General/Singleton.aspx

欲了解更多信息,请访问该网站:http://csharpindepth.com/Articles/General/Singleton.aspx

EDIT

The object is still subject to garbage collection, so unless you are using lots of unmanaged resources, you should be fine. You can implement IDisposible to clean up any resources that need to be cleaned up as well.

该对象仍然需要进行垃圾回收,因此除非您使用大量非托管资源,否则您应该没问题。您可以实现IDisposible来清理任何需要清理的资源。

#2


Instead of a static class, have a static instance of a class:

而不是静态类,具有类的静态实例:

class Foo
{
  public int Something;
  public static Foo Instance = new Foo();
  public void Reset()
  {
    Instance = new Foo();
  }
}

void test
{
  int i = Foo.Instance.Something;
}

You can also delegate to an instance of the class:

您还可以委托给该类的实例:

class Foo
{
  public int Something
  {
    get { return instance.something; }
  }
  private int something;
  private static Foo instance = new Foo();
  public void Reset()
  {
    instance = new Foo();
  }
}

void test
{
  int i = Foo.Something;
}

#3


There's no way to destroy a static unless it resides in a separate AppDomain in which case you can get rid of it by unloading the AppDomain. However it is usually better to avoid statics.

除非它驻留在单独的AppDomain中,否则无法销毁静态,在这种情况下,您可以通过卸载AppDomain来消除静态。然而,通常最好避免使用静力学。

EDIT: Additional question

编辑:其他问题

When the singleton is no longer referenced it will be collected just as everything else. In other words, if you want it collected you must make sure that there are no references to it. It goes without saying that if you store a static reference to your singleton, you will have the same problem as before.

当不再引用单例时,它将像其他一样被收集。换句话说,如果你想收集它,你必须确保没有对它的引用。不言而喻,如果您将静态引用存储到您的单例中,您将遇到与以前相同的问题。

#4


Use a Singleton like ktrauberman said, and have an initialization method or a reset method. You only have to write the code once and call the method.

使用像ktrauberman这样的Singleton,并且有一个初始化方法或一个重置方法。您只需编写一次代码并调用该方法。

#5


You destroy objects, not classes. There's nothing wrong with static classes--C# provides them for a reason. Singletons are just extra overhead, unless you actually need an object, e.g. when you have to pass the object as a parameter.

你破坏对象,而不是类。静态类没有任何问题 - C#提供它们是有原因的。单身人士只是额外的开销,除非你真的需要一个物体,例如当您必须将对象作为参数传递时。

Static classes contain only static variables. These variables tend to last for the lifetime of the app, in which case you don't have to worry about disposing referenced objects, unless you have a mild case of OCD. That just leaves the case where your static class allocates and releases resources throughout its lifetime. Dispose of these objects in due course as you usually would (e.g., "using...").

静态类仅包含静态变量。这些变量往往会持续应用程序的生命周期,在这种情况下,您不必担心处置引用的对象,除非您有一个温和的OCD案例。这就是静态类在其生命周期中分配和释放资源的情况。像往常一样在适当的时候处理这​​些物体(例如,“使用......”)。

#6


The best way in your condition is to have an Reset() method built-in as well, which can reset the values of the class.

你的条件最好的方法是内置一个Reset()方法,它可以重置类的值。

#7


class myclass

{

private static myclass singleobj = null;
private myclass(){}
public static myclass CreateInstance()
{
if(singleobj == null)
  singleobj =  new myclass();

return singleobj
}

}

#8


Building on Ahemd Said's answer: (and props to him!)

以Ahemd Said的回答为基础:(并向他道具!)

class Singleton
{
    private static Singleton instance  = null;
    private Singleton(){}   // private constructor: stops others from using

    public static Singleton Instance
    {
        get { return instance ?? (instance = new Singleton()); }
        set {
                if (null != value)
                { throw new InvalidValueException(); }
                else
                { instance = null; }
            }
    }
}


void SampleUsage()
{
    Singleton myObj = Singleton.Instance;
    // use myObj for your work...
    myObj.Instance = null;  // The set-operator makes it ready for GC
}

(untested... but mostly right, I think) You could also add in usage of the IDispose interface for more cleanup.

(未经测试......但大多数是正确的,我认为)您还可以添加IDispose接口的使用以进行更多清理。

#9


You can create a method in the static class which resets the values of all properties. Consider you have a static class

您可以在静态类中创建一个方法,该方法将重置所有属性的值。考虑一下你有一个静态类

public static class ClassA
{
     public static int id=0;
     public static string name="";

     public static void ResetValues()
     {
         // Here you want to reset to the old initialized value
         id=0;
         name="";
     }
}

Now you can use any of the below approaches from any other class to reset value of a static class

现在,您可以使用任何其他类的以下任何方法来重置静态类的值

Approach 1 - Calling directly

方法1 - 直接呼叫

ClassA.ResetValues();

Approach 2 - Invoking method dynamically from a known namespace and known class

方法2 - 从已知的命名空间和已知类动态调用方法

Type t1 = Type.GetType("Namespace1.ClassA");
MethodInfo methodInfo1 = t1.GetMethod("ResetValues");
if (methodInfo1 != null)
{
     object result = null;
     result = methodInfo1.Invoke(null, null);                
}

Approach 3 - Invoking method dynamically from an assembly/set of assemblies

方法3 - 从一个程序集/一组程序集动态调用方法

foreach (var Ass in AppDomain.CurrentDomain.GetAssemblies())
{
     // Use the above "If" condition if you want to filter from only one Dll
     if (Ass.ManifestModule.FullyQualifiedName.EndsWith("YourDll.dll"))
     {
            List<Type> lstClasses = Ass.GetTypes().Where(t => t.IsClass && t.IsSealed && t.IsAbstract).ToList();
            foreach (Type type in lstClasses)
            {
                  MethodInfo methodInfo = type.GetMethod("ResetValues");
                  if (methodInfo != null)
                  {
                       object result = null;
                       result = methodInfo.Invoke(null, null);                                
                  }
             }
             break;
    }
}

#10


Inject the objects into the static class at startup from a non static class that implements IDisposable, then when your non static class is destroyed so are the objects the static class uses.

在启动时从一个实现IDisposable的非静态类将对象注入静态类,然后在非静态类被销毁时,静态类使用的对象也是如此。

Make sure to implement something like "Disable()" so the static class is made aware it's objects have just been set to null.

确保实现类似“Disable()”的内容,以便让静态类知道它的对象刚被设置为null。

Eg I have a logger class as follows:

例如,我有一个记录器类如下:

public static class Logger
{
    private static Action<string, Exception, bool> _logError;

    public static void InitLogger(Action<string, Exception, bool> logError)
    {
        if(logError != null) _logError = logError;
    }

    public static void LogError(string msg, Exception e = null, bool sendEmailReport = false)
    {
        _logError?.Invoke(msg, e, sendEmailReport);
    }

In my constructor of my Form I call the following to setup the logger.

在我的Form的构造函数中,我调用以下内容来设置记录器。

Logger.InitLogger(LogError);

Then from any class in my project I can do the following:

然后从我的项目中的任何类,我可以执行以下操作:

Logger.LogError("error",new Exception("error), true);