Best Practices for Designing Interface Types                                        
•        When designing interfaces, always prefix a capital letter I to the interface name.
•        IDbConnection, IDisposable, ICustomSnapIn, etc.
•        As a general rule, define a single source code file in your project which contains all interface definitions.
•        By doing so, you can easily move these interfaces into new projects without bringing the baggage of
implementation details.
•        As a general rule, avoid adding events to interface definitions.
•        Typically, common events are better served by defining them in an abstract base class.
// C#
interface ITestInterface
{
// OK, but not recommended.
event EventHandler SomeEvent;

// Properties and methods OK!
string SomeProperty { get; set;}
void SomeMethod(int a, int b);
}

' VB 2005
Interface ITestInterface
' OK, but not recommended.
Event SomeEvent()

'Properties and methods OK!
Property SomeProperty() As String
Sub SomeMethod(ByVal a As Integer, ByVal b As Integer)
End Interface

•        As a rule, avoid designing interfaces which have more than 6 members.
•        If this is the case, consider refactoring the code into a base and derived interface.
•        This keeps your behaviors clean and more reusable.
•        This rule is found all over the collections namespaces.

•        Always consider interface types immutable entities.
•        Like COM, .NET interfaces should never change once published to other developers.
•        If you do, you will risk breaking code all across the work environment.
•        While this can sometimes be unavoidable during development, never change interfaces on production
applications.  
•        If you need to tweak the definition of a production interface, make use of interface inheritance to
preserve existing contracts.

•        When implementing an interface in a non-sealed base classes, forward to a virtual protected method.
•        In this way, derived classes can change the implementation details if necessary.
•        Using the interface reference, the correct override will be invoked.
// C#
class Person : ICloneable
{
// Method of ICloneable.
public object Clone()
{ OnClone(); }

protected virtual object OnClone()
{
   // Default clone implementation.
}
}

' VB 2005
Class Person
Implements ICloneable

' Method of ICloneable.
Public Function Clone() As Object _
 Implements System.ICloneable.Clone
   OnClone()
End Function

Protected Overridable Function OnClone() As Object
 ' Default clone implementation.
End Function

End Class

•        Make use of explicit interface implementation when:
•        You wish to ensure the functionality can only be invoked from an interface (not an object) reference.
•        You have to resolve a name clash resulting from implementing two or more interfaces which have
identically named members.
// C#
// You can now only call Clone() from an ICloneable
// interface reference, not from a Person object.
class Person : ICloneable
{
protected virtual void OnClone()
{
   // Default clone implementation.
}

object ICloneable.Clone()
{
   OnClone();
}
}

' VB 2005
' You can now only call Clone() from an ICloneable
' interface reference, not from a Person object.
Class Person
Implements ICloneable

Private Function Clone() As Object Implements System.ICloneable.Clone
   OnClone()
End Function

Protected Overridable Function OnClone() As Object

End Function
End Class
Best Practices for Designing Enum Types                                        
•        Always use enums to build custom data types which can take a fixed set of values.
•        Never make use of ‘magic numbers’ in your code.
•        Like interfaces, consider defining all enums in a project within a separate file to reuse them easily across
applications.
•        When an enum is only used to define arguments or return values of a given type member, nest the enum
directly within that type.
•        This enforces a tight association between the types.
•        Furthermore, if the enum is never exposed from the defining type, mark it as a private enum.
// C#
class Car
{
public Car(CarColors color)
{
   currentColor = color;
}

// A car can have these colors.
public enum CarColors
{  Red = 4, Green = 8, Yellow = 12 }

// Expose a Car.CarColor type.
private CarColors currentColor;

public CarColors Color
{
   get { return currentColor; }
   set { currentColor = value; }
}
}


'VB 2005
Class Car
Public Sub New(ByVal color As CarColors)
currentColor = color
End Sub

' A car can have these colors.
Public Enum CarColors
Red = 4
Green = 8
Yellow = 12
End Enum

' Expose a Car.CarColor type.
Private currentColor As CarColors
Public Property Color() As CarColors
Get
 Return currentColor
End Get
Set
 currentColor = value
End Set
End Property
End Class
•        Apply the [Flags] attribute on custom attributes when you wish to allow callers to pipe together a
series of values from a single enum.
•        This ensures that the enum’s ToString() value prints out correctly.

•        For example, assume the following code which makes use of the previous CarColors enum.
•        Specifically note how the output does not account for each of the piped values.
// C#
static void Main(string[] args)
{
Car myCar = new Car(Car.CarColors.Green | Car.CarColors.Red);
Console.WriteLine(myCar.Color.ToString());
}

' VB 2005
Sub Main()
Dim myCar As New Car(Car.CarColors.Green Or Car.CarColors.Red)
Console.WriteLine(myCar.Color.ToString())
End Sub



•        The [Flags] attribute corrects the issue:
•        This will cause the previous Main() logic to print out Yellow.
•        [Red]4 + [Green]8 = [Yellow]12!
// A car can have these colors.
[Flags] public enum CarColors
{
Red = 4, Green = 8, Yellow = 12
}

<Flags()> Public Enum CarColors
Red = 4
Green = 8
Yellow = 12
End Enum
•        Don’t design enums with ‘reserved fields’.
•        This is an old C++ / COM hack which allows an enum to add more values over time.
•        In the world of .NET, enum values are hard-coded in the CIL.  Thus, if you wish to add new name-
value pairs to an existing enum, the older assemblies will not have a record of them.
•        In a nutshell, added new members to an enum (but not removing or reassigning values) is safe across
builds.

•        Don’t assign negative values to members of an enum.
•        This causes unexpected results when combining values with a bitwise-OR operator.
•        If you wish to define an enum that has an undefined state, consider adding a value of None set to zero.
•        Finally, when building bit-coded enums, combine values from existing members for increased type-
safety.
•        In this way, when values change, they have the least amount of impact.
// A car can have these colors.
[Flags] public enum CarColors
{
None = 0, Red = 4, Green = 8, Yellow = Red | Green
}

<Flags()> Public Enum CarColors
None = 0
Red = 4
Green = 8
Yellow = Red Or Green
End Enum
Interface Types and Enums
Table of Contents
Copyright (c) 2008.  Intertech, Inc. All Rights Reserved.  This information is to be used exclusively as an
online learning aid.  Any attempts to copy, reproduce, or use for training is strictly prohibited.
Courseware
Training Resources
Tutorials