Elton Stoneman

  Home  |   Contact  |   Syndication    |   Login
  120 Posts | 0 Stories | 3607 Comments | 0 Trackbacks

News

Archives

Post Categories

[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());

}

 

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati
posted on Monday, September 21, 2009 3:47 PM

Feedback

# re: CA1502:AvoidExcessiveComplexity and Lambdas 5/10/2010 3:48 PM Planos de Hospedagem
very good post.

# re: CA1502:AvoidExcessiveComplexity and Lambdas 10/9/2010 2:44 AM Stegplatten
Awesome information.I never hear about this before.After reading this post a have gained some knowledge about this .Thanks


# re: CA1502:AvoidExcessiveComplexity and Lambdas 11/16/2010 8:43 AM search engine optimisation
You have to watch for false positives when coding in this way, thats certain!

# re: CA1502:AvoidExcessiveComplexity and Lambdas 11/16/2010 8:44 AM Daily Forex Trading
Thanks for another really useful posting. This blog is in my faves.

# re: CA1502:AvoidExcessiveComplexity and Lambdas 11/25/2010 2:33 AM sikiş
Good post thanks for sharing

# re: CA1502:AvoidExcessiveComplexity and Lambdas 1/27/2012 12:40 PM Sanovnik
Looking forward to learn some more from you. Keep it up.Sanovnik

Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: