이벤트를 통해 다른 가입자에게 알리기 위해 C#의 정적 클래스를 사용하는 간단한 상태 머신

StackOverflow https://stackoverflow.com/questions/2411803

문제

시스템 상태가 변경 될 때 다른 컨트롤 및 코드에 알리기 위해 내 응용 프로그램을 위해 간단한 정적 클래스 상태 머신을 작성하려고 노력했습니다. 그리고 나는 거의 그것을 가지고 있다고 생각하지만, 나는 어떻게 해야하는지 잘 모르겠다는 작은 문제에 빠져 있습니다.

코드는 다음과 같습니다.

// An enum denoting the 3 States
public enum Status { Error = -1, Working, Ready }

// The main state change class
public static class Sys
{
    // system status
    private static Status state;

    // delegate and event
    public static delegate void StateChangeHandler(object sys, SysInfoEventArgs sysStateInfo);
    public static event StateChangeHandler OnStateChange;

    public static Status State
    {
        get { return state; }
        set
        {
            SysInfoEventArgs sysInfo = new SysInfoEventArgs(state, value);
            state = value;
            OnStateChange(this, sysInfo);
        }
    }
}

/// <summary>Contains previous and current state info</summary>
public class SysInfoEventArgs : EventArgs
{
    public readonly Status oldState;
    public readonly Status newState;
    public SysInfoEventArgs(Status oldState, Status newState)
    {
        this.oldState = oldState;
        this.newState = newState;
    }
}

내가 가진 문제는이 라인에 관한 것입니다.

 OnStateChange(this, sysInfo);

구체적으로, "이것"이라는 단어는 불법입니다. 그리고 나는 그 이유를 이해합니다. "이것"은 인스턴스화 된 대상 (정적 클래스가 아님)의 자아를 다시 언급해야합니다.

나는 여러 사본을 인스턴스화 할 수있는 것이 아니라 내 상태 기계의 정적 클래스를 선호합니다. (그렇게 나쁜 것은 아니지만 코드 클리너가 정적 클래스를 갖는 것 같습니다.)

그래서 어떻게 작동해야합니까?

업데이트:

후속 조치로서, 나는 Jon Skeet의 답변을 올바른 것으로 선택했습니다. 문제는 내가 가지고 있던 기술적 실패가 아니라 내가 취한 접근 방식에 관한 것이기 때문입니다. 그러나 아래의 다른 모든 답변은 내가 다루고 있던 기술 결함을 수정합니다.

이상하게도, 제가 동료와 함께 내가 쓴 응용 프로그램을 검토 할 때, 그녀는 프로그램이 서버 연결 상태와 수행중인 작업 상태를 모두 추적해야한다고 지적했습니다. (예, 버지니아, 이것은 2 개의 주 머신이 필요하다는 것을 의미합니다 ... Ergo, 위의 코드에서 모든 "정적"키워드를 제거하고 정기적 인 클래스가 현명한 접근 방식이었습니다.)

다시 한 번 감사드립니다.

도움이 되었습니까?

해결책

왜 정적 수업을 원하십니까? 그것은 a입니다 상태 기계 - 가지고 있습니다 상태 - 자연스럽게 비 정적 클래스를 사용하는 것을 제안합니다. 실제로 원하는 경우 항상 하나의 인스턴스를 참조하는 정적 변수를 가질 수 있습니다.

기본적으로, 본능은 내 견해에서 부정확합니다. 일반 클래스를 갖는 것은 코드를 정적보다 깨끗하게 만듭니다. 정적 클래스는 상태가 거의 없어야합니다. 아마도 캐시 (모호하지만) 또는 진단 목적 등의 카운터 일 수도 있습니다. 사물 보다는 클래스. 현재 상태와 다른 이벤트 처리기가 다른 두 개의 개별 상태 머신을 갖는 것이 합리적입니까? 그 사실을 상상하기 쉽습니다. 테스트 등을위한 새로운 인스턴스를 쉽게 만들 수 있다는 것을 의미합니다 (독립적 인 테스트를 병렬로 실행할 수 있습니다.) 따라서 기계의 인스턴스에 상태를 갖는 것은 자연스럽게 적합합니다.

존재해야한다고 믿는 사람들이 있습니다 아니요 정적 방법, 아니요 정적 클래스 등. 조금 멀어지고 있다고 생각하지만 항상 최소한 고려하다 통계 도입의 테스트 가능성 영향.

다른 팁

정적 클래스 또는 정적 메소드와 같은 정적 범위 내에서 작업 할 때 "this"를 사용할 수 없습니다.

여기에는 두 가지 옵션이 있습니다. 당신은 통과 할 수 있습니다 null "SYS"매개 변수의 경우. 실제로,이 매개 변수는 정적 클래스의 경우 "발신자"가 항상 정적 클래스이기 때문에 실제로 유용하지 않습니다.

또는 상태 알림을 만드는 것을 고려할 수 있습니다. 하나씩 일어나는 것. 이를 통해 정적이 아닌 클래스의 단일 인스턴스를 가질 수 있습니다. 이는 향후 요구 사항이 변경되면 비 정적 구현으로 쉽게 전환 할 수 있다는 장점이 있습니다.


또한이 이벤트를 제기하기 전에 가입자가 있는지 확인해야합니다. 그렇게하지 않으면 문제가 발생할 수 있습니다.

public static Status State
{
    get { return state; }
    set
    {
        SysInfoEventArgs sysInfo = new SysInfoEventArgs(state, value);
        state = value;
        var handler = OnStateChange;
        if (handler != null)
            handler(null, sysInfo);
    }
}

대의원 수정 :

에서:

public static delegate void StateChangeHandler(object sys, SysInfoEventArgs sysStateInfo);

에게:

public static delegate void StateChangeHandler(SysInfoEventArgs sysStateInfo);

이 코드를 변경하겠습니다.

public static delegate void StateChangeHandler(object sys, SysInfoEventArgs sysStateInfo);
public static event StateChangeHandler OnStateChange;

에게:

public static event Action<SysInfoEventArgs> OnStateChange;

정적 클래스를 유지하고 의미론을 사용하고 싶다면 object sender, 그러면 전달해야 할 적절한 것은입니다 typeof(Sys). 이것은 또한 정적 클래스에서 (오래되고 희귀 한) 잠금 관용구와 유사합니다.

그러나 이벤트 핸들러가 그 가치를 사용하지 않기 때문에 그것은 단지 pedantic 일뿐입니다. null 도 잘 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top