I like to keep my .net code FxCop clean -- and especially when writing an FxCop rule set, it's pretty much part of the ground rules -- even though some of the rules tend at times towards coding for Mort to use your library (rather than educating him). However, FxCop does tend to assume you're coding in any .net language you like, so long as it's C#.
Take this example:
which emulates the C# as
keyword (or C++ dynamic_cast<C *>()
) by contrast to the F# :?> which is more akin to dynamic_cast<C &>()
. I don't mind the CA1004:GenericMethodsShouldProvideTypeParameter
warning this gives -- but taking the F# idiomatic 'a
and generating
warning : CA1709 : Microsoft.Naming : On method 'Patterns.As<a>(object)', correct the
casing of 'a' in generic type parameter name 'a' by changing it to 'A'.
warning : CA1704 : Microsoft.Naming : On method 'Patterns.As<a>(object)', consider
providing a more meaningful name than generic type parameter name 'a'.
warning : CA1715 : Microsoft.Naming : On method 'Patterns.As<a>(object)', prefix generic
type parameter name 'a' with 'T'.
seems a bit excessive, even though replacing it with 'Target
, like you might if you actually had to write it in C# as well, will suppress all three.
And that's just in code I write.
When the code subject to warnings is itself generated, that tends to add a degree of insult to injury. As in
which conjures up CA1707:IdentifiersShouldNotContainUnderscores
from variables state_0
and state_1
in generated code that looks like
or CA1804:RemoveUnusedLocals
for name x
in the guard pattern
which maps to
because symbol x
has to be scoped that way, as well as CA1811:AvoidUncalledPrivateCode
or CA1804:RemoveUnusedLocals
for entities only present in generated code.
That's debug build. In release build (not normally subject to FxCop, since you don't want to have SuppressMessage
attributes floating around in what you ship) we get a different set of messages from differently shaped IL -- for
we at last get the entirely plausible CA1801:ReviewUnusedParameters
(by contrast debug build's function body that assigns the argument to a write-only local causes no warnings!), and for the obvious combinator for chaining state with the Either
type
we get "'arg_1', a parameter, is cast to type 'Either<x, a>._Right' multiple times in method 'Local.op_GreaterMultiplyGreater...
-- but, surprisingly, no warning about underscores in names this time!
This certainly makes it harder to do the right thing, when none of the warnings, apart from the underscores one, actually seem like things that could really be called bugs as such. And it's also harder to frame alternative FxCop rules to use instead of the standard ones, rules that work with F# idiom, beyond possibly the generic type parameter naming cluster.
The debug build for the Feb 2010 CTP is unchanged from this; the release build produces more warnings for both the above cases, mainly about naming -- but also including
"In member 'Module1.op_GreaterMultiplyGreater<q,
x, a, b>(q, Either<x, a>, FSharpFunc<q, FSharpFunc<a,
Either<x, b>>>)', remove the underscores from parameter
name 'arg_0'."