2010-05-02 5 views
8

나는 같은 것을 할 싶습니다 :static 클래스에 state를 두는 것은 나쁜 습관입니까?

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을 찾았지만, 주어진 답은 제 경우에는 실제로 적용되지 않습니다.

답변

9

누가 정적 클래스를 상태 비 저장해야합니까? 정적 을 의미합니다.

그냥 클래스는 CLR에서 작동하는 방법을 정적 알고 정적 생성자가 호출 될 때

  • 당신은 시간을 제어 할 수 없습니다.
  • 정적 클래스는 각 호출 프로그램마다 별도의 상태를 갖습니다.

동시성 문제도 알고 있어야합니다.

사람들이 "X를 사용하지 마십시오."라고 말하는 것이 얼마나 놀랍습니까? 이 도구는 도구에 들어가서 6 개의 도구를 가리키며 "그 도구는 나쁜 습관"이라고 말합니다. 그것은 말이되지 않습니다.

+1

예, 우리는 더 많은 전역 변수와 유용한 정보를 사용해야합니다 ... – Lucas

+1

문제가 발생하지 않도록해야하지만 똑똑해야합니다. 나중에 더 나은 것으로 움직이기 위해 민첩하게 행동하십시오. –

3

여기에 찾고있는 것 중 하나가 정적 클래스가 아닌 싱글 톤 클래스입니다. Stateless 클래스 및 메소드는 Stateless 루틴을 참조해야합니다. 싱글 톤 클래스는 애플리케이션 실행 당 한 번만 인스턴스화되며 클래스의 모든 기능을 그대로 유지합니다. 앞으로 참조 할 때마다 똑같은 멤버 속성을 사용하여 동일한 인스턴스를 다시 가져올 수 있습니다.

"C# singleton"에 대한 첫 번째 Google 검색 결과는 구현에 대해 꽤 괜찮은 설명이있는 것으로 보입니다. http://www.yoda.arachsys.com/csharp/singleton.html

+1

비록 싱글 톤은 종속성을 생성하기 때문에 좋은 습관이 아니지만, 결국 IoC (Inversion of Control)와 Dependency Injection이 더 나은 솔루션이 될 것입니다. – Femaref

4

글로벌 데이터는 강력하고 공통적 인 문제의 원인이기 때문에 종속성 주입과 같은 기술이 사용됩니다. 보통의 디커플링 문제라고 생각할 수 있습니다. 프로그램의 많은 장소에서 직접 참조되는 전역 데이터를 보유하면 해당 전역 데이터와 모든 장소간에 강력한 결합이 이루어집니다.

그러나 예에서는 데이터에 대한 액세스를 전역 데이터의 액세스 세부 정보를 제어하는 ​​클래스로 분리했습니다. 일부 글로벌 데이터는 필연적으로 불가피하므로 좋은 접근 방법이라고 생각합니다.

예를 들어 app.config 및 web.config가 .NET Framework를 통해 어떻게 사용되는지 비교할 수 있습니다. 정적 속성 AppSettings을 가진 정적 클래스 System.Configuration.ConfigurationManager을 통해 액세스합니다.이 속성은 전역 데이터에 도달하는 방법에 대한 세부 정보를 숨 깁니다.

2

일반적으로 좋지 않습니다. 드문 경우지만 큰 오버 헤드가있는 다른 것을 구현하는 것보다 그렇게하는 것이 필요합니다.

하지만 threadsafety를 감시하는 것이 좋습니다.

한 번에 하나의 스레드 만 액세스 할 수 있도록 사전에 대한 모든 호출을 잠 가야합니다.


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

+0

멀티 스레딩 환경에서 작업하는 경우 "사전에 대한 모든 호출을 잠 가야합니다"라고 추가합니다. 그렇지 않으면 쓸데없는 오버 헤드가 될 것입니다. – Budda

+0

흠, 아마 맞을 것입니다. 그러나 내 경험에 비추어 볼 때 항상 그렇게하는 것이 낫다. 저는 처음에는 멀티 스레딩 환경을 위해 구현되지 않았기 때문에 거의 모든 것을 리팩토링해야하는 회사에서 일하고 있습니다. 나는이 안전을 필요로하지 않을지라도 처음에는 threadsafe를 구현하는 것보다 훨씬 많은 비용이 든다고 생각한다. – DHN

0

클래스에 읽기 전용 정적 속성을 사용하면이 속성은 클래스의 모든 인스턴스에서 동일하게 적용됩니다. 생성자 등에서 필요에 따라 증가시키고 감소시킵니다.

0

필자는 항상 정적 클래스의 목록을 사용하여 (또는 극히 드물게) 변경되지 않는 항목을 항상 사용합니다. 매번 데이터베이스를 치지 않고 선택 목록을로드하는 등의 작업에 편리합니다. 변경을 허용하지 않기 때문에 잠금/액세스 제어에 대해 걱정할 필요가 없습니다.

0

고려해야 할 또 다른 한 가지는 애플리케이션 자체와 예산입니다. 실제로 정적 클래스보다 복잡한 것이 필요합니까?

관련 문제