Geeks With Blogs

News This is the *old* blog. The new one is at blog.sixeyed.com
Elton Stoneman
This is the *old* blog. The new one is at blog.sixeyed.com

[Source: http://geekswithblogs.net/EltonStoneman]

In code with lots of lambda expressions, you may trigger a false positive for the Code Analysis rule CA1502 "AvoidExcessiveComplexity". The rule calculates cyclomatic complexity using the logic in Microsoft.FxCop.Sdk.MethodMetrics, which enumerates the instruction set and increments complexity count when it finds one of a given set of opcodes.

The rule was triggered by code which uses the Fluent DAL approach to populate a composite entity:

public static Entity GetEntity(int entityId)

{

//populate basic details:

Entity entity = Fluently.Load<Entity>().With<EntityMap>()

.From<GetEntity>(i => i.Id = entityId,

x => x.Execute());

 

//load child entities:

if (entity.IsKnown)

{

entity.Address = Fluently.Load<Address>().With<AddressMap>()

.From<GetEntityAddresses>(i => i.Id = entityId,

x => x.Execute());

entity.Contact = Fluently.Load<Contact>().With<ContactMap>()

.From<GetEntityContacts>(i => i.Id = entityId,

x => x.Execute());

}

else

{

//more of the same...

 

The method in question had a single if/else branch, no other conditional logic, but 7 fluent calls totalling 12 lambdas. I calculate the cyclomatic complexity to be 2, and NDepend agrees. FxCop tells me the complexity is 26.

I stripped this down to a much simpler sample and found the same issue:

public void CCCheck2()

{

Fluently.Load().With().From(i => i.ToString(), x => x.ToString());

Fluently.Load().With().From(i => i.ToString(), x => x.ToString());

Fluently.Load().With().From(i => i.ToString(), x => x.ToString());

}

- this gives a CC of 13, although it has no conditional logic at all.

The answer's in the IL – the lambdas are emitted as private static classes and executed using an instance which is lazy-loaded:

IL_000b: ldsfld class [System.Core]System.Func`2<int32,string> FxCopCC.LambdaSample::'CS$<>9__CachedAnonymousMethodDelegate6'

IL_0010: brtrue.s IL_0025

IL_0012: ldnull

IL_0013: ldftn string FxCopCC.LambdaSample::'<CCCheck>b__0'(int32)

IL_0019: newobj instance void class [System.Core]System.Func`2<int32,string>::.ctor(object,

native int)

IL_001e: stsfld class [System.Core]System.Func`2<int32,string> FxCopCC.LambdaSample::'CS$<>9__CachedAnonymousMethodDelegate6'

IL_0023: br.s IL_0025

br and brtrue are transfer of control statements, so every lambda expression actually causes a branch – where the IL checks to see if there's a cached instance of the delegate, or whether it needs to instantiate one – and a return. The complexity rating is correct for the IL, as 1 + 2x(number of lambdas).

But cyclomatic complexity is a measure of readability, so the additional branches in the IL should be irrelevant. The short term solution is to suppress the message on methods with heavy lambda usage. A longer term option is an alternative rule which uses a different calculation.

A side point is that the IL isn't aggressively optimised by the compiler – lambdas with identical code are generated as separate private classes, each with their own lazy-loading check, so to avoid that overhead lambdas which are reused can be centralised:

private Func<int, string> GetInitialise()

{

return new Func<int,string>(i => i.ToString());

}

 

 

Posted on Monday, September 21, 2009 3:47 PM FxCop | Back to top


Comments on this post: CA1502:AvoidExcessiveComplexity and Lambdas

# re: CA1502:AvoidExcessiveComplexity and Lambdas
Requesting Gravatar...
very good post.
Left by Planos de Hospedagem on May 10, 2010 3:48 PM

# re: CA1502:AvoidExcessiveComplexity and Lambdas
Requesting Gravatar...
Awesome information.I never hear about this before.After reading this post a have gained some knowledge about this .Thanks
Left by Stegplatten on Oct 09, 2010 2:44 AM

# re: CA1502:AvoidExcessiveComplexity and Lambdas
Requesting Gravatar...
You have to watch for false positives when coding in this way, thats certain!
Left by search engine optimisation on Nov 16, 2010 8:43 AM

# re: CA1502:AvoidExcessiveComplexity and Lambdas
Requesting Gravatar...
Thanks for another really useful posting. This blog is in my faves.
Left by Daily Forex Trading on Nov 16, 2010 8:44 AM

# re: CA1502:AvoidExcessiveComplexity and Lambdas
Requesting Gravatar...
Good post thanks for sharing
Left by sikiş on Nov 25, 2010 2:33 AM

# re: CA1502:AvoidExcessiveComplexity and Lambdas
Requesting Gravatar...
Looking forward to learn some more from you. Keep it up.Sanovnik
Left by Sanovnik on Jan 27, 2012 12:40 PM

Your comment:
 (will show your gravatar)


Copyright © Elton Stoneman | Powered by: GeeksWithBlogs.net