Otherwise an excellent document, the IDesign C# Coding Standards does have a few issues that I will warn people of:
-
1.10.
I have to go with Jeffrey Richter (author of CLR via C#) on this one. He makes the point that the framework methods refer to the actual CLR types and not what one particular language alias them as. i.e. Convert.ToInt32(value) method. It does make more sense to standardize on one set of types. We have the CTS, use it.
I'll add that if you work in companies that use more than just c# (my team here at Microsoft uses 3 different languages alone in our project) then it reduces the mental load to standardize the type system. I'll also point out that unless a language happens to support all the Value Types in the System namespace as native types then their point is moot (sorry but System.Guid should NOT be a second class citizen).
-
1.20
Go one step further. #region directives are YOUR FRIEND.
-
2.1
Put nested types in a partial class and move them to a FileName.Designer.cs
-
2.4
Poppycock. Reduce that number by a factor of 10. Anyone with a method 400 lines long should be forced to put their big head on the desk and have quiet time. STOP THINKING PROCEDUREAL PROGRAMMING! Just because your language has the class keyword does not mean you are doing OO.
-
2.17
Here they write the correct statement and violate the damn rule with their own example! Do this instead:
catch (SomeExceptionType ex)
{
//Do your whatever here
throw;
}
Better yet, Don't catch the exception unless you can do something about it!
p.s. NEVER catch Exception without a higher catch ... throw that does NO WORK for OutOfMemoryException, ExecutionEngineException, and StackOverflowException. It's a great way to bust up your application and open DOS or security holes. Granted it's 1 in a million chance but that just means an attacker has to run their script a million times. Think about it.
-
2.19
rubbish. That's why we have an unsealed System.Exception class. Just keep it "shallow but wide" in your exception taxonomy.
-
2.22
Go one step further. seal tham also.
-
If the enum is a numeric value in a database in your persistence methodology then you sure as hell better explicitly set them. I've seen more than my fair share of smeg-ups when someone adds a new item to the enum and doesn't think about where they inserted it.
-
2.27
Ignore when performing Interop or working with services
-
2.29
Use them when they improve readability. Sorry but this is much more maintainable:
return someCollection.Count > 0 ? someCollection[0] : null;
than:
SomeType returnVal = null;
if (someCollection.Count > 0)
{
returnVal = someCollection[0];
}
return returnVal;
it's a constant source of bugs at MS code reviews.
-
2.57
Doesn't count for static methods. Methods that are marked static should also be designed when possible to be "side effect free".
-
2.58
WRONG WRONG WRONG!
NEVER use a static constructor unless there is explicit configuration of said reference types.
When a type declares an explicit static constructor, the just-in-time (JIT) compiler adds a check to each of the type's static methods and instance constructors to ensure that the static constructor was previously called. Static initialization is triggered when any static member is accessed or when an instance of the type is created. However, static initialization is not triggered if you declare a variable of the type but do not use it, which can be important if the initialization changes global state.
When all static data is initialized inline and an explicit static constructor is not declared, Microsoft intermediate language (MSIL) compilers add the beforefieldinit flag and an implicit static constructor, which initializes the static data, to the MSIL type definition. When the JIT compiler encounters the beforefieldinit flag, in most cases the static constructor checks are not added. Static initialization is guaranteed to occur at some time before any of the static fields are accessed but not before a static method or instance constructor is invoked. Note that static initialization can occur at any time after a variable of the type is declared.
-
2.68
Do the inverse. It's better to not corrupt data and suffer the check penality at runtime because something sliped through your code review than to introduce a bug or even worse a security hole. Use the unchecked instead.
-
3.14
Ignore if the projects in your solution ship on independant time frames (sorry but reality comes into play here, most groups should use two seperate solutions in this use case but it just doesn't happen).
-
4.1.7
Use an ORM or injectable Repository instead of data adapters directly.
-
4.5.9
Try reading something from Ingo Rammer, aka the God of all things Remoting
Ingo's recomendation: Singlecall SAOs hosted in IIS with HttpChannel and BinaryFormatter
Don't try and reinvent everything that IIS does. If you think you could do better then you should be writing IIS 8 here in Redmond.
-
4.6.8
Go further. Require what you need, accept nothing optional.
[assembly: SecurityPermission(
SecurityAction.RequestMinimum, Execution = true)]
[assembly: PermissionSet(
SecurityAction.RequestOptional, Name = "Nothing")]
|