CodeContracts static analysis tool이라는 인수가 있습니다.CodeContracts : null 참조에서 메서드를 호출했을 가능성이 있음
내 코드 :
Screenshot http://i40.tinypic.com/r91zq9.png
이 도구는 instance.bar
가 null 참조가 될 수 있음을 알려줍니다. 나는 그 반대를 믿는다.
누가 맞습니까? 어떻게 잘못했는지 증명할 수 있습니까?
CodeContracts static analysis tool이라는 인수가 있습니다.CodeContracts : null 참조에서 메서드를 호출했을 가능성이 있음
내 코드 :
Screenshot http://i40.tinypic.com/r91zq9.png
이 도구는 instance.bar
가 null 참조가 될 수 있음을 알려줍니다. 나는 그 반대를 믿는다.
누가 맞습니까? 어떻게 잘못했는지 증명할 수 있습니까?
업데이트 : 문제가있는 것 같습니다. invariants are not supported for static fields.
두 번째 업데이트 : 아래에 요약 된 방법은 currently the recommended solution입니다.
가능한 해결 방법은 보유하려는 불변량이 instance
인 Ensure
의 속성을 만드는 것입니다. (물론 Ensure
을 증명하려면 Assume
가 필요합니다.) 일단이 작업을 완료하면 속성을 사용하면 모든 불변량을 올바르게 증명할 수 있습니다. 여기
class Foo
{
private static readonly Foo instance = new Foo();
private readonly string bar;
public static Foo Instance
// workaround for not being able to put invariants on static fields
{
get
{
Contract.Ensures(Contract.Result<Foo>() != null);
Contract.Ensures(Contract.Result<Foo>().bar != null);
Contract.Assume(instance.bar != null);
return instance;
}
}
public Foo()
{
Contract.Ensures(bar != null);
bar = "Hello world!";
}
public static int BarLength()
{
Contract.Assert(Instance != null);
Contract.Assert(Instance.bar != null);
// both of these are proven ok
return Instance.bar.Length;
}
}
CodeContracts가 맞습니다. BarLength()
메서드를 호출하기 전에 instance.bar = null
을 설정하는 데 아무 것도 멈추지 않습니다.
하지만'instance.bar = null'을 아무 곳에서 설정하지 않고'instance.bar'는 private이므로 null이 될 수 없습니까? – dtb
그래, 전체 코드라면 네가 옳다고 생각해. 정적 분석은 아마도 값을 null로 설정했는지 여부를 파악할만큼 똑똑하지 않을 수도 있으므로 가정 할 수 있습니다. 나는 그것을 확인하기 위해 어떤 길이가 될지 모르겠다. – EMP
'instance.bar'가 절대로'null'이 아니라는 것을 어떻게 확신합니까? 'bar'를 읽기 전용으로 만들고 'Contract.Ensures (bar! = null);'을 생성자에 추가하면 트릭이 수행되지 않습니다. 'Contract.Assume (instance.bar! = null);'BarLength()'는 작동하지만 엉망으로 보입니다. – dtb
나는 동의합니다. instance
및 bar
은 모두 비공개이므로 CodeContracts는 instance.bar
이 null로 설정되지 않음을 알 수 있어야합니다.
'bar'필드를 읽기 전용으로 표시하면 정적 분석기가 ctor을 실행 한 후에 그 필드가 다른 것으로 설정되지 않을 것입니다.
private static Foo instance = new Foo();
당신이 때문에 초기화 된 bar
을 보장, 이것이 예를 생성자는 항상 정적 메서드에 액세스하기 전에 실행 한 것을 의미 것으로 가정합니다 :
'bar'를 읽기 전용으로 표시하는 것은 효과가 없습니다. 어떤 이유로 든, 분석기는 생성자의 null이 아닌 값에'bar'를 할당하고 있다는 것을 인식하지 못합니다. – dtb
코드는 개인 정적 초기화 된 인스턴스를 포함?
단일 스레드 케이스에서 나는 당신이 옳다고 생각합니다.
이벤트의 순서는 다음과 같습니다
Foo.BarLength()
에Foo
의 정적 초기화 Foo
instance
의
Foo.BarLength()
그러나 클래스의 정적 초기화는 앱 도메인 당 한 번만 트리거됩니다. IIRC에서는 다른 정적 메소드가 호출되기 전에 이 완료되도록을 보장하기 위해 차단 기능이 없습니다.
Foo.BarLength()
그래서, 당신은이 시나리오 가질 수있다 (이미 완료하지 않은 경우) 클래스 Foo
의 정적 초기화 시작을
Foo.BarLength()
Foo
의 정적 초기화에 전화이 이미 진행되고 있기 때문에Foo.BarLength()
에 : null
에 액세스 계약 분석기는 것을 알 수있는 방법은 없습니다 instance
정적 멤버 코드를 다중 스레드 방식으로 실행하지 않으므로 신중해야합니다.
맞습니다.하지만 (단계 7) 말했듯이,'instance'는 null이 될 것이고,'instance.bar'는 null이 될 것입니다. 'instance.bar'는 Foo 인스턴스의 생성자에 할당되기 전에는 null이지만 인스턴스는 생성자가 완료된 후 필드에 저장됩니다. – dtb
어쨌든 그것은 정적 분석기의 한계입니다. 이제 나는 그것이 내가 옳다는 것을 확신시키는 최선의 방법을 찾고 있습니다. 'Assume' 문이나 결코 발생할 수없는 수표로 내 코드를 지저분하게 만드는 것은 더러웠다. – dtb
예, CLR은 정적 생성자가 서로를 참조하는 두 개의 클래스가 없으면 정적 생성자가 해당 클래스의 다른 항목이 참조되기 전에 완료되는지 확인합니다. http://msdn.microsoft.com/en-us/library/ aa645612.aspx – EMP
,하지만 당신은 당신이 사용하는 비주얼 어떤 스튜디오 테마 말해 수 있을까? – Justin
@ Justin : 내 자신 만의 텍스트 색 구성표가있는 기본 vs2010 테마입니다 (편집 된 게시물 참조). 왜 묻는거야? – dtb
저는 최근에 제 자신의 비주얼 스튜디오 색상 체계를 바꾸고 싶었습니다. 당신이 어딘가에 그것을 다운로드했는지 궁금 해서요. – Justin