2013-06-30 2 views
2

나는 많은 방법과 그 풀어서 속성 _isLoaded라는 사설 읽기 전용의 부울 필드 클래스가 나는 확신 객체 불변 방법이 알고하나의 메소드 만이 특정 필드를 수정할 수 있도록 코드 계약을 작성하는 방법이 있습니까? 공공 부울은 IsLoaded 표시 :

class MyClass 
{ 
    readonly bool _isLoaded; 
    public bool IsLoaded 
    { 
     get { return _isLoaded; } 
    } 

    public void Method1() 
    { 
     //does whatever 
    } 

    public void Method2() 
    { 
     //does another thing 
    } 

    public void Load() 
    { 
     //does a lot of things and then... 
     _isLoaded = true; 
    } 
} 

을 공개 메소드를 호출 한 후, 특정 그 객체는 여전히 일관된 상태를 유지합니다. 마찬가지로, 만약 내가 내 수업이 추가 :

[ContractInvariantMethod] 
void checkState() 
{ 
    Contract.Invariant(!_isLoaded); 
} 

지금, 내 문제가 : 내 경우 (하나의 특정 공용 방법에 대한 ContractInvariantMethod 주석이 메소드를 호출하는 런타임을 말할 수있는 방법이있다, 로드), 그래서 그 중 하나의 방법으로 내 필드의 상태가 변경 될 것이라고 확신 할 수 있습니까?

(또는 다른 방법으로 같은 목적을 달성하십시오)

고마워요.

편집 :
@Liel
감사합니다.
이 패턴은 걱정할 필드가 하나만있을 때 완벽하게 작동합니다.

public abstract class BaseMyClass 
{ 
    private bool _isLoaded; 
    public bool IsLoaded 
    { 
     get { return _isLoaded; } 
    } 
    public virtual void Load() 
    { 
     Contract.Ensures(IsLoaded); 
     _isLoaded = true; 
    } 
} 

public class MyClass : BaseMyClass 
{ 
    public override void Load() 
    { 
     //does a lot of things and then... 
     base.Load(); 
    } 
} 

불행하게도, 정적 검사 내가 사후 조건을 충족 base.Load() 전화를해야 알아낼만큼 똑똑하지 않다 : 나는 또한이 계약 사후 조건을 추가했다. 그것은 내가 단지 Contract.Assume(IsLoaded) 일 수 있다고 제안한다. .. 명백하게, 정적 체커는 완벽하지 않다.

+0

:이를 컴파일 할 때

public class MyClass { bool _isLoaded; public bool IsLoaded { get { return _isLoaded; } } public void Method1() { Contract.Ensures(this._isLoaded == Contract.OldValue(this._isLoaded)); //does whatever _isLoaded = false; } public void Method2() { Contract.Ensures(this._isLoaded == Contract.OldValue(this._isLoaded)); //does another thing } public void Load() { //does a lot of things and then... _isLoaded = true; } } 

, 당신은 다음과 같은 경고를 얻을 수 있습니다를 내 대답이 도움이된다면, 당신은 항상 대답으로 받아 들일 수 있습니다. :) – Liel

답변

0

는 다음과 같은 접근 시도 할 수 있습니다 : 당신이 MyClass에서 IsLoaded에 액세스 할 수 있습니다

public class BaseMyClass 
{ 
    private bool _isLoaded; 
    public bool IsLoaded 
    { 
     get { return _isLoaded; } 
    } 
    public virtual void Load() 
    { 
     _isLoaded = true; 
    } 
} 

public class MyClass : BaseMyClass 
{ 
    public void Method1() 
    { 
     //does whatever 
    } 

    public override void Load() 
    { 
     //does a lot of things and then... 
     base.Load(); 
    } 
} 

이 방법을, 만 Load 재정이 _isLoaded 속성을 변경되었는지 확인합니다.

1

난 당신이 달성하고자하는 것을 이해한다면, 당신은 Contract.OldValue() 구조 사용할 수 있습니다

CodeContracts: ensures unproven: this._isLoaded == Contract.OldValue(this._isLoaded) 
+0

'Contract.OldValue'는 필드가 아닌 매개 변수에 대한 것이라고 생각했습니다. 그러나 그것이 정말로 좋은 디자인이라면, 나는 그걸로 갈 것이라고 생각합니다. 기본 클래스를 구현할 필요가없고, 임의의 수의 필드에서 작동하기 때문에 더 간단한 솔루션이기 때문입니다. 이것이 정말로 좋은 선택이라면 누구나 말할 수 있습니까? – user2212990

+0

필드 나 속성에 완벽하게 사용할 수 있다고 생각합니다. 예를 들어 15 페이지의 "계약 약어 방법"을 참조하십시오. 규칙에서는 "... 이전 표현식은 메소드의 사전 상태에 있던 값을 참조해야합니다. 즉, 다음과 같은 표현식을 사용할 수 있습니다. 방법의 전제 조건이 유지되는 한 평가 될 수 있습니다. " –

+0

사용자 매뉴얼 15 페이지를 읽어 주셔야합니다. 죄송합니다. :) –