Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  1. Use Pascal casing for type, method names and constants:

    Code Block
    languagec#
    public class SomeClass
    {
        private const int DefaultSize = 100;
        
        public void SomeMethod()
        {
             …
        }
    }
  2. Use camel casing for local variable names and method arguments:

    Code Block
    languagec#
    public void SomeMethod(int someNumber)
    {
        int number;
        …
    }
  3. Apply camel casing and Pascal casing as follows:
    1. Make sure the changes in casing match individual words and are not actually splitting compound words.

      Code Block
      languagec#
      // Good
      bool grasshopper = false;
      string grandmother = "Nellie";
      
      // Bad	
      bool grassHopper = false;
      string grandMother = "Nellie";
    2. If a parameter or variable name matches a C# language keyword, either rename the variable or use the @ symbol to prevent compilation errors.  (Do not modify the casing to resolve the compilation error and thereby effectively split a compound word in two.)

      Code Block
      languagec#
      // Bad
      private string StripNamespacePrefixFromValue(string value, string nameSpace)
      {
          if (value.BeginsWith(nameSpace))
          {
              return value.Substring(nameSpace.Length);
          }
          return value;
      }
      
      // Better
      private string StripNamespacePrefixFromValue(string value, string @namespace)
      {
          if (value.BeginsWith(@namespace))
          {
              return value.Substring(@namespace.Length);
          }
      
          return value;
      }
      
      // Best
      private string StripNamespacePrefixFromValue(string value, string namespacePrefix)
      {
          if (value.BeginsWith(namespacePrefix))
          {
              return value.Substring(namespacePrefix.Length);
          }
      
          return value;
      }
  4. Prefix interfaces with I.

    Code Block
    languagec#
    public interface ISomethingProvider
    {
        …
    }
  5. Suffix interface implementations with the non-prefixed interface name.

    Code Block
    languagec#
    public class ThisSomethingProvider : ISomethingProvider
    {
        …
    }
  6. Prefix all fields with an underscore (_). If a file happens to differ in style from these guidelines, the existing style in that file takes precedence.

    Code Block
    languagec#
    public class SomeClass
    {
        private ISomethingProvider _thisSomethingProvider;
    }
  7. Name methods using a verb or verb-object pair (unless implementing a fluent API).

    Code Block
    languagec#
    public decimal CalculateTax(decimal amount)
    {
        …
    }
  8. What's in a name?   Everything.   Use clear and descriptive names for classes, methods, fields and variables to reduce maintenance costs.  Make sure that after refactoring code that the names are still appropriate. 
    For example:

    Code Block
    languagec#
    titleA Method Name That Does Not Reflect Its Behavior
    private static bool IsNotDuplicate(Dictionary<Tuple<string, string>, int> idsByValue, Tuple<string, string> key, StringBuilder duplicatesMessageBuilder)
    {
        if (idsByValue.ContainsKey(key))
        {
            duplicatesMessageBuilder.AppendFormat("\tDescriptor Type: {0}, Code Value: {1}\r\n", key.Item1, key.Item2);
            return false;
        }
        
        return true;
    }

     

    1. The method name includes the text "Not" and returns a boolean value.  This could create scenarios where callers are performing double negatives, which are hard to read (e.g. if (!IsNotDuplicate(…) { ) 
    2. The behavior of the method actually appends to the provided StringBuilder, but this is not reflected in the method name at all and is only discoverable by a developer inspecting the code.
    3. Since the main behavioral aspect of this method is to modify the StringBuilder, it would make more sense to pass it first in the list of arguments.
    4. Without refactoring the code (which is probably the better option here), a more descriptive method name and signature might look like this (note the flip in boolean semantics):

      Code Block
      languagec#
      titleA New Name that Captures Actual Behavior
      private static bool TryAppendDuplicateValueMessage(StringBuilder duplicatesMessageBuilder, Tuple<string, string> key, Dictionary<Tuple<string, string>, int> idsByValue)
      {
          …
      }
  9. You can use single-character or mnemonic variable names in the following scenarios:

    1. In for loops where it is a common convention to use variables like i, j, and k.

    2. In LINQ expressions where it is a common convention to use variables like x or a mnemonic for the item being represented (e.g. ssa for an object of type StudentSchoolAssociation).

  10. Always use ex for exception handling variables.

    Code Block
    languagec#
    try
    {
        int x = 0;
        int y = 5 / x;
    }
    catch (DivideByZeroException ex)
    {
    	_logger.Warn("Somebody was dividing by zero.");
    }
    catch (Exception ex)
    {
    	_logger.Error(ex);
        throw;
    }
  11. Name dictionaries using a name format of {ValueName}By{KeyName}.

    1. Precisely describe the keys and values (e.g. SchoolNameById would indicate that you can obtain a school's name by its identifier).

    2. If each entry’s value is a single item, the name should be singularized (e.g. StudentById).

    3. If each entry’s value is a collection, the name should be pluralized (e.g. StudentsBySectionId).
  12. Do not abbreviate terms as this leads to usage inconsistency in the code and other application artifacts.  Specifically, do not abbreviate "EducationOrganization" as “EdOrg” or “LocalEducationAgency” as “Lea”.

  13. Name abstract classes using a suffix of Base (e.g. EdFiControllerBase).

  14. Use the following guidelines when defining generic types:
    1. For types with a single generic type, prefer the use of "T".

      Code Block
      languagec#
      public interface IList<T>
    2. For types with multiple generic types, use a capital "T" followed by an optional secondary name for additional clarity.  In all cases, start the type with a capital letter.

      Code Block
      languagec#
      public interface IService<TRequest, TResponse>
  15. Name custom attribute and exception classes using suffixes of Attribute and Exception, respectively.

  16. Name enumerations in the singular (e.g. FileMode) unless the enumeration is representing a bit flag value (e.g. FileAttributes) in which case the [Flags] attribute should also be applied.

...