在静态类中使用状态是不好的做法吗?

时间:2010-05-02 16:24:16

标签: c# static singleton global-variables

我想做这样的事情:

public class Foo {
    // Probably really a Guid, but I'm using a string here for simplicity's sake.
    string Id { get; set; }

    int Data { get; set; }

    public Foo (int data) {
        ...
    }

    ...
}

public static class FooManager {
    Dictionary<string, Foo> foos = new Dictionary<string, Foo> ();

    public static Foo Get (string id) {
        return foos [id];
    }

    public static Foo Add (int data) {
        Foo foo = new Foo (data);
        foos.Add (foo.Id, foo);

        return foo;
    }

    public static bool Remove (string id) {
        return foos.Remove (id);
    }

    ...

    // Other members, perhaps events for when Foos are added or removed, etc.
}

这将允许我从任何地方管理Foo的全局集合。但是,我被告知静态类应该始终是无状态的 - 您不应该使用它们来存储全局数据。总的来说,全球数据似乎不受欢迎。如果我不应该使用静态类,那么解决这个问题的正确方法是什么?

注意:我确实找到了similar question,但给出的答案并不适用于我的情况。

7 个答案:

答案 0 :(得分:9)

谁坚持静态课程应该是无国籍的?静态表示陈述。

只知道静态类在CLR中的工作原理:

  • 您无法控制调用静态构造函数的时间。
  • 静态类对每个调用程序都有一个单独的状态。

还要注意并发问题。

作为旁注,令人惊讶的是人们常说“不要使用X”。就像有人走进你的工具并指着六个工具说:“这些工具是不好的做法。”这没有意义。

答案 1 :(得分:4)

全局数据既强大又是问题的常见来源,这就是使用依赖注入等技术的原因。您可以将其视为正常的解耦问题。拥有在程序中很多地方直接引用的全局数据,可以在全局数据和所有这些地方之间建立强大的耦合。

在您的示例中,您已将对数据的访问隔离到一个类中,该类控制全局数据访问的确切详细信息。由于一些全球数据往往是不可避免的,我认为这是一个很好的方法。

例如,您可以通过.NET框架比较app.config和web.config的使用方式。它们通过静态类System.Configuration.ConfigurationManager访问,其静态属性AppSettings,隐藏了如何获取全局数据的详细信息。

答案 2 :(得分:3)

你在这里寻找的是一个单例类,而不是一个静态类。应该为无状态例程引用静态类和方法。单例类实例化一次,每个应用程序运行一次,并且具有类的全部功能。每次您将来引用它时,您将获得具有完全相同成员属性的完全相同的实例。

“C#singleton”的第一个google结果似乎对实现有相当不错的解释。 http://www.yoda.arachsys.com/csharp/singleton.html

答案 3 :(得分:2)

一般情况下都不好。在一些罕见的情况下,这样做是必要的,而不是实现其他开销很大的东西。

但建议注意线程安全。

您应该锁定对字典的每次调用,以便一次只能有一个线程访问它。


private static readonly object LockStaticFields = new object();

public static Foo Add (int data) {
        lock(LockStaticFields)
        {
           Foo foo = new Foo (data);
           foos.Add (foo.Id, foo);

           return foo;
        }
    }

答案 4 :(得分:0)

在类中使用只读静态属性,该属性在类的所有实例中都是相同的。根据需要从构造函数等增加和减少

答案 5 :(得分:0)

我一直在静态类中使用列表来处理永远(或极少)更改的内容 - 这对于加载选择列表很方便,而且每次都不会点击数据库。由于我不允许更改,因此我不必担心锁定/访问控制。

答案 6 :(得分:0)

需要考虑的另一件事是应用程序本身及其预算。是否真的需要比静态类更复杂的东西?