2009-09-24 9 views
2

코드 계약서는 "LINQ 문의 가능성이있는 메서드 호출"경고를 내 LINQ 문의 모든 것에 대해 계속 제공하며 침묵 할 수있는 방법을 찾을 수 없습니다. 예를 들어, 다음 메소드는 null을 먼저 확인하지 않고 "car"객체의 "Make"및 "Model"속성에 액세스하기 때문에 두 가지 경고를 생성합니다. 내 특정 경우코드 계약을 LINQ와 함께 사용할 수있는 방법이 있습니까?

public IEnumerable<string> GetCarModelsByMake(string make) 
    { 
     return from car in Cars 
       where car.Make == make 
       select car.Model; 
    } 

, 나는 자동차 컬렉션에 null 항목을 포함하지 않을 것이라는 점을 알고있다, 그래서 내가 그냥가, 정적 검사를 침묵과 같이하는 방법에 가정 추가 할 수 있습니다 생각 :

public IEnumerable<string> GetCarModelsByMake(string make) 
    { 
     Contract.Assume(Cars.All(car => car != null)); 

     return from car in Cars 
       where car.Make == make 
       select car.Model; 
    } 

그러나 그것은 작동하지 않습니다. 아마 정적 검사기가 이해하기가 너무 많기 때문입니다. 따라서 다음 SuppressMessage 특성을 사용하여 경고를 표시하지 않기로 결정했습니다.

[SuppressMessage("Microsoft.Contracts", "NonNull")] 

그러나 어떤 이유로 든 경고를 표시하지 못합니다.

[SuppressMessage("Microsoft.Contracts", "Requires")] 
    [SuppressMessage("Microsoft.Contracts", "Ensures")] 
    [SuppressMessage("Microsoft.Contracts", "Invariant")] 

나는 심지어 ContractVerification 속성을 사용하는 방법을 완전히 비활성화 계약 검증하려 :

[ContractVerification(false)] 

을하지만 그건하지 않았다 난 일 어느 것도, 다음 SuppressMessage뿐만 아니라 속성 시도 어느 쪽이든 일하십시오. 그래서, 난 그냥 LINQ 문의 "여기서"절에 명시 적으로 널 (null) 검사를 추가 할 것입니다 결정 :

public IEnumerable<string> GetCarModelsByMake(string make) 
    { 
     return from car in Cars 
       where car != null && car.Make == make 
       select car.Model; 
    } 

성공적 "여기서"절에 경고를 제거한다, 그러나 그렇지 않습니다 "select"절에 대한 경고를 제거하십시오. 사실, 실제로 모두 경고를 제거하기 위해 찾은 유일한 방법은 지금처럼 LINQ 문에 모든 절에 널 (null) 검사를 추가하는 것입니다 : 분명히

public IEnumerable<string> GetCarModelsByMake(string make) 
    { 
     return from car in Cars 
       where car != null && car.Make == make 
       select car == null ? null : car.Model; 
    } 

, 즉없는 매우 깨끗 또는 효율적인 코드 , 그리고 실제로 모든 LINQ 문에 이러한 중복 null 검사를 추가 할 생각은 없습니다. 특히 열거 형에 null 항목이 포함되어 있지 않은 경우에는주의해야합니다. 이 문제를 해결하는 최선의 방법은 정적 검사기가 컬렉션의 각 항목에 대해 null이 아닌 값을 보장하는 Contract.Assume 문을 이해할 수 있지만 그렇게 할 수없는 경우 메서드의 SuppressMessage 특성을 준수하는 것입니다 .

답변

5

자동차 점검시 Null에 대해 불평 할 수 있습니다. 이 시도 : 자동차가 null의 경우는 예외를 얻을 수 있습니다

 
return Cars.Where(car => car.Make == make).Select(car => car.Model); 

:

 
public IEnumerable GetCarModelsByMake(string make) 
{ 
    if (null == Cars) 
     return new string[0]; // or null if you like 

    return from car in Cars 
     where car.Make == make 
     select car.Model; 
} 

는 기억이 LINQ 문 효과적으로 동일합니다.

+0

+1하지만 나는'Cars!= null '을 클래스 불변 식이자는 원래 코드의 정신에 더 가깝게 머물 것인데, 이는 분명히'자동차 '가'null '이 될 것으로 기대하지 않습니다. http://msdn.microsoft.com/en-us/magazine/ee236408.aspx#id0070066 –

+0

물론입니다. 이 클래스의 불변량은이 질문의 코드 계약 성격에 더 적합합니다. –

+0

클래스에 이미 Cars! = null을 보장하는 불변성이 있음을 분명히 했어야합니다. 그것은 계약 경고에 관한 것이 아닙니다. 경고는 "car"컬렉션이 아니라 "car"변수가 null 인 것에 대한 것입니다. –

2

코드 계약의 최신 버전을 사용해 보셨습니까? 10 월에 출시 된 제품이 있었는데이 제품을이 제품으로 재현 할 수 없습니다.

코드 계약에는 Contracts 클래스에 정의 된 ForAll 메서드가 있습니다.이 메서드는 LINQ 확장 All 메서드보다 논리가 더 효율적일 수 있습니다.

관련 문제