There are several good answers here already, that explain the warning and the reason for it. Several of these state something like having a static field in a generic type generally a mistake.
I thought I'd add an example of how this feature can be useful, i.e. a case where suppressing the R#-warning makes sense.
Imagine you have a set of entity-classes that you want to serialize, say to Xml. You can create a serializer for this using new XmlSerializerFactory().CreateSerializer(typeof(SomeClass))
, but then you will have to create a separate serializer for each type. Using generics, you can replace that with the following, which you can place in a generic class that entities can derive from:
new XmlSerializerFactory().CreateSerializer(typeof(T))
Since your probably don't want to generate a new serializer each time you need to serialize an instance of a particular type, you might add this:
public class SerializableEntity<T>
{
// ReSharper disable once StaticMemberInGenericType
private static XmlSerializer _typeSpecificSerializer;
private static XmlSerializer TypeSpecificSerializer
{
get
{
// Only create an instance the first time. In practice,
// that will mean once for each variation of T that is used,
// as each will cause a new class to be created.
if ((_typeSpecificSerializer == null))
{
_typeSpecificSerializer =
new XmlSerializerFactory().CreateSerializer(typeof(T));
}
return _typeSpecificSerializer;
}
}
public virtual string Serialize()
{
// .... prepare for serializing...
// Access _typeSpecificSerializer via the property,
// and call the Serialize method, which depends on
// the specific type T of "this":
TypeSpecificSerializer.Serialize(xmlWriter, this);
}
}
If this class was NOT generic, then each instance of the class would use the same _typeSpecificSerializer
.
Since it IS generic however, a set of instances with the same type for T
will share a single instance of _typeSpecificSerializer
(which will have been created for that specific type), while instances with a different type for T
will use different instances of _typeSpecificSerializer
.
An example
Provided the two classes that extend SerializableEntity<T>
:
// Note that T is MyFirstEntity
public class MyFirstEntity : SerializableEntity<MyFirstEntity>
{
public string SomeValue { get; set; }
}
// Note that T is OtherEntity
public class OtherEntity : SerializableEntity<OtherEntity >
{
public int OtherValue { get; set; }
}
... let's use them:
var firstInst = new MyFirstEntity{ SomeValue = "Foo" };
var secondInst = new MyFirstEntity{ SomeValue = "Bar" };
var thirdInst = new OtherEntity { OtherValue = 123 };
var fourthInst = new OtherEntity { OtherValue = 456 };
var xmlData1 = firstInst.Serialize();
var xmlData2 = secondInst.Serialize();
var xmlData3 = thirdInst.Serialize();
var xmlData4 = fourthInst.Serialize();
In this case, under the hood, firstInst
and secondInst
will be instances of the same class (namely SerializableEntity<MyFirstEntity>
), and as such, they will share an instance of _typeSpecificSerializer
.
thirdInst
and fourthInst
are instances of a different class (SerializableEntity<OtherEntity>
), and so will share an instance of _typeSpecificSerializer
that is different from the other two.
This means you get different serializer-instances for each of your entity types, while still keeping them static within the context of each actual type (i.e., shared among instances that are of a specific type).