1160 строки
46 KiB
XML
1160 строки
46 KiB
XML
<?xml version="1.0"?>
|
|
<doc>
|
|
<assembly>
|
|
<name>Gendarme.Rules.Performance</name>
|
|
</assembly>
|
|
<members>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidConcatenatingCharsRule">
|
|
<summary>
|
|
This rule will warn you if boxing is used to concatenate a string
|
|
since this will slow down your code and can be easily avoided. This
|
|
often happen when concatenating <c>System.String</c> and <c>System.Char</c>
|
|
values together. However the rule is not limited to check boxing on
|
|
<c>System.Char</c> since compilers often transform a character into its
|
|
integer value (e.g. 'a' == 61) and the same boxing issue exists on integers.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public string PrintIndex (string a, char b)
|
|
{
|
|
// This is compiled into String.Concat(params object[])
|
|
// and requires boxing the 4 characters
|
|
Console.WriteLine ('[' + a + ',' + b + ']');
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public string PrintIndex (string a, char b)
|
|
{
|
|
// This is compiled into String.Concat(params string[])
|
|
// and no boxing is required
|
|
Console.WriteLine ("[" + a + "," + b.ToString () + "]");
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.8</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidLargeNumberOfLocalVariablesRule">
|
|
<summary>
|
|
This rule warns when the number of local variables exceed a maximum value (default is
|
|
64). Having a large amount of local variables makes it hard to generate code that
|
|
performs well and, likely, makes the code harder to understand.
|
|
</summary>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="P:Gendarme.Rules.Performance.AvoidLargeNumberOfLocalVariablesRule.MaximumVariables">
|
|
<summary>The maximum number of local variables which methods may have without a defect being reported.</summary>
|
|
<remarks>Defaults to 64.</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidLargeStructureRule">
|
|
<summary>
|
|
This rule will fire if a value type (struct in C#) is larger than a maximum value
|
|
(16 bytes by default). This is a problem because, unlike reference types, value
|
|
types are bitwise-copied whenever they are assigned to a variable or passed to
|
|
a method. If the type
|
|
cannot be reduced in size then it should be
|
|
turned into a reference type (class in C#).
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public struct BigArgb {
|
|
long a, r, g, b;
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public sealed class BigArgb {
|
|
long a, r, g, b;
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="P:Gendarme.Rules.Performance.AvoidLargeStructureRule.MaxSize">
|
|
<summary>The maximum size structs may be without a defect.</summary>
|
|
<remarks>Defaults to 16 bytes.</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidLocalDataStoreSlotRule">
|
|
<summary>
|
|
This rule warns if a method use <c>LocalDataStoreSlot</c> to store or
|
|
retrieve data from Thread or Context Local Storage. The faster alternative
|
|
is to use <c>[ThreadStatic]</c> or <c>[ContextStatic]</c> attributes to avoid
|
|
extra calls and typecasts.
|
|
Also <c>[ThreadStatic]</c> is available on Silverlight while the
|
|
<c>LocalDataStoreSlot</c> API are not.
|
|
</summary>
|
|
<example>
|
|
Bad example (Thread Local Storage):
|
|
<code>
|
|
static void SetSharedKey (byte[] key)
|
|
{
|
|
LocalDataStoreSlot lds = Thread.AllocateNamedDataSlot ("shared-key");
|
|
lds.SetData (key.Clone ());
|
|
}
|
|
public byte[] SignData (byte[] data)
|
|
{
|
|
LocalDataStoreSlot lds = Thread.GetNamedDataSlot ("shared-key");
|
|
using (HMACSHA1 hmac = new HMACSHA1 (Thread.GetData (lds) as byte[])) {
|
|
return hmac.ComputeHash (data);
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example (Thread Local Storage):
|
|
<code>
|
|
[ThreadStatic]
|
|
static byte[] shared_key;
|
|
static void SetSharedKey (byte[] key)
|
|
{
|
|
shared_key = (byte[]) key.Clone ();
|
|
}
|
|
public byte[] SignData (byte[] data)
|
|
{
|
|
using (HMACSHA1 hmac = new HMACSHA1 (shared_key)) {
|
|
return hmac.ComputeHash (data);
|
|
}
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.8</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidMethodWithLargeMaximumStackSizeRule">
|
|
<summary>
|
|
This rule fires if a method has a large maximum stack size (default is
|
|
100). Having a large maximum stack size makes it hard to generate code that
|
|
performs well and, likely, makes the code harder to understand.
|
|
</summary>
|
|
<remarks>This rule is available since Gendarme 2.6</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidRepetitiveCallsToPropertiesRule">
|
|
<summary>
|
|
The rule warn if virtual, or unlikely to be inline-able, property getters
|
|
are called several times by a method. In most cases repetitive calls simply
|
|
requires more time without any gains since the result will always be identical.
|
|
You should ignore the reported defects if a different value is expected
|
|
each time the property is called (e.g. calling <c>DateTime.Now</c>).
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
private int Report (IList list)
|
|
{
|
|
if (list.Count > 1) {
|
|
DisplayList (list);
|
|
}
|
|
Console.WriteLine ("# items: {0}", list.Count);
|
|
return list.Count;
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
private int Report (IList list)
|
|
{
|
|
int count = list.Count;
|
|
if (count > 1) {
|
|
DisplayList (list);
|
|
}
|
|
Console.WriteLine ("# items: {0}", count);
|
|
return count;
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.8</remarks>
|
|
</member>
|
|
<member name="P:Gendarme.Rules.Performance.AvoidRepetitiveCallsToPropertiesRule.InlineLimit">
|
|
<summary>
|
|
Methods with a code size below InlineLimit (20 by default)
|
|
are considered to be inline-able by the JIT.
|
|
</summary>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidRepetitiveCastsRule">
|
|
<summary>
|
|
This rule fires if multiple casts are done on the same value, for the same type.
|
|
Casts are expensive so reducing them, by changing the logic or caching the
|
|
result, can help performance.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
foreach (object o in list) {
|
|
// first cast (is)
|
|
if (o is ICollection) {
|
|
// second cast (as) if item implements ICollection
|
|
Process (o as ICollection);
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
foreach (object o in list) {
|
|
// a single cast (as) per item
|
|
ICollection c = (o as ICollection);
|
|
if (c != null) {
|
|
SingleCast (c);
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
// first cast (is):
|
|
if (o is IDictionary) {
|
|
// second cast if item implements IDictionary:
|
|
Process ((IDictionary) o);
|
|
// first cast (is):
|
|
} else if (o is ICollection) {
|
|
// second cast if item implements ICollection:
|
|
Process ((ICollection) o);
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
// a single cast (as) per item
|
|
IDictionary dict;
|
|
ICollection col;
|
|
if ((dict = o as IDictionary) != null) {
|
|
SingleCast (dict);
|
|
} else if ((col = o as ICollection) != null) {
|
|
SingleCast (col);
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidReturningArraysOnPropertiesRule">
|
|
<summary>
|
|
This rule check for properties which return arrays. This can be a problem because
|
|
properties are supposed to execute very quickly so it's likely that this property
|
|
is returning a reference to the internal state of the object. This means that
|
|
the caller can change the object's internal state via a back-door channel which
|
|
is usually a very bad thing and it means that the array's contents may change
|
|
unexpectedly if the caller holds onto the array.
|
|
The preferred approach is to either return a read-only collection or to change
|
|
the property to a method and return a copy of the array (it's important to use
|
|
a method so that callers are not misled about the performance of the property).
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public byte[] Foo {
|
|
get {
|
|
// return the data inside the instance
|
|
return foo;
|
|
}
|
|
}
|
|
public byte[] Bar {
|
|
get {
|
|
// return a copy of the instance's data
|
|
// (this is bad because users expect properties to execute quickly)
|
|
return (byte[]) bar.Clone ();
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public byte[] GetFoo ()
|
|
{
|
|
return (byte[]) foo.Clone ();
|
|
}
|
|
public byte[] GetFoo ()
|
|
{
|
|
return (byte[]) bar.Clone ();
|
|
}
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidTypeGetTypeForConstantStringsRule">
|
|
<summary>
|
|
This rule warns when a method use <c>Type.GetType(string)</c> with a constant string.
|
|
Such calls requires reflection in order to return a <c>Type</c> instance and, for
|
|
known types, can be replaced with a much faster <c>typeof(x)</c>.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
booleanType = Type.GetType ("System.Boolean");
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
booleanType = typeof (bool);
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUncalledPrivateCodeRule">
|
|
<summary>
|
|
This rule will check for internally visible methods which are never called.
|
|
The rule will warn you if a private method isn't called in its declaring type or
|
|
if an internal method doesn't have any callers in the assembly or isn't invoked by
|
|
the runtime or a delegate.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public class MyClass {
|
|
private void MakeSuff ()
|
|
{
|
|
// ...
|
|
}
|
|
public void Method ()
|
|
{
|
|
Console.WriteLine ("Foo");
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example (removing unused code):
|
|
<code>
|
|
public class MyClass {
|
|
public void Method ()
|
|
{
|
|
Console.WriteLine ("Foo");
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example (use the code):
|
|
<code>
|
|
public class MyClass {
|
|
private void MakeSuff ()
|
|
{
|
|
// ...
|
|
}
|
|
public void Method ()
|
|
{
|
|
Console.WriteLine ("Foo");
|
|
MakeSuff ();
|
|
}
|
|
}
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUninstantiatedInternalClassesRule">
|
|
<summary>
|
|
This rule will fire if a type is only visible within its assembly, can be instantiated, but
|
|
is not instantiated. Such types are often leftover (dead code) or are debugging/testing
|
|
code and not required. However in some case the types might by needed, e.g. when
|
|
accessed thru reflection or if the <c>[InternalsVisibleTo]</c> attribute is used on the
|
|
assembly.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
// defined, but never instantiated
|
|
internal class MyInternalClass {
|
|
// ...
|
|
}
|
|
public class MyClass {
|
|
static void Main ()
|
|
{
|
|
// ...
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
internal class MyInternalClass {
|
|
// ...
|
|
}
|
|
public class MyClass {
|
|
static void Main ()
|
|
{
|
|
MyInternalClass c = new MyInternalClass ();
|
|
// ...
|
|
}
|
|
}
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUnnecessaryOverridesRule">
|
|
<summary>
|
|
This rule looks for overriding methods which just call the base method, and don't
|
|
define any additional attributes or security declarations.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public override string ToString ()
|
|
{
|
|
return base.ToString ();
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example (different attributes):
|
|
<code>
|
|
[FileIOPermission (SecurityAction.Demand, @"c:\dir\file")]
|
|
public override string ToString ()
|
|
{
|
|
return base.ToString ();
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example (remove override):
|
|
<code>
|
|
/*public override string ToString ()
|
|
{
|
|
return base.ToString ();
|
|
}*/
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUnneededCallsOnStringRule">
|
|
<summary>
|
|
This rule detects when some methods, like <c>Clone()</c>, <c>Substring(0)</c>,
|
|
<c>ToString()</c> or <c>ToString(IFormatProvider)</c>, are being called on a
|
|
string instance. Since these calls all return the original string they don't do anything
|
|
useful and should be carefully reviewed to see if they are working as intended and,
|
|
if they are, the method call can be removed.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public void PrintName (string name)
|
|
{
|
|
Console.WriteLine ("Name: {0}", name.ToString ());
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public void PrintName (string name)
|
|
{
|
|
Console.WriteLine ("Name: {0}", name);
|
|
}
|
|
</code></example>
|
|
<remarks>Prior to Gendarme 2.0 this rule was more limited and named AvoidToStringOnStringsRule</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUnneededFieldInitializationRule">
|
|
<summary>
|
|
This rule looks for constructors that assign fields to their default value
|
|
(e.g. 0 for an integer, null for an object or a string). Since the CLR zero initializes
|
|
all values there is no need, under most circumstances, to assign default values.
|
|
Doing so only adds size to source code and in IL.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public class Bad {
|
|
int i;
|
|
string s;
|
|
public Bad ()
|
|
{
|
|
i = 0;
|
|
s = null;
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public class Good {
|
|
int i;
|
|
string s;
|
|
public Good ()
|
|
{
|
|
// don't assign 'i' since it's already 0
|
|
// but we might prefer to assign a string to String.Empty
|
|
s = String.Empty;
|
|
}
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.2</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUnneededUnboxingRule">
|
|
<summary>
|
|
This rule checks methods which unbox the same value type multiple times (i.e. the
|
|
value is copied from the heap into the stack). Because the copy is relatively expensive,
|
|
the code should be rewritten to minimize unboxes. For example, using a local variable
|
|
of the right value type should remove the need for more than one unbox instruction
|
|
per variable.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public struct Message {
|
|
private int msg;
|
|
private IntPtr hwnd, lParam, wParam, IntPtr result;
|
|
public override bool Equals (object o)
|
|
{
|
|
bool result = (this.msg == ((Message) o).msg);
|
|
result &= (this.hwnd == ((Message) o).hwnd);
|
|
result &= (this.lParam == ((Message) o).lParam);
|
|
result &= (this.wParam == ((Message) o).wParam);
|
|
result &= (this.result == ((Message) o).result);
|
|
return result;
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public struct Message {
|
|
private int msg;
|
|
private IntPtr hwnd, lParam, wParam, IntPtr result;
|
|
public override bool Equals (object o)
|
|
{
|
|
Message msg = (Message) o;
|
|
bool result = (this.msg == msg.msg);
|
|
result &= (this.hwnd == msg.hwnd);
|
|
result &= (this.lParam == msg.lParam);
|
|
result &= (this.wParam == msg.wParam);
|
|
result &= (this.result == msg.result);
|
|
return result;
|
|
}
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUnsealedConcreteAttributesRule">
|
|
<summary>
|
|
This rule fires if an attribute is defined which is both concrete (i.e. not abstract)
|
|
and unsealed. This is a performance problem because it means that
|
|
<c>System.Attribute.GetCustomAttribute</c> has to search the attribute type
|
|
hierarchy for derived types. To fix this either seal the type or make it abstract.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
[AttributeUsage (AttributeTargets.All)]
|
|
public class BadAttribute : Attribute {
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example (sealed):
|
|
<code>
|
|
[AttributeUsage (AttributeTargets.All)]
|
|
public sealed class SealedAttribute : Attribute {
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example (abstract and sealed):
|
|
<code>
|
|
[AttributeUsage (AttributeTargets.All)]
|
|
public abstract class AbstractAttribute : Attribute {
|
|
}
|
|
[AttributeUsage (AttributeTargets.All)]
|
|
public sealed class ConcreteAttribute : AbstractAttribute {
|
|
}
|
|
</code></example>
|
|
<remarks>Before Gendarme 2.0 this rule was named AvoidUnsealedAttributesRule.</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUnsealedUninheritedInternalTypeRule">
|
|
<summary>
|
|
This rule will fire for classes which are internal to the assembly and have no derived
|
|
classes, but are not <c>sealed</c>. Sealing the type clarifies the type hierarchy and
|
|
allows the compiler/JIT to perform optimizations such as eliding virtual method calls.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
// this one is correct since MyInheritedStuff inherits from this class
|
|
internal class MyBaseStuff {
|
|
}
|
|
// this one is bad, since no other class inherit from MyConcreteStuff
|
|
internal class MyInheritedStuff : MyBaseStuff {
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
// this one is correct since the class is abstract
|
|
internal abstract class MyAbstractStuff {
|
|
}
|
|
// this one is correct since the class is sealed
|
|
internal sealed class MyConcreteStuff : MyAbstractStuff {
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0 and, before 2.2, was named AvoidUnsealedUninheritedInternalClassesRule</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUnusedParametersRule">
|
|
<summary>
|
|
This rule is used to ensure that all parameters in a method signature are being used.
|
|
The rule wont report a defect against the following:
|
|
<list><item><description>Methods that are referenced by a delegate;</description></item><item><description>Methods used as event handlers;</description></item><item><description>Abstract methods;</description></item><item><description>Virtual or overriden methods;</description></item><item><description>External methods (e.g. p/invokes)</description></item></list></summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public void MethodWithUnusedParameters (IEnumerable enumerable, int x)
|
|
{
|
|
foreach (object item in enumerable) {
|
|
Console.WriteLine (item);
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public void MethodWithUsedParameters (IEnumerable enumerable)
|
|
{
|
|
foreach (object item in enumerable) {
|
|
Console.WriteLine (item);
|
|
}
|
|
}
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.AvoidUnusedPrivateFieldsRule">
|
|
<summary>
|
|
This rule checks all private fields inside each type to see if some of them are not
|
|
being used. This could be a leftover from debugging or testing code or a more
|
|
serious typo where a wrong field is being used. In any case this makes the type bigger
|
|
than it needs to be which can affect performance when a large number of instances
|
|
exist.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public class Bad {
|
|
int level;
|
|
bool b;
|
|
public void Indent ()
|
|
{
|
|
level++;
|
|
#if DEBUG
|
|
if (b) Console.WriteLine (level);
|
|
#endif
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public class Good {
|
|
int level;
|
|
#if DEBUG
|
|
bool b;
|
|
#endif
|
|
public void Indent ()
|
|
{
|
|
level++;
|
|
#if DEBUG
|
|
if (b) Console.WriteLine (level);
|
|
#endif
|
|
}
|
|
}
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.CompareWithEmptyStringEfficientlyRule">
|
|
<summary>
|
|
This rule will fire if a string is compared to <c>""</c> or <c>String.Empty</c>.
|
|
Instead use a <c>String.Length</c> test which should be a bit faster. Another
|
|
possibility (with .NET 2.0) is to use the static <c>String.IsNullOrEmpty</c> method.
|
|
<c>String.IsNullOrEmpty</c>.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public void SimpleMethod (string myString)
|
|
{
|
|
if (myString.Equals (String.Empty)) {
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public void SimpleMethod (string myString)
|
|
{
|
|
if (myString.Length == 0) {
|
|
}
|
|
}
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.ConsiderCustomAccessorsForNonVisibleEventsRule">
|
|
<summary>
|
|
This rule looks for non-visible events to see if their add/remove accessors are
|
|
the default ones. The default, compiler generated, accessor is marked as synchronized
|
|
which means that the runtime will bracket them between <c>Monitor.Enter</c> and
|
|
<c>Monitor.Exit</c> calls. This is the safest approach unless, for non-visible events,
|
|
you have a performance bottleneck around the events. In this case you should review
|
|
if your code needs the locks or if you can provide an alternative to them.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
private event EventHandler<TestEventArgs> TimeCritical;
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
static object TimeCriticalEvent = new object ();
|
|
EventHandlerList events = new EventHandlerList ();
|
|
private event EventHandler<TestEventArgs> TimeCritical {
|
|
add {
|
|
events.AddHandler (TimeCriticalEvent, value);
|
|
}
|
|
remove {
|
|
events.AddHandler (TimeCriticalEvent, value);
|
|
}
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.DoNotIgnoreMethodResultRule">
|
|
<summary>
|
|
This rule fires if a method is called that returns a new instance but that instance
|
|
is not used. This is a performance problem because it is wasteful to create and
|
|
collect objects which are never actually used. It may also indicate a logic problem.
|
|
Note that this rule currently only checks methods within a small number of System
|
|
types.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public void GetName ()
|
|
{
|
|
string name = Console.ReadLine ();
|
|
// This is a bug: strings are (mostly) immutable so Trim leaves
|
|
// name untouched and returns a new string.
|
|
name.Trim ();
|
|
Console.WriteLine ("Name: {0}", name);
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public void GetName ()
|
|
{
|
|
string name = Console.ReadLine ();
|
|
name = name.Trim ();
|
|
Console.WriteLine ("Name: {0}", name);
|
|
}
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.RemoveUnneededFinalizerRule">
|
|
<summary>
|
|
This rule looks for types that have an empty finalizer (a.k.a. destructor in C# or
|
|
<c>Finalize</c> method). Finalizers that simply set fields to null are considered to be
|
|
empty because this does not help the garbage collection. You should remove the empty
|
|
finalizer to alleviate pressure on the garbage collector and finalizer thread.
|
|
</summary>
|
|
<example>
|
|
Bad example (empty):
|
|
<code>
|
|
class Bad {
|
|
~Bad ()
|
|
{
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Bad example (only nulls fields):
|
|
<code>
|
|
class Bad {
|
|
object o;
|
|
~Bad ()
|
|
{
|
|
o = null;
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
class Good {
|
|
object o;
|
|
}
|
|
</code></example>
|
|
<remarks>Prior to Gendarme 2.2 this rule was named EmptyDestructorRule</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.UseSuppressFinalizeOnIDisposableTypeWithFinalizerRule">
|
|
<summary>
|
|
This rule will fire if a type implements <c>System.IDisposable</c> and has a finalizer
|
|
(called a destructor in C#), but the Dispose method does not call <c>System.GC.SuppressFinalize</c>.
|
|
Failing to do this should not cause properly written code to fail, but it does place a non-trivial
|
|
amount of extra pressure on the garbage collector and on the finalizer thread.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
class BadClass : IDisposable {
|
|
~BadClass ()
|
|
{
|
|
Dispose (false);
|
|
}
|
|
public void Dispose ()
|
|
{
|
|
// GC.SuppressFinalize is missing so the finalizer will be called
|
|
// which puts needless extra pressure on the garbage collector.
|
|
Dispose (true);
|
|
}
|
|
private void Dispose (bool disposing)
|
|
{
|
|
if (ptr != IntPtr.Zero) {
|
|
Free (ptr);
|
|
ptr = IntPtr.Zero;
|
|
}
|
|
}
|
|
[DllImport ("somelib")]
|
|
private static extern void Free (IntPtr ptr);
|
|
private IntPtr ptr;
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
class GoodClass : IDisposable {
|
|
~GoodClass ()
|
|
{
|
|
Dispose (false);
|
|
}
|
|
public void Dispose ()
|
|
{
|
|
Dispose (true);
|
|
GC.SuppressFinalize (this);
|
|
}
|
|
private void Dispose (bool disposing)
|
|
{
|
|
if (ptr != IntPtr.Zero) {
|
|
Free (ptr);
|
|
ptr = IntPtr.Zero;
|
|
}
|
|
}
|
|
[DllImport ("somelib")]
|
|
private static extern void Free (IntPtr ptr);
|
|
private IntPtr ptr;
|
|
}
|
|
</code></example>
|
|
<remarks>Prior to Gendarme 2.2 this rule was named IDisposableWithDestructorWithoutSuppressFinalizeRule</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.ImplementEqualsTypeRule">
|
|
<summary>
|
|
This rule looks for types that override <c>Object.Equals(object)</c> but do not
|
|
provide a <c>Equals(x)</c> overload using the type. Such an overload removes the
|
|
need to cast the object to the correct type. For value types this also removes the
|
|
costly boxing operations. Assemblies targeting .NET 2.0 (and later) should
|
|
also implement <c>System.IEquatable<T></c>.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public class Bad {
|
|
public override bool Equals (object obj)
|
|
{
|
|
return base.Equals (obj);
|
|
}
|
|
public override int GetHashCode ()
|
|
{
|
|
return base.GetHashCode ();
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
// IEquatable<T> is only available since
|
|
// version 2.0 of the .NET framework
|
|
public class Good : IEquatable<Good> {
|
|
public override bool Equals (object obj)
|
|
{
|
|
return (obj as Good);
|
|
}
|
|
public bool Equals (Good other)
|
|
{
|
|
return (other != null);
|
|
}
|
|
public override int GetHashCode ()
|
|
{
|
|
return base.GetHashCode ();
|
|
}
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.MathMinMaxCandidateRule">
|
|
<summary>
|
|
This rule checks methods for code which seems to duplicate <c>Math.Min</c> or
|
|
<c>Math.Max</c>. The JIT can inline these methods and generate
|
|
better code for, at least some types, than it can for a custom inline
|
|
implementation.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
int max = (a > b) ? a : b;
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
int max = Math.Max (a, b);
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.OverrideValueTypeDefaultsRule">
|
|
<summary>
|
|
This rule checks all value types, except enumerations, to see if they use the default
|
|
implementation of <c>Equals(object)</c> and <c>GetHashCode()</c> methods. While
|
|
<c>ValueType</c> implementations work for any value type they do so at the expense of
|
|
performance (the default implementation uses reflection to access fields). You can easily
|
|
override both methods
|
|
with much faster code since you know all meaningful fields inside your structure.
|
|
At the same time you should also provide, if your language allows it, operator overloads
|
|
for equality (<c>op_Equality</c>, <c>==</c>) and inequality (<c>op_Inequality</c>,
|
|
<c>!=</c>).
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public struct Coord {
|
|
int X, Y, Z;
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public struct Coord {
|
|
int X, Y, Z;
|
|
public override bool Equals (object obj)
|
|
{
|
|
if (obj == null) {
|
|
return false;
|
|
}
|
|
Coord c = (Coord)obj;
|
|
return ((X == c.X) && (Y == c.Y) && (Z == c.Z));
|
|
}
|
|
public override int GetHashCode ()
|
|
{
|
|
return X ^ Y ^ Z;
|
|
}
|
|
public static bool operator == (Coord left, Coord right)
|
|
{
|
|
return left.Equals (right);
|
|
}
|
|
public static bool operator != (Coord left, Coord right)
|
|
{
|
|
return !left.Equals (right);
|
|
}
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.PreferCharOverloadRule">
|
|
<summary>
|
|
This rule looks for calls to <c>String</c> methods that use <b>String</b>
|
|
parameters when a <c>Char</c> parameter could have been used. Using the
|
|
<c>Char</c> overload is preferred because it will be faster.
|
|
Note, however, that this may result in subtly different behavior on versions of
|
|
.NET before 4.0: the string overloads do a culture based comparison using
|
|
<c>CultureInfo.CurrentCulture</c> and the char methods do an ordinal
|
|
comparison (a simple compare of the character values). This can result in
|
|
a change of behavior (for example the two can produce different results when
|
|
precomposed characters are used). If this is important it is best to use an
|
|
overload that allows StringComparison or CultureInfo to be explicitly specified
|
|
see [http://msdn.microsoft.com/en-us/library/ms973919.aspx#stringsinnet20_topic4]
|
|
for more details.
|
|
With .NET 4.0 <c>String</c>'s behavior will change and the various methods
|
|
will be made more consistent. In particular the comparison methods will be changed
|
|
so that they all default to doing an ordinal comparison.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
if (s.IndexOf (":") == -1) {
|
|
Console.WriteLine ("no separator found");
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
if (s.IndexOf (':') == -1) {
|
|
Console.WriteLine ("no separator found");
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.4</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.PreferInterfaceConstraintOnGenericParameterForPrimitiveInterfaceRule">
|
|
<summary>
|
|
This rule fires if a method use an interface of a primitive type as parameter.
|
|
(IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<int> ...)
|
|
Using generic method with an interface constraint instead avoid boxing of value
|
|
type when calling the method.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public bool GreaterThan (IComparable arg1, IComparable arg2)
|
|
{
|
|
return arg1.CompareTo (arg2) > 0
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public bool GreaterThan<T> (T arg1, T arg2) where T : IComparable
|
|
{
|
|
return arg1.CompareTo (arg2) > 0
|
|
}
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.PreferLiteralOverInitOnlyFieldsRule">
|
|
<summary>
|
|
This rule looks for <c>InitOnly</c> fields (<c>readonly</c> in C#) that could be
|
|
turned into <c>Literal</c> (<c>const</c> in C#) because their value is known at
|
|
compile time. <c>Literal</c> fields don't need to be initialized (i.e. they don't
|
|
force the compiler to add a static constructor to the type) resulting in less code and the
|
|
value (not a reference to the field) will be directly used in the IL (which is OK
|
|
if the field has internal visibility, but is often problematic if the field is visible outside
|
|
the assembly).
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public class ClassWithReadOnly {
|
|
static readonly int One = 1;
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public class ClassWithConst
|
|
{
|
|
const int One = 1;
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.2</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.RemoveUnusedLocalVariablesRule">
|
|
<summary>
|
|
This rule looks for unused local variables inside methods. This can leads to larger
|
|
code (IL) size and longer JIT time, but note that some optimizing compilers
|
|
can remove the locals so they won't be reported even if you can still see them in
|
|
the source code. This could also be a typo in the source were a value is assigned
|
|
to the wrong variable.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
bool DualCheck ()
|
|
{
|
|
bool b1 = true;
|
|
bool b2 = CheckDetails ();
|
|
if (b2) {
|
|
// typo: a find-replace changed b1 into b2
|
|
b2 = CheckMoreDetails ();
|
|
}
|
|
return b2 && b2;
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
bool DualCheck ()
|
|
{
|
|
bool b1 = true;
|
|
bool b2 = CheckDetails ();
|
|
if (b2) {
|
|
b1 = CheckMoreDetails ();
|
|
}
|
|
return b1 && b2;
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.ReviewLinqMethodRule">
|
|
<summary>
|
|
Linq extension methods operate on sequences of values so they generally
|
|
have linear time complexity. However you may be able to achieve better
|
|
than linear time performance if you use a less general method or take
|
|
advantage of a method provided by an <c>Sytem.Collections.Generic.IEnumerable<T></c>
|
|
subclass.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
public string FirstOrMissing (IEnumerable<string> sequence, string missing)
|
|
{
|
|
// Count () is O(n)
|
|
if (sequence.Count () > 0) {
|
|
return sequence.First ();
|
|
}
|
|
return missing;
|
|
}
|
|
public void Append (List<string> lines, string line)
|
|
{
|
|
// Last () is O(n)
|
|
if (lines.Count == 0 || lines.Last () != line) {
|
|
lines.Add (line);
|
|
}
|
|
}
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
public string FirstOrMissing (IEnumerable<string> sequence, string missing)
|
|
{
|
|
// We don't need an exact count so we can use the O(1) Any () method.
|
|
if (sequence.Any ()) {
|
|
return sequence.First ();
|
|
}
|
|
return missing;
|
|
}
|
|
public void Append (List<string> lines, string line)
|
|
{
|
|
// Lines is a List so we can use the O(1) subscript operator instead of
|
|
// the Last () method.
|
|
if (lines.Count == 0 || lines [lines.Count - 1] != line) {
|
|
lines.Add (line);
|
|
}
|
|
}
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.6</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.UseIsOperatorRule">
|
|
<summary>
|
|
This rule looks for complex cast operations (e.g. a <c>as</c>
|
|
with a <c>null</c> check) that can be simplified using the <c>is</c> operator
|
|
(C# syntax). Note: in some case a compiler, like [g]mcs, can optimize the code and
|
|
generate IL identical to a <c>is</c> operator. In this case the rule will not report
|
|
an error even if you could see one while looking the at source code.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
bool is_my_type = (my_instance as MyType) != null;
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
bool is_my_type = (my_instance is MyType);
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.UseStringEmptyRule">
|
|
<summary>
|
|
This rule checks for methods that are using the literal <c>""</c> instead of the
|
|
<c>String.Empty</c> field. You'll get slighly better performance by using
|
|
<c>String.Empty</c>. Note that in some cases, e.g. in a <c>switch/case</c> statement,
|
|
you cannot use a field, so <c>""</c> must be used instead of <c>String.Empty</c>.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
string s = "";
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
string s = String.Empty;
|
|
</code></example>
|
|
</member>
|
|
<member name="T:Gendarme.Rules.Performance.UseTypeEmptyTypesRule">
|
|
<summary>
|
|
This rule fires if a zero length array of <c>System.Type</c> is created.
|
|
This value is so often required by the framework API that the <c>System.Type</c> includes
|
|
an <c>EmptyTypes</c> field. Using this field avoids the memory allocation (and GC tracking)
|
|
of your own array.
|
|
</summary>
|
|
<example>
|
|
Bad example:
|
|
<code>
|
|
ConstructorInfo ci = type.GetConstructor (new Type[0]);
|
|
</code></example>
|
|
<example>
|
|
Good example:
|
|
<code>
|
|
ConstructorInfo ci = type.GetConstructor (Type.EmptyTypes);
|
|
</code></example>
|
|
<remarks>This rule is available since Gendarme 2.0</remarks>
|
|
</member>
|
|
</members>
|
|
</doc>
|