2016-04-14 4 views
15

Der angegebene CodeVertrag, der die IEnumerable gewährleistet, ist nicht leer

static public int Q() 
{ 
    return Enumerable.Range(0, 100) 
     .Select(i => i) 
     .First(); 
} 

die folgende Warnung aussendet:

warning : CodeContracts: requires unproven: Any(source) 

Wenn ich .Select() Klausel entfernen sie verschwindet.

Aber es ist mir nicht klar, was genau ich brauche .Ensure, so dass die cccheck zufrieden war.

+0

in diesem Code, warum Sie, wenn Sie Quelle in neue Form – Viru

+1

@Viru es ist ein Minimum tragfähige Beispiel speziell um das Problem zu demonstrieren, in Handarbeit verwandeln wollen verwenden wird Select-Methode ... Diese Methode verwendet. In realem Code sind mehr LINQ-Methoden sicher verkettet. – zerkms

+1

@Szeki https://github.com/Microsoft/CodeContracts – zerkms

Antwort

1

Können Sie die Warnung mit diesem Code vermeiden?

var res = Enumerable.Range(0, 100).Select(i => i).Take(1); //execute one query with TOP1 and store in memory 
Contract.Assume(res.Any()); //or res.Count() > 0 //query already in memory 
return res.First(); //query already in memory 
+0

Ja, das ist definitiv eine Verbesserung für meine Antwort (für die Fälle, in denen '.Any()' möglicherweise nicht erwünscht ist). – zerkms

1

Da dies das Problem löst und ist immer noch nicht so hässlich wie man zunächst vielleicht gedacht haben, ich es als Antwort bin Entsendung (wenn man bessere Ideen hat Ich bin offen für Ihre Anregungen obwohl):

static public int Q() 
{ 
    var e = Enumerable.Range(0, 100) 
     .Select(i => i); 

    Contract.Assume(e.Any()); 
    return e.First(); 
} 

Also ich sollte nicht den ganzen Ausdruck teilen müssen, aber der Teil, für den der statische Analysator Angst hatte, und für diesen Teil konnte ich versichern, dass es "alles in Ordnung ist, vertraue mir, ich weiß, was ich tue" .

Eine Anmerkung:

aus irgendeinem Grund weder

Contract.Assert(e.Count() > 0); 

oder

Contract.Assert(e.Any()); 

Arbeit.

Wichtige: wie andere Leute erwähnen, könnte dies für alle Fälle nicht geeignet, da der zusätzliche e.Any() Aufruf die Sammlung materialisieren würde, was in einigen Fällen unerwünscht sein kann (zB: wenn es eine LINQ aus einer 3rd-Party Quelle).

+1

Sie sollten' Contract.Assume (e.Any()); 'nur für gute Form verwenden. –

+0

Wie @Wicher Visser in Frage Kommentar sagte; Das Aufteilen von 'Select' und' First' wird dazu führen; d.h. Entitätsrahmen; TOP1 in der generierten SQL-Abfrage nicht enthalten und die Leistung beeinträchtigt. – jlvaquero

+0

@jlvaquero wird es? – zerkms

Verwandte Themen