== Why is this an issue?

A static field in a generic type is not shared among instances of different closed constructed types, thus ``++LengthLimitedSingletonCollection<int>.instances++`` and ``++LengthLimitedSingletonCollection<string>.instances++`` will point to different objects, even though ``++instances++`` is seemingly shared among all ``++LengthLimitedSingletonCollection<>++`` generic classes.


If you need to have a static field shared among instances with different generic arguments, define a non-generic base class to store your static members, then set your generic type to inherit from the base class.


=== Noncompliant code example

[source,csharp]
----
public class LengthLimitedSingletonCollection<T> where T : new() 
{
  protected const int MaxAllowedLength = 5;
  protected static Dictionary<Type, object> instances = new Dictionary<Type, object>(); // Noncompliant

  public static T GetInstance() 
  {
    object instance;

    if (!instances.TryGetValue(typeof(T), out instance)) 
    {
      if (instances.Count >= MaxAllowedLength) 
      {
        throw new Exception();
      }
      instance = new T();
      instances.Add(typeof(T), instance);
    }
    return (T)instance;
  }
}
----


=== Compliant solution

[source,csharp]
----
public class SingletonCollectionBase 
{
  protected static Dictionary<Type, object> instances = new Dictionary<Type, object>(); 
}

public class LengthLimitedSingletonCollection<T> : SingletonCollectionBase where T : new()
{
  protected const int MaxAllowedLength = 5;

  public static T GetInstance() 
  {
    object instance;

    if (!instances.TryGetValue(typeof(T), out instance)) 
    {
      if (instances.Count >= MaxAllowedLength) 
      {
        throw new Exception();
      }
      instance = new T();
      instances.Add(typeof(T), instance);
    }
    return (T)instance;
  }
}
----


=== Exceptions

If the static field or property uses a type parameter, then the developer is assumed to understand that the static member is not shared among the closed constructed types.

[source,csharp]
----
public class Cache<T> 
{
   private static Dictionary<string, T> CacheDictionary { get; set; } // Compliant
}
----


ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

A static field in a generic type is not shared among instances of different close constructed types.


'''
== Comments And Links
(visible only on this page)

=== on 20 Mar 2015, 13:07:59 Tamas Vajk wrote:
This is the first draft of this rule, I don't know which properties need to be set. (SQALE, tags, ...)

=== on 20 Mar 2015, 13:21:20 Ann Campbell wrote:
\[~tamas.vajk] if you'll expand the description to include the reasons (bad thing that will happen if you break the rule or good thing that will happen if you follow it) that will help me with filling in the other fields.

=== on 10 Apr 2015, 08:09:30 Tamas Vajk wrote:
Ann, I've added an exception to this rule, could you please check it?

Thanks

=== on 10 Apr 2015, 12:10:12 Ann Campbell wrote:
The exception looks fine, but I think it would be helpful if you added a small code sample. 

You can use a "// Compliant" or "// Ignored" comment to mark the line that's being ignored.

=== on 13 Apr 2015, 12:50:55 Tamas Vajk wrote:
\[~ann.campbell.2]: [~dinesh.bolkensteyn] asked for a more meaningful example, so I updated the description. 

=== on 11 May 2015, 12:11:49 Tamas Vajk wrote:
Added the code sample as well to the Exception

=== on 11 May 2015, 14:03:33 Ann Campbell wrote:
thanks [~tamas.vajk]

endif::env-github,rspecator-view[]
