Já existem várias boas respostas que explicam o aviso e o motivo. Vários desses afirmam algo como ter um campo estático em um tipo genérico geralmente um erro .
Pensei em acrescentar um exemplo de como esse recurso pode ser útil, ou seja, um caso em que suprimir o aviso R # faz sentido.
Imagine que você tem um conjunto de classes de entidade que deseja serializar, digamos em Xml. Você pode criar um serializador para isso usando new XmlSerializerFactory().CreateSerializer(typeof(SomeClass))
, mas precisará criar um serializador separado para cada tipo. Usando genéricos, você pode substituir isso pelo seguinte, que pode ser inserido em uma classe genérica da qual as entidades podem derivar:
new XmlSerializerFactory().CreateSerializer(typeof(T))
Como você provavelmente não deseja gerar um novo serializador sempre que precisar serializar uma instância de um tipo específico, você pode adicionar o seguinte:
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);
}
}
Se essa classe NÃO fosse genérica, cada instância da classe usaria a mesma _typeSpecificSerializer
.
Porém, como é genérico, um conjunto de instâncias do mesmo tipo T
compartilhará uma única instância de _typeSpecificSerializer
(que será criada para esse tipo específico), enquanto instâncias com um tipo diferente de T
usarão instâncias diferentes de _typeSpecificSerializer
.
Um exemplo
Forneceu as duas classes que se estendem 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; }
}
... vamos usá-los:
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();
Nesse caso, sob o capô, firstInst
e secondInst
haverá instâncias da mesma classe (a saber SerializableEntity<MyFirstEntity>
) e, como tal, eles compartilharão uma instância de _typeSpecificSerializer
.
thirdInst
e fourthInst
são exemplos de uma classe diferente ( SerializableEntity<OtherEntity>
), e por isso irão partilhar um exemplo de _typeSpecificSerializer
que é diferente das outras duas.
Isso significa que você obter diferentes serializador-instances para cada um de seus entidade tipos , mantendo-los estáticos dentro do contexto de cada tipo real (ou seja, compartilhada entre os casos que são de um tipo específico).