나는 순서를 시행하기 위해 코드 계약을 사용하여 불변의 정렬 된 단일 링크 목록 클래스를 설정하려고합니다. 나는 이것에 졸이다 몇 가지 문제로 실행 해요 :코드 계약 정적 분석기에서 이러한 속성 getter 호출을 동일한 것으로 취급하는 이유는 무엇입니까?
이[Pure, ContractVerification(true)]
public class Hierarchy
{
private readonly object _data;
private readonly Hierarchy _childField;
public Hierarchy() { }
public Hierarchy(object data, Hierarchy childParameter) {
Contract.Requires<ArgumentNullException>(childParameter != null);
_data = data;
_childField = childParameter;
Contract.Assert(HasChild);
Contract.Assert(_childField == childParameter);
Contract.Assert(_childField.Data == childParameter.Data);
Contract.Assert(ChildProperty == _childField);
Contract.Assert(ChildProperty.Data == _childField.Data); //Warning -- CodeContracts: assert unproven
}
public bool HasChild { get { return _childField != null; } }
public object Data {
get {
Contract.Ensures(Contract.Result<object>() == _data);
return _data;
}
}
public Hierarchy ChildProperty {
get {
Contract.Requires<InvalidOperationException>(HasChild);
Contract.Ensures(Contract.Result<Hierarchy>() == _childField);
//un-commenting this line causes the assertion to succeed.
//Contract.Ensures(Contract.Result<Hierarchy>().Data == _childField.Data);
return _childField;
}
}
[ContractInvariantMethod]
private void Invariant() {
Contract.Invariant(HasChild == (ChildProperty != null));
}
}
그것은 그 코드 계약이 주장 ChildProperty.Data == _childField.Data
을 입증 할 수 있어야한다고 나에게 보인다. 이전의 어설 션 ChildProperty == _childField
이 성공하고 동일한 객체에서 순수 Data
속성 getter를 두 번 호출하면 동일한 결과가 반환됩니다.
_childField == childParameter
및 _childField.Data == childParameter.Data
이라는 (성공한) 이전 주장에 유의하십시오.
위의 두 번째 주석에서 언급했듯이 ChildProperty
게터에 후행 Contract.Ensures(Contract.Result<Hierarchy>().Data == _child.Data);
을 추가하면이 문제가 해결됩니다. 이것이 우리가해야 할 모든 것임을 유의하십시오.이 경우 코드 계약은 x == y
일 때 x 및 y에 Data
게터를 호출하면 동일한 결과를 산출합니다.
이 해결 방법은이 작은 예제에서는 문제가되지 않지만 큰 클래스에서는 각 유형의 속성에 대한 사후 조건을 추가해야하는 번거 로움이 있습니다.
버그입니까? Child.Data == _child.Data
을 입증 할 수있는 일부 계약 주석 또는 그 밖의 것이 누락 되었습니까? 즉, 문제를 해결할 다른 방법이 있습니까?
글쎄 - 그렇다면 왜 Contract.Assert (x.Data == y.Data)에 대한 다른 호출이 성공할 것인가? 또한 객체를 돌연변이해도 참조의 값이 변경되지 않으므로 _data가 변경 되더라도 참조 동등성 검사가 성공해야합니다. 하지만, 당신이 제안한 사후 조건을 ChildProperty 게터에 추가했는데 결과는 바뀌지 않았습니다. – phoog
+1, Contract.OldValue를 생각 나게하기 위해, 나는 어떤 이유로 간과 했었습니다. 다른 문제를 해결하는 데 도움이되었습니다. – phoog
흥미로운 문제입니다. 나는이 대답이 그것을 해결하지 못한다는 것을 알지만, 다른 사람들이 무슨 일이 일어나는지를 이해할 수 있도록 도움을주기 위해 그것을 떠날 것이다. –