šŸ’…šŸ¼ Code Style

back

Code style makes things easier to read. It is about using clear names as well as white space.
Specific language construct preferences are also part of the deal.

Contents

Introduction

This article lists code style preferences, that might be followed in some of the JJ projects.

They mostly conform to Microsoft standards described in these articles:

A tool like ReSharper may help. Its settings can be fine-tuned to closely match the preferences. It then checks the code style and can auto-format for you.

Casing

Suggestion Examples
Pascal case for properties, methods, class names and events MyProperty MyMethod
Camel case for local variables and parameters myLocalVariable myParameter
Fields in camel case starting with underscore _myField
Constants in capitals with underscores between words MY_CONSTANT
Type arguments just the letter T or start with the letter T T TEntity TViewModel
Interfaces start with I. IMyInterface
Abbreviations not preferred Ā 
Abbreviations of 2 letters with capitals. ID
Abbreviations of 3 letters or more in pascal case. Mvc
MVC partial View names in pascal case, starting with underscore _MyPartialView
For long identifiers, underscores to separate ā€˜the piecesā€™ Sine_OperatorCalculator_VarFrequency

Naming

Reasons for naming conventions might be, just knowing what kind of system elements they are.

Method Names

Method names commonly start with verbs, e.g. CreateOrder.
For clarity generally donā€™t use verbs, for things other than methods.
Suggestions for verbs:

Verb Description
Add List.Add(item)
ListManager.Add(list, item)
(List can be the this argument or the first argument.)
Assert Throws an Exception if input is invalid.
Calculate Ā 
Clear Clears a list.
Convert Ā 
ConvertTo Ā 
Create Returns a new object.
Delete Ā 
Ensure Setting up a state, if not set up yet.
If Ensure means to throw an Exception,
consider using the Assert verb instead.
Execute Ā 
Generate Ā 
Get Ā 
Invoke Ā 
Parse Ā 
Process Ā 
Remove Ā 
Save Ā 
Set Ā 
Try Ā 
TryGet Returns null if an object does not exist.
Validate Generating validation messages for user-input errors.

Class Names

In this architecture, class names may end with a pattern name or a verb converted to a noun, e.g.:

Converter
Validator
Calculator

And they may start with a term out of the functional domain (like Order, Product or Price):

OrderConverter
ProductValidator
PriceCalculator

More specialized classes might get a prefix or suffix (like Optimized or WithPriorityShipping):

OptimizedPriceCalculator
OrderValidatorWithPriorityShipping

Abstract classes might prefer a Base suffix:

ProductValidatorBase

It might be quite important to see in code, whether something is a base class. But exceptions may be made. For instance, entity classes might leave out the Base suffix for readability reasons.

You might keep variables names similar to the class names and include the prefixes and suffixes, so it stays clear what they are.

Apart form pattern names, here are some other suggested ā€˜last namesā€™ for classes:

Ā  Ā 
Resolver A class that does lookups requiring complex keys or different ways of looking up depending on the situation, fuzzy lookups, etc.
Dispatcher A class calls different methods or sends messages to different endpoints based on the input it receives.
Invoker Something that invokes a method, possibly based on input or specific conditions.
Provider A class that provides something. It can be useful to have a separate class that provides something if there are many conditions or contextual dependencies involved in retrieving something. A Provider might also be used when something is retrieved conditionally or if retrieval is postponed until later.
Asserter A class meant to throw Exceptions under certain conditions.
Ā  Any verb might become a class name, by turning it into a verby noun, e.g. Convert => Converter.

Boolean Names

When naming boolean variables, consider using prefixes and suffixes:

Prefix / Suffix Example Comment
Is... IsDeleted Might be the most common prefix.
Must... MustDelete Ā 
Can... CanDelete Might indicate what user can do.
Has... HasRecords Ā 
Are... AreEqual For plural things.
Not... NotNull A nice prefix, but perhaps be careful with negative names. See Double Negatives.
Include... IncludeHidden Verb are usually for methods, but these may make sense for booleans.
Exclude... ExcludeSpecialChars ā€
...Exists FileExists Ā 
Always... Ā  Ā 
Never... Ā  Ā 
Only... Ā  Ā 

A prefix might not always be put at the beginning. If it looks better, you might put it somewhere else:

LinesAreCopied

instead of:

AreLinesCopied

Some boolean names are so common, that they might not need a prefix:

Visible
Enabled

Collection Names

Plural words are preferred for collections:

Products
Orders

Variable names for amounts of elements might be named:

Count

So perhaps avoid plural words to denote a count or describe things other than collections.

Enum Names

This architecture tends to end enum types with the Enum suffix e.g. OrderStatusEnum.

Another alternative might be the suffix Mode, e.g. ConnectionMode. But Enum expresses it more explicitly and that might be quite important.

DateTime Names

A DateTime property might be suffixed with Utc or Local:

StartDateLocal
OrderDateTimeUtc

An alternative suffix for DateTimes could be When:

ModifiedWhen
OrderedWhen

But that might not look so nice, when you add the Local and Utc suffixes again:

ModifiedWhenUtc
OrderedWhenLocal

Sort Order

For number sequences the following names might be used:

ListIndex
IndexNumber
SortOrder
Rank

Perhaps donā€™t use the word Index on its own, because thatā€™s an SQL keyword.

Variable names that describe parts of file paths might easily become ambiguous. Here are some suggestions to make them clearer:

Name Value
FileName "MyFile.txt"
FilePath "C:\MyFolder\MyFile.txt"
FolderPath "C:\MyFolder"
SubFolder "MyFolder"
RelativeFolderPath /
SubFolder /
SubFolderPath
"MyFolder\MyFolder2"
RelativeFilePath "MyFolder\MyFile.txt"
FileNameWithoutExtension "MyFile"
FileExtension ".txt"
AbsoluteFilePath "C:\MyFolder\MyFile.txt"
AbsoluteFolderPath "C:\MyFolder"
AbsoluteFileName DOES NOT EXIST
FileNamePattern /
FilePathPattern / etc.
wildcards like * and ?
*.xml
C:\temp\BLA_???.csv
FileNameFormat /
FilePathFormat / etc.
placeholders like {0} and {0:dd-MM-yyyy}
order-{0}.txt
orders-{0:dd-MM-yyyy}\*.*

Prefixes and Suffixes

Example Description
source...
dest...
In code that converts one structure to the other, it might be clear to use the prefixes source and dest. You might use them consistently in the variable names, to keep track of where data comes from and where it goes.
existing... Denoting that something already existed (in the database).
new... Denoting that the object was just newly created.
original... May denote that this is an original value that was (temporarily) replaced.
...WithRelatedEntities
...WithRelatedObjects
Indicating that it does more than handling a single object. Related objects linked to it are also included.
Versatile... Versatile in that it might handle a multitude of types or situations.
...With... When making a specialized class that works well for a specific situation, you might use the word With in the class name e.g.:
CostCalculator
CostWithTaxCalculator
...Polymorphic Handling a variety of (derived) types, which may need different ways of processing.
...IfNeeded A suffix alternative for Conditional that might be easier to read.
...Unsafe When it lacks e.g. thread-safety, executes unmanaged code, or lacks some other checks.
...Recursive When the process is recursive. Meaning: A method might call itself directly or indirectly. Or when processing a tree, the same type of data might be there deeper down the tree.
To... For conversion from one thing to another. Sometimes the this is the source of the conversion, for example:
array.ToHashSet()
Sometimes a parameter is the source, for instance:
MyConverter.ToHashSet(object[] array)
But Convert or ConvertTo might be used as an alternative in that case:
MyConverter.ConvertToHashSet(object[] array)
From... For conversion from one thing to another. A lot like To... but executed on the dest object:
dest.FromSource(source)
The To... prefix might be more common, and possibly more readable.

Event Names / Delegate Names

Event names and delegate names representing what just happened might be written in the past tense. For example:

Deleted
TransactionCompleted

Event names and delegate names representing what is about to happen might be written in the following form:

Deleting
TransactionCompleting

User-initiated events might not follow that pattern:

Click
DoubleClick
KeyPress
MouseUp

Delegate names might also have the suffix Callback or Delegate:

ProgressInfoCallback
AddItemDelegate

Sometimes the word On may be used:

OnSelectedIndexChanged
OnClick

Or the prefix Handle:

HandleMouseDown

Or the suffix Requested, if your event looks like a method name.

RemoveRequested

The names mentioned above can be used for events, but also for methods that raise or handle the event. Some prefixes for these methods include: On, Handle, Fire, and Do.

Perhaps avoid using event names with two event-indicating words, like OnDragging or OnMouseUp. Instead, you can use shorter names like Dragging or MouseUp.

Test Class Names

Test class names end with the word Tests.

RecommendedLess Preferred
[TestClass]
public class ValidatorTests()
{
    
}
[TestClass]
public class Tests_Validator()
{
    
}

Reason: Just convention.

Test Method Names

Prefer to start test method names with Test_ and use underscores freely.

RecommendedLess Preferred
[TestMethod]
public void Test_Validator_NotNullOrEmpty_Valid()
{ }

[TestMethod]
public void Test_Validator_NotNullOrEmpty_NotValid()
{ }
[TestMethod]
public void Test1()
{ }

[TestMethod]
public void Test2()
{ }

Reason:
When test names mean to be descriptive, they might become long. Underscores can separate the ā€˜piecesā€™ and make it more readable.

ā€˜Hungarianā€™ Notation

Avoid prefixes such as strName.

Enters

Properties on Separate Lines

RecommendedLess Preferred
int A { get; set; } 
int B { get; set; }

int C
{
    get { ... }
    set { ... }
}

int D
{
    get 
    {
        ... 
    }
    set 
    { 
        ...
    }
}
int A { get; set; } int B { get; set; } 

Reason:
Otherwise it might be easily overlooked, that there is another property.

Variables on Separate Lines

RecommendedLess Preferred
int i;
int j;
int i, j; 

Reason:
Just a preference. Itā€™s up to you. But when youā€™re not familiar with it, variables might be missed while searching the code. This syntax would have to be taken into account.

Enters between Methods

RecommendedLess Preferred
void Bla()
{
   
}

void Bla2()
{
   
}
void Bla()
{
    
}
void Bla2()
{
    
}

Reason: Just a bit more tidy.

Enters in Methods

Putting enters inside methods between the ā€˜pieces that do somethingā€™.

RecommendedLess Preferred
void Bla()
{
    var x = new X();
    x.A = 10;
    
    var y = new Y();
    y.B = 20;
    y.X = x;
    
    Bla2(x, y);
}
   
void Bla()
{
    var x = new X();
    x.A = 10;
    var y = new Y();
    y.B = 20;
    y.X = x;
    Bla2(x, y);
} 

Reason:
Visible separation between steps inside methods.

Loops Multi-Line

RecommendedLess Preferred
foreach (var x in list)
{ 
    Bla();
}
foreach (var x in list) { Bla(); } 

Reason: May look odd if youā€™re not used to it.

Enters between Switch Cases

RecommendedLess Preferred
switch (x)
{
    case 1:
        break;

    case 2:
        break;
}
switch (x)
{
    case 1:
        break;
    case 2:
        break;
}

Reason: A bit tidier and the bits better separated.

Surplus Enters Between Braces

RecommendedLess Preferred
    }
}
    }
    
}

Reason: More tidy.

Generic Constraints on Separate Line

RecommendedLess Preferred
class MyGenericClass<T>
    where T: MyInterface
{
    ...
}
class MyGenericClass<T> where T: MyInterface
{
    ...
}

Reason: So they stand out.

Generic Constraints on Same Line for One-Liners

RecommendedLess Preferred
interface IMyInterface
{
    void MyMethod(T param) where T : ISomething
}
interface IMyInterface
{
    void MyMethod(T param) 
        where T : ISomething
} 

Reason:
It might have been on a single line for readability, so perhaps we want to keep it like that.

Spaces and Braces

Auto-Formatting

Perhaps start out with Visual Studio's auto-formatting enabled and set to its defaults.

Reason: Less surprising to the next developer.

Indentation

Apply indentation properly.

RecommendedLess Preferred
object ParseValue(string input, Type type)
{
    if (type.IsNullableType())
    {
        if (string.IsNullOrEmpty(input))
        {
            return null;
        }

        type = type.GetUnderlyingNullableTypeFast();
    }

    if (type.IsEnum)
    {
        return Enum.Parse(type, input);
    }

    if (type == typeof(TimeSpan))
    {
        return TimeSpan.Parse(input);
    }

    if (type == typeof(Guid))
    {
        return new Guid(input);
    }

    return Convert.ChangeType(input, type);
}
        object ParseValue(string input,
Type type 
            )
{
        if (type.IsNullableType()) 
        {
    if (string.IsNullOrEmpty(input)) {
    return null;
}

type = type.GetUnderlyingNullableTypeFast();
    }

        if (type.IsEnum) 
    {
return Enum.Parse(type, input);
    }

            if (type == 
    typeof(TimeSpan))
{
                return TimeSpan.Parse(input);
}

            if (type == typeof(Guid))
            { 
    return new Guid(input);
            }


        return 
        Convert.ChangeType(
   input, 

        type);
                }

Reason: More readable.

No Braces for Single-Line If Statements

RecommendedLess Preferred
if (condition) Bla();
if (condition) { Bla(); }

Reason: Less clutter.

Braces for Multi-Line Statements

RecommendedLess Preferred
foreach (var x in list)
{
    Bla();
}

if (condition)
{
    Bla();
    Something();
}
foreach (var x in list)
    Bla();

if (condition)
    Bla(); 
    Something();

Reason:
Without braces, only the next line is looped or executed conditionally. The line after that would not be part of the loop or if, which might not be very obvious and might lead to error.

Tabular Form Less Preferred

RecommendedLess Preferred
public int ID { get; set; }
public bool IsActive { get; set; }
public string Text { get; set; }
public string Answer { get; set; }
public bool IsManual { get; set; }
public int    ID       { get; set; }
public bool   IsActive { get; set; }
public string Text     { get; set; }
public string Answer   { get; set; }
public bool   IsManual { get; set; } 

Reason:
Tabular form might be undone by auto-formatting. It may look nice, but maybe get your eyes used to non-tabular form instead.

Align LINQ Queries

Aligning the elements:

RecommendedLess Preferred
var arr = coll.Where(x => x...)
              .OrderBy(x => x...)
              .ToArray()
var arr = coll.Where(x => x...).
   OrderBy(x => x...).ToArray() 

Reason: readability.

Encapsulation

Members Private

Keeping members private is preferred.

private void Bla()
{
    ...
}

Reason:
Other code might become dependent on publicly accessible things. Managing dependencies like that is quite a thing in software development.

Types Internal

Keep types internal is preferred.

internal class MyClass
{
    ...   
}

Reason:
Managing dependency between parts is quite a concern in software development. We might protect things from forming too many connections, by using access modifying keywords, like private and internal.

Explicit Access Modifiers

RecommendedLess Preferred

public int Bla() { ... }

int Bla() { ... }

Reason:
Avoiding confusion about the defaults.

Exception:
Interface members have no access modifiers.

No Public Fields

Prefer not to use public fields. Use either private fields or use properties.

RecommendedLess Preferred

public int X { get; set; }

public int X;

Reason:
Some may say using public fields makes the interface less stable. Fields may look similar to properties from the outside. However, frameworks may expect properties, not fields. This makes it harder to use fields in reusable functions and may cause compatibility issues.

Public Members for Internal Classes

The use of internal members is not recommended within internal classes.

RecommendedLess Preferred

internal class A { public void B { } }

internal class A { internal void B { } }

Reason:
If the class is internal, the members are automatically internal too. When making the class public, more access modifiers may need to change, creating an opportunity for error.

Prefer Interface Types

RecommendedLess Preferred

IList<int> list = new List<int>;

List<int> list = new List<int>;

Reason:
Interface types may give you less to refactor when changing a type. Less dependency on specific implementation, allowing for an easier switch to another class.

Nested Class on Top

Putting nested classes at the top of the parent class' code.

RecommendedLess Preferred
internal class A
{
    private class B
    {
        
    }
    
    ...

    public int X { get; set; }
}
internal class A
{
    public int X { get; set; }
    
    ...
    
    private class B
    {
        
    }
}

Reason:
It may not be obvious there are nested classes, unless they are put at the top.

1 Type 1 File

Give each class (or interface or enum) its own file.

Reason:
One might be surprised to find types hidden away behind a single file name. It may harm the overview of the different pieces of the code.

Exceptions:
This guideline does not apply to nested classes. Also, a single class can be split across multiple files if they are partial classes. This guideline may also be ignored if there are a large number of smaller classes.

No Lone Classes

It may not be very handy to have many folders that only contain one or few classes. Consider moving those classes to other folders or putting them together in a single Helpers folder.

Comments

Comments in Summaries

You might put comment for members in <summary> tags.

RecommendedLess Preferred
/// <summary> This is the x coordinate. </summary>
int X { get; set; }
// This is the x-coordinate.
int X { get; set; } 

Reason:
Your comment might be valuable from the outside for others to see. Your summary would show up when hovering over a member.

Comments in English

RecommendedLess Preferred
// This is a thing.
// Dit is een ding. 

Reason:
English is basically the main language in IT. A broader reach of people might be able to read your comments.

No Comments without Info

Avoid comments that do not add information.

RecommendedLess Preferred
int x;
// This is x
int x;

Reason:
Less visual clutter. Reading it might not be worth the time.

No Unused / Outcommented Code

Avoid leaving around unused or outcommented code. If necessary, you can move it to an Archive folder.

Reason:
Unused code might clutter your vision. It may also give the impression, that it was outcommented in error.

More Notation

Object Initializers

RecommendedLess Preferred
var x = new X
{
    A = 10,
    B = 20
}
var x = new X();
x.A = 10;
x.B = 20; 

Reason: More readable.

Default Switch Case at the Bottom

RecommendedLess Preferred
switch (x)
{
    case 0:
        break;
    
    case 1:
        break;
    
    default:
        break;
}
switch (x)
{
    default:
        break;

    case 0:
        break;

    case 1:
        break;
} 

Reason:
The default switch case is often the ā€˜last resortā€™ case, so it may make sense to put it last.

Long Code Lines

Avoid long code lines for readability.

Var

The use of var is not preferred here.

RecommendedLess Preferred

int x = y.X;

var x = y.X;

Reason:
A variable type might be relevant to see.

Exceptions:
But in some cases, var may be preferred after all. For example, when the type is obvious, or it makes the code more readable.

Anonymous Types

RecommendedNot Preferred

var q = from x in list select new { A = x.A };

X q = from x in list select new { A = x.A };

New Statements

RecommendedLess Preferred

var x = new X();

X x = new X();

Direct Casts

RecommendedLess Preferred

var x = (X)y;

X x = (X)y;

Long Code Lines

RecommendedLess Preferred
foreach (var entry in dictionary)
foreach (KeyValuePair<Canonical.ValidationMessage,  
         Tuple<NonPhysicalOrderProductList, Guid>> entry in dictionary)

Views

RecommendedLess Preferred

<% foreach (var order in Model.Orders) %>

<% foreach (OrderViewModel order in Model.Orders) %>

No Inferrable Type Arguments

Prefer not to use type arguments that can be inferred.

RecommendedLess Preferred

References(x => x.Child)

Reference<Child>(x => x.Child)

Reason: Less visual clutter.

FileOpen, FileMode, FileAccess, FileShare

When a FileStream is opened it is appreciated to specify the aspects FileMode, FileAccess and FileShare explicitly. Try to use the most logical and most limiting values tailored to the situation.

Reason:
Otherwise these aspects may have surprising defaults.

Ordered If Range

When expressing a range in an if statement, showing the actual limits of the range may look better. Also, mentioning the start of the range first and the end of the range second might make it more readable.

RecommendedLess Preferred
if (x >= 10 && x <= 100)
if (x > 10 && x < 100)
if (x <= 100 && x >= 10)
if (x >= 11 && x <= 99) 

Reason: Readability. More obvious what the range limits are.

Parameter Order

Passing infrastructure-related parameters to constructors or methods, the parameters might be listed in a certain order:

For instance:

class MyPresenter
{
    public MyPresenter(
        MyEntity entity, 
        IMyRepository repository,
        IAuthenticator authenticator,
        string cultureName,
        int pageSize)
    {
        ...
    }
}

Reason:
Just to have some kind of standard for consistency.

Namespace Tips

Full Namespaces

Full namespaces in code might not be preferred:

Less Preferred
JJ.Business.Cms.RepositoryInterfaces.IUserRepository userRepository =
    PersistenceHelper.CreatCmsRepository<JJ.Business.Cms.RepositoryInterfaces.IUserRepository>(cmsContext);

Reason:
Long and wordy code can make it harder to read.

Half Namespaces

Half a namespace might not be preferred either:

Less Preferred
Cms.RepositoryInterfaces.IUserRepository userRepository = 
    PersistenceHelper.CreateCmsRepository<Cms.RepositoryInterfaces.IUserRepository>(cmsContext);

Reason:
If youā€™d want to rename the namespace, it might create more manual work. The shortened namespace could be overlooked when searching through the code.

Unique Class Names

To prevent using a namespace in the code line, you might give a class a more unique name:

ICmsUserRepository cmsUserRepository = 
    PersistenceHelper.CreateCmsRepository<ICmsUserRepository>(cmsContext);

Type Aliases

To disambiguate a type name, you might use a type alias instead. This can prevent long namespaces in the code lines:

Recommended
using IUserRepository_Cms = JJ.Business.Cms.RepositoryInterfaces.IUserRepository;

IUserRepository_Cms cmsUserRepository = 
    PersistenceHelper.CreateCmsRepository<IUserRepository_Cms>(cmsContext);

Reason:
Long, visually cluttered code lines might be harder to read.

Member Order

To improve readability, try giving the members in your code a logical order, instead of putting them all in an arbitrary order. Suggestions for organizing the members in your code:

Ā  Ā 
Chronological When one method delegates to another in a particular order, you might order the methods chronologically.
By functional aspect When your code has distinct functionalities, you might keep members with similar functions together and add a comment line above the group.
By technical aspect You may choose to keep your fields together, your properties together, your methods together. Another option might be to group them by access modifier (e.g. public or private).
By layer When you can identify layers in your class, you might first list the members of layer 1, then the members of layer 2, etc.

You might prefer to make it chronological if possible. Otherwise, order it by functional aspect. But there are no rights and wrongs here. Whatever seems most appropriate for your code.

Misc Preferences

Null / Empty Strings

Prefer handling both null and "" the same way.

Reason: No surprises when using either null or "".

String.IsNullOrEmpty

Prefer string.IsNullOrEmpty to check if a string is filled in.

RecommendedLess Preferred
String.IsNullOrEmpty(str)
str == null 

Reason:
Reference equality (==) may fail in exceptional cases even when strings are equal.

String.Equals

Prefer string.Equals to check the equality of string.

RecommendedLess Preferred
string.Equals(str, "bla")
str == "bla"

Reason:
Reference equality (==) may fail in exceptional cases even if string values are equal.

Prefer Value and HasValue

For Nullable types:

RecommendedLess Preferred
int? number;
if (number.HasValue)
{
    string message = $"Number = {number.Value}";
}
int? number;
if (number != null)
{
    string message = $"Number = {number}";
}

Reason:
The less preferred one may look nice, but the behavior of the code would change considerably, if the variable type is changed to object.

Prefer ToArray

Prefer ToArray over ToList.

RecommendedLess Preferred

IList<int> collection = x.ToArray();

IList<int> collection = x.ToList();

Reason: More performance.
Downside: The Add method may throw an Exception for an Array.

CLR Data Types

Prefer using CLR- compliant data types. Some arenā€™t CLR- compliant.

RecommendedLess Preferred
int
long
byte
// Unsigned types:
uint
ulong
// And also:
sbyte

Reason:
For compatibility with more variations of .NET.

No Decisions from Exceptions

Avoid getting information by catching an Exception. Prefer getting your information without using Exception handling.

RecommendedLess Preferred
bool FileExists(string path)
{
    return File.Exists(path);
}
bool FileExists(string path)
{
    try
    {
        File.Open(path, ...);
        return true;
    }
    catch (IOException)
    {
        return false;
    }
}

Reason:
Exception handling is more performance intensive than might be expected. When no Exception goes off, Exception handling might perform well, but when an Exception does go off, quite a few things happen, like gathering StackTrace information.

Entity Equality by ID

Entity equality checks might be better done by ID than by reference.

RecommendedLess Preferred
if (entity1.ID == entity2.ID)
if (entity1 == entity2) 

Reason:
Code that compares identities may be less likely to break, because persistence frameworks donā€™t always ensure instance integrity.

(Also consider doing null checks on the entities if needed.)

Compiler Directives

Prefer not to use compiler directives, unless the code cannot run on a platform without excluding that piece of code. Otherwise a boolean variable might be preferred, a configuration setting or different concrete implementations of classes.

RecommendedLess Preferred
if (config.FeatureXEnabled)
{
    // ...
}
#if FEATURE_X_ENABLED
    // ...
#endif

Reason:
When using these compiling directives, a compilation might succeed, without all the code being actually compilable.

Activator.CreateInstance

Prefer using the new keyword instead of Activator.CreateInstance. Using genericsā€™ new constraint might avoid some of the Activator.CreateInstance calls.

RecommendedLess Preferred
new T()
Activator.CreateInstance(typeof(T)) 

A call to Activator.CreateInstance might be the last choice for instantiating an object.

Reason:
New statements are strongly typed, less likely to break and possibly faster.

back